元数据的使用
1)想取得对数据库相关信息的描述,可以元数据
2)DatabaseMetaData/DatabaseMetaData dbmd =conn.getMetaData()
3)ParameterMetaData/ParameterMetaData psmd =pstmt.getParameterMetaData();
4)ResultSetMetaData/ResultSetMetaData rsmd =rs.getMetaData();
l 元数据:数据库、表、列的定义信息。
l Connection.getDatabaseMetaData()
l DataBaseMetaData对象
• getURL():返回一个String类对象,代表数据库的URL。
• getUserName():返回连接当前数据库管理系统的用户名。
• getDatabaseProductName():返回数据库的产品名称。
• getDatabaseProductVersion():返回数据库的版本号。
• getDriverName():返回驱动驱动程序的名称。
• getDriverVersion():返回驱动程序的版本号。
• isReadOnly():返回一个boolean值,指示数据库是否只允许读操作。
l PreparedStatement.getParameterMetaData()
• 获得代表PreparedStatement元数据的ParameterMetaData对象。
l ParameterMetaData对象
• getParameterCount()
l 获得指定参数的个数
l ResultSet.getMetaData()
• 获得代表ResultSet对象元数据的ResultSetMetaData对象。
l ResultSetMetaData对象
• getColumnCount()
• 返回resultset对象的列数
• getColumnName(int column)
• 获得指定列的名称
• getColumnTypeName(int column)
• 获得指定列的类型(Types类)
l 业务背景:系统中所有实体对象都涉及到基本的CRUD操作:
• 所有实体的CUD操作代码基本相同,仅仅发送给数据库的SQL语句不同而已,因此可以把CUD操作的所有相同代码抽取到工具类的一个update方法中,并定义参数接收变化的SQL语句。
使用到的数据表:
reatetable if notexistsuser(
id intprimarykey auto_increment,
username varchar(20) notnull,
password varchar(6) notnull,
birthday datenotnull,
salary float
);
元数据实现代码:
c3p0配置文件:
<?xml version="1.0"encoding="UTF-8"?>
<c3p0-config>
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="user">root</property>
<property name="password">root</property>
<property name="jdbcUrl">jdbc:mysql://127.0.0.1:3306/mydb2</property>
</default-config>
</c3p0-config>
jdbc工具类
package cn.itcast.web.jdbc.util;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
importcom.mchange.v2.c3p0.ComboPooledDataSource;
//JDBC工具类:关闭流和取得连接
public final class JdbcUtil {
privatestatic ComboPooledDataSource dataSource;
static{
dataSource= new ComboPooledDataSource();
}
//取得数据源
publicstatic ComboPooledDataSource getDataSource() {
returndataSource;
}
//取得连接
publicstatic Connection getMySqlConnection() throws SQLException{
return dataSource.getConnection();
}
//关闭连接
publicstatic void close(Connection conn) throws SQLException{
if(conn!=null){
conn.close();
}
}
publicstatic void close(PreparedStatement pstmt) throws SQLException {
if(pstmt!=null){
pstmt.close();
}
}
publicstatic void close(ResultSet rs) throws SQLException {
if(rs!=null){
rs.close();
}
}
}
元数据的三种用法:
//演示三种元数据库的用法
publicclass Demo1 {
publicstaticvoid main(String[] args) throws Exception {
Connection conn = JdbcUtil.getMySqlConnection();
String sql = "select *from user";
PreparedStatement pstmt = conn.prepareStatement(sql);
ResultSet rs = pstmt.executeQuery();
//取得结果集的相关元数据
ResultSetMetaData rsmd = rs.getMetaData();
int size = rsmd.getColumnCount();
for(int i=0;i<size;i++){
//取得每列的列名
String columnName = rsmd.getColumnName(i+1);
//取得每列的类型
int typeCode = rsmd.getColumnType(i+1);
System.out.println(columnName+":"+typeCode);
}
/*取是有关SQL的相关元数据
String sql = "insert into user(username,password,birthday,salary)values(?,?,?,?)";
ParameterMetaData psmd = pstmt.getParameterMetaData();
int size = psmd.getParameterCount();
System.out.println("共有" + size+"个参数");
*/
//取得DataBaseMetaData
DatabaseMetaData dbmd = conn.getMetaData();
String driver = dbmd.getDriverName();//驱动名
String url = dbmd.getURL();//连接url
int level = dbmd.getDefaultTransactionIsolation();//事务隔离级别
String productName = dbmd.getDatabaseProductName();//产品名称
boolean flag = dbmd.isReadOnly();//是否只读
System.out.println("flag="+flag);
System.out.println("driver="+driver);
System.out.println("url="+url);
System.out.println("level="+level);
System.out.println("productName="+productName);
}
使用元数据进行CURD操作
/使用元数据+反射优化CURD操作
publicclass Demo2 {
publicstaticvoid main(String[] args) throws Exception {
/*
* 插入
String sql = "insert into user(username,password,birthday,salary)values(?,?,?,?)";
Object[] params = {"sisi","000000","2011-10-28",5000};
update(sql, params);
*/
/*
* 更新
String sql = "update user set username=?where username=?";
Object[] params = {"shashan","sisi"};
update(sql, params);
*/
/*
//删除
String sql = "delete from user where id = ?";
update(sql,new Object[]{2});
*/
/*
* 查询
String sql = "select * from user where id =?";
User user = (User) query(sql,newObject[]{1},User.class);
System.out.println("用户名:" + user.getUsername());
System.out.println("密码:" + user.getPassword());
System.out.println("生日:" + user.getBirthday().toLocaleString());
System.out.println("薪水:" + user.getSalary());
*/
}
//R操作(通用的方法)
publicstatic Object query(String sql,Object[] params,Classclazz) throws Exception {
Object obj = clazz.newInstance();
Connection conn = JdbcUtil.getMySqlConnection();
PreparedStatement pstmt = conn.prepareStatement(sql);
ParameterMetaData psmd = pstmt.getParameterMetaData();
int size = psmd.getParameterCount();
for(int i=0;i<size;i++){
pstmt.setObject(i+1,params[i]);
}
ResultSet rs = pstmt.executeQuery();
if(rs.next()){
//取得结果集元数据
ResultSetMetaData rsmd = rs.getMetaData();
//取得结果集列数目
size = rsmd.getColumnCount();
//以列值为单位,设置到JavaBean中去
for(int i=0;i<size;i++){
//取得列名
String columnName = rsmd.getColumnName(i+1);
//通过BeanUtils框架为JavaBean设置值
BeanUtils.setProperty(obj,columnName,rs.getObject(i+1));
}
}
JdbcUtil.close(rs);
JdbcUtil.close(pstmt);
JdbcUtil.close(conn);
return obj;
}
//CUD操作(通用的方法)
publicstaticvoid update(String sql,Object[] params) throws SQLException {
Connection conn = JdbcUtil.getMySqlConnection();
PreparedStatement pstmt = conn.prepareStatement(sql);
//取得参数元数据
ParameterMetaData psmd = pstmt.getParameterMetaData();
//取得参数的个数
int size = psmd.getParameterCount();
//循环绑定对象的值
for(int i=0;i<size;i++){
pstmt.setObject(i+1,params[i]);
}
//执行
pstmt.executeUpdate();
//关闭对应的连接对象
JdbcUtil.close(conn);
JdbcUtil.close(pstmt);
}
}
l commons-dbutils 是 Apache 组织提供的一个开源 JDBC工具类库,它是对JDBC的简单封装,学习成本极低,并且使用dbutils能极大简化jdbc编码的工作量,同时也不会影响程序的性能。因此dbutils成为很多不喜欢hibernate的公司的首选。
l API介绍:
• org.apache.commons.dbutils.QueryRunner(类)
• org.apache.commons.dbutils.ResultSetHandler(接口)
• 工具类
• org.apache.commons.dbutils.DbUtils。
QueryRunner类
l 该类简单化了SQL查询,它与ResultSetHandler组合在一起使用可以完成大部分的数据库操作,能够大大减少编码量。
l QueryRunner类提供了两个构造方法:
• 默认的构造方法
• 需要一个 javax.sql.DataSource 来作参数的构造方法。
QueryRunner类的主要方法
l public Object query(Connectionconn, String sql, Object[] params, ResultSetHandler rsh) throws SQLException:执行一个查询操作,在这个查询中,对象数组中的每个元素值被用来作为查询语句的置换参数。该方法会自行处理 PreparedStatement 和 ResultSet 的创建和关闭。
l public Object query(String sql,Object[] params, ResultSetHandler rsh) throws SQLException: 几乎与第一种方法一样;唯一的不同在于它不将数据库连接提供给方法,并且它是从提供给构造方法的数据源(DataSource) 或使用的setDataSource 方法中重新获得 Connection。
l public Object query(Connectionconn, String sql, ResultSetHandler rsh) throws SQLException : 执行一个不需要置换参数的查询操作。
l public int update(Connectionconn, String sql, Object[] params) throws SQLException:用来执行一个更新(插入、更新或删除)操作。
l public int update(Connectionconn, String sql) throws SQLException:用来执行一个不需要置换参数的更新操作。
ResultSetHandler接口
l 该接口用于处理 java.sql.ResultSet,将数据按要求转换为另一种形式。
l ResultSetHandler 接口提供了一个单独的方法:Object handle(java.sql.ResultSet .rs)。
ResultSetHandler接口的实现类
l BeanHandler:将结果集中的第一行数据封装到一个对应的JavaBean实例中。
l BeanListHandler:将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里。
l ArrayHandler:把结果集中的第一行数据转成对象数组。
l ArrayListHandler:把结果集中的每一行数据都转成一个对象数组,再存放到List中。
ResultSetHandler接口的实现类
l MapHandler:将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值。
l MapListHandler:将结果集中的每一行数据都封装到一个Map里,然后再存放到List。
l ScalarHandler:结果集中只有一行一列数据。
DbUtils类
l DbUtils :提供如关闭连接、装载JDBC驱动程序等常规工作的工具类,里面的所有方法都是静态的。主要方法如下:
l public static void close(…)throws java.sql.SQLException: DbUtils类提供了三个重载的关闭方法。这些方法检查所提供的参数是不是NULL,如果不是的话,它们就关闭Connection、Statement和ResultSet。
l public static voidcloseQuietly(…): 这一类方法不仅能在Connection、Statement和ResultSet为NULL情况下避免关闭,还能隐藏一些在程序中抛出的SQLException。
l public static voidcommitAndCloseQuietly(Connection conn):用来提交连接,然后关闭连接,并且在关闭连接时不抛出SQL异常。
l public static booleanloadDriver(java.lang.String driverClassName):这一方装载并注册JDBC驱动程序,如果成功就返回true。使用该方法,你不需要捕捉这个异常ClassNotFoundException。
* DBUtils框架的使用
1)目的:减化CURD操作
2)DBUtils框架最核心的类,就是QueryRunner类,构造其有二种方式
a)空参构造
b)通过DataSource构造
3)DBUtils对象的update()方法,内部已经关闭相关的连接对象
4)update(Connection)方法带有Connection对象的,需要手工关闭,其它对象自动关闭
update()方法无Connection对象的,DBUtils框架自动关闭
5)为什么作者要这样设计?
主要考虑了在分层结构中,需要用到同一个Connection的问题
6)对于query()操作与update()操作有着一致的含义
7)对于query()操作的实现类含义如下;
BeanHandler/BeanListHandler:争对JavaBean
ArrayHandler/ArrayListHandler:争对数组
MapHandler/MapListHandler:争对Map
ScalarHandler:争对Long
DBUTIL
//演示DBUtils框架的使用
publicclass Demo3 {
publicstaticvoid main(String[] args) throws SQLException {
//QueryRunner runner = newQueryRunner(JdbcUtil.getDataSource());
//String sql ="insert into user(username,password,birthday,salary)values(?,?,?,?)";
//String sql ="update user set username=? where username=?";
//String sql ="delete from user where id = ?";
//runner.update(sql,newObject[]{4});
//插入
Connection conn = JdbcUtil.getMySqlConnection();
QueryRunner runner = new QueryRunner();
String sql = "insert intouser(username,password,birthday,salary) values(?,?,?,?)";
runner.update(conn,sql,new Object[]{"tim","111222","2011-10-10",5000});
JdbcUtil.close(conn);
}
}
//演示ResultSetHandler接口的各种实现类的用法
publicclass Demo4 {
@Test
publicvoid testBeanHandler() throws SQLException{
QueryRunner runner = new QueryRunner(JdbcUtil.getDataSource());
String sql = "select *from user";
User user = (User) runner.query(sql,new BeanHandler(User.class));
System.out.println("用户名:" + user.getUsername());
}
@Test
publicvoid testBeanListHandler() throws SQLException{
QueryRunner runner = new QueryRunner(JdbcUtil.getDataSource());
String sql = "select *from user";
List<User> userList = (List<User>)runner.query(sql,new BeanListHandler(User.class));
for(User user : userList){
System.out.println("用户名:" + user.getUsername());
System.out.println("密码:" + user.getPassword());
}
}
@Test
publicvoid testArrayHandler() throws SQLException{
QueryRunner runner = new QueryRunner(JdbcUtil.getDataSource());
String sql = "select *from user";
Object[] array = (Object[]) runner.query(sql,new ArrayHandler());
System.out.println("编号 : " + array[0]);
System.out.println("用户名 : " + array[1]);
}
@Test
publicvoid testArrayListHandler() throws SQLException{
QueryRunner runner = new QueryRunner(JdbcUtil.getDataSource());
String sql = "select *from user";
List<Object[]> list = (List<Object[]>)runner.query(sql,new ArrayListHandler());
for(Object[] array : list){
System.out.print("编号 : " + array[0] + "\t");
System.out.println("用户名 : " + array[1]);
}
}
@Test
publicvoid testMapHandler() throws SQLException{
QueryRunner runner = new QueryRunner(JdbcUtil.getDataSource());
String sql = "select *from user";
Map<Object,Object> map = (Map<Object, Object>)runner.query(sql,new MapHandler());
System.out.println("用户名:" + map.get("username"));
}
@Test
publicvoid testMapListHandler() throws SQLException{
QueryRunner runner = new QueryRunner(JdbcUtil.getDataSource());
String sql = "select *from user";
List<Map<Object,Object>> list = (List<Map<Object,Object>>) runner.query(sql,new MapListHandler());
for(Map<Object,Object> map : list){
System.out.println("用户名:" + map.get("username"));
System.out.println("薪水:" + map.get("salary"));
}
}
@Test
publicvoid testScalarHandler() throws SQLException{
QueryRunner runner = new QueryRunner(JdbcUtil.getDataSource());
String sql = "selectcount(*) from user";
Long sum = (Long) runner.query(sql,new ScalarHandler());
System.out.println("共有" + sum + "人");
}
}