jdbc元数据_自定义O-R Mapping映射框架

类似于javase的反射

0 元数据概念:

a) 数据的定义数据

b) 数据库,表,列等信息也是一种对象,他们也是由最基础的数据组建而成,基础组件就叫做元数据。

1 数据库元数据: DataBaseMetaData

a) 获取方式: connection.getMetaData();

b) 常用方法说明:

getURL() 返回一个String类对象,代表数据库的URL。
getUserName() 返回连接当前数据库管理系统的用户名。
getDatabaseProductName() 返回数据库的产品名称。
getDatabaseProductVersion() 返回数据库的版本号
getDriverName() 返回驱动驱动程序的名称
getDriverVersion() 返回驱动程序的版本号
isReadOnly() 返回一个boolean值,指示数据库是否只允许读操作

代码如下:

public static void main(String[] args) {

		try {
			Connection  conn = JdbcUtils.getConnection();
			DatabaseMetaData dbmetadata = conn.getMetaData();
			String url = dbmetadata.getURL();
			String username = dbmetadata.getUserName();
			String dbProName = dbmetadata.getDatabaseProductName();
			String dbProVersion = dbmetadata.getDatabaseProductVersion();
			String driverName = dbmetadata.getDriverName();
			String diriverVersion = dbmetadata.getDriverVersion();
			boolean readonly = dbmetadata.isReadOnly();
			System.out.println("url: " + url);
			System.out.println("username: " + username);
			System.out.println("dbProName: " + dbProName);
			System.out.println("dbProVersion: " + dbProVersion);
			System.out.println("driverName: " + driverName);
			System.out.println("diriverVersion: " + diriverVersion);
			System.out.println("readonly: " + readonly);
			
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}


结果:
url: jdbc:mysql://localhost:3306/jdbc
username: root@localhost
dbProName: MySQL
dbProVersion: 5.0.96-community-nt
driverName: MySQL-AB JDBC Driver
diriverVersion: mysql-connector-java-5.0.8 ( Revision: ${svn.Revision} )
readonly: false

2 参数元数据:

a) 获取方式: preparedStatement.getParameterMetaData();

b) 常用方法说明:

getParameterCount() 获得指定参数的个数
getParameterType(int param) 获得指定参数的sql类型

代码如下:

   // 参数元数据
   public static void test1(){
	Connection conn = null;
	PreparedStatement st = null;
	ResultSet rs = null;
	try {
		conn = JdbcUtils.getConnection();
		String sql = "select * from account where id=? and name=?";
		st = conn.prepareStatement(sql);
		ParameterMetaData meta = st.getParameterMetaData();
		System.out.println(meta.getParameterCount());
		
		//int i = meta.getParameterType(1);  // 1 数据类型都放在 Types, in java.sql.Types中,用整数表示 2 mysql驱动对此方法支持不利 方法执行不了
		System.out.println(i);
		
		
	}catch(Exception e){
		e.printStackTrace();
	}
	finally {
		JdbcUtils.release(rs, st, conn);
	}
   }

结果:
2

3 结果集元数据:

a) 获取方式:resultSet.getMetaData();

b) 常用方法说明:

getColumnCount() 返回resultset对象的列数
getColumnName(int column) 获得指定列的名称
getColumnTypeName(int column) 获得指定列的类型

代码如下:

 // 结果集元数据
   public static void test2(){
		Connection conn = null;
		PreparedStatement st = null;
		ResultSet rs = null;
		try {
			conn = JdbcUtils.getConnection();
			String sql = "select * from user";
			st = conn.prepareStatement(sql);
			rs = st.executeQuery();
			
			ResultSetMetaData  meta = rs.getMetaData();
			System.out.println(meta.getColumnCount());
			System.out.println(meta.getColumnName(2)); // 参数角标从1开始
			
		}catch(Exception e){
			e.printStackTrace();
		}
		finally {
			JdbcUtils.release(rs, st, conn);
		}
	}


结果为: 
5
name

4 自定义o-r mapping映射框架实现dml:

a) 所有实体的CUD操作代码基本相同,仅仅发送给数据库的SQL语句不同而已,因此可以把CUD操作的所有相同代码抽取到工具类的一个update方法中,并定义参数接收变化的SQL语句。

b) 实体的R操作,除SQL语句不同之外,根据操作的实体不同,对ResultSet的映射也各不相同,因此可义一个query方法,除以参数形式接收变化的SQL语句外,可以使用策略模式由qurey方法的调用者决定如何把ResultSet中的数据映射到实体对象中。

c) 在查询中,因为使用到反射,因此表中属性要和javabean属性保持一致(大小写),否则映射不过去报java.lang.NoSuchFieldException

代码如下:

自定义o-r mappping dml写法:

interface ResultSetHandler{
	public Object handler(ResultSet rs);
}

/**
 * 把查询结果封装到bean中
 * public Customer find(int id) throws SQLException {
		String sql = "select id,name,sex,birthday,cellphone,email,preference,type,description from customer where id=?";
		Object params[] = {id};
		return (Customer) JdbcUtils.query(sql, params, new BeanHandler(Customer.class));
	}
 * 
 */
class BeanHandler implements ResultSetHandler{

	// 封装到实际对象的类型
	private Class clazz;
	public BeanHandler(Class clazz){
		this.clazz = clazz;
	}
	// javabean数据封装
	public Object handler(ResultSet rs) {
		try{
			Object obj = clazz.newInstance();
			if(!rs.next()){
				return null;
			}
			ResultSetMetaData meta = rs.getMetaData();
			int count =  meta.getColumnCount();
			for(int i=0;i<count;i++){
				// 得到每一列 的名称和值
				String columnName = meta.getColumnName(i+1);
				Object value = rs.getObject(i+1);
				// 通过反射得到 每一列列名 区域,然后在把值给设置进来
				Field f = clazz.getDeclaredField(columnName);
				f.setAccessible(true);
				f.set(obj, value);
			}
			return obj;
		
		
		}catch(Exception e){
			throw new RuntimeException(e);
		}
	}
}


/**
 * 把查询结果封装到集合中
 * public List getAll() throws SQLException{
		String sql = "select * from customer";
		Object params[] = {};
		return (List) JdbcUtils.query(sql, params, new ListBeanHandler(Customer.class));
	}
 */
class ListBeanHandler implements ResultSetHandler{

	private Class clazz;
	public ListBeanHandler(Class clazz){
		this.clazz = clazz;
	}
	
	public Object handler(ResultSet rs) {
		
		try{
			if(rs==null){
				return null;
			}
			ResultSetMetaData meta = rs.getMetaData();
			int count = meta.getColumnCount();
			List list = new ArrayList();
			while(rs.next()){
				Object obj = clazz.newInstance();
				for(int i=0;i<count;i++){
					String columnName = meta.getColumnName(i+1);
					Object value = rs.getObject(i+1);
					
					Field f = clazz.getDeclaredField(columnName);
					f.setAccessible(true);
					f.set(obj, value);
				}
				list.add(obj);
			}
			
			return list;
			
		}catch(Exception e){
			throw new RuntimeException(e);
		}
	}
	
}





public class JdbcUtils {
	
	/*private static String driver = "com.mysql.jdbc.Driver";
	private static String url = "jdbc:mysql://localhost:3306/jdbc2";
	private static String username = "root";
	private static String password = "root";*/
	
	/*
	private static String driver = "oracle.jdbc.driver.OracleDriver";
	private static String url = "jdbc:oracle:thin:@localhost:1521:orcl";
	private static String username = "scott";
	private static String password = "tiger";*/
	
	private static String driver = null;
	private static String url = null;
	private static String username = null;
	private static String password = null;
	
	static{
		try {
			
			InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("bj/util/db.properties");
			Properties prop = new Properties();
			prop.load(in);
			
			driver = prop.getProperty("driver");
			url = prop.getProperty("url");
			username = prop.getProperty("username");
			password = prop.getProperty("password");
			
			Class.forName(driver);
		} catch (Exception e) {
			throw new ExceptionInInitializerError(e);
		}
	}
	
	public static Connection getConnection() throws SQLException{
		return DriverManager.getConnection(url,username,password);
	}
	
	public static void release(ResultSet rs,Statement st,Connection conn){
		
		if(rs!=null)
		{
			try{
				rs.close();
			}catch(Exception e){
				e.printStackTrace();
			}
			rs = null;
		}
		if(st!=null)
		{
			try{
				st.close();
			}catch(Exception e){
				e.printStackTrace();
			}
			st = null;
		}
		if(conn!=null){
			try{
				conn.close();
			}catch(Exception e){
				e.printStackTrace();
			}
			conn = null;
		}
		
		
	}
	
	
	/*
	 * DBUtils工具类的 增删改 原理代码 
	 * 用Object数组接受传递参数的个数和类型
	 */
	public static void update(String sql,Object params[]) throws SQLException{
		
		Connection conn = null;
		PreparedStatement st = null;
		ResultSet rs = null; 
		try{
			conn = JdbcUtils.getConnection();
			st = conn.prepareStatement(sql);
			for(int i=0;i<params.length;i++){
				st.setObject(i+1, params[i]);// 给参数赋值时,PreparedStatement角标从1开始,因此第一个参数为i+1
			}
			st.executeUpdate();
		}finally{
			JdbcUtils.release(rs, st, conn);
		}
	}
	
	/*
	 * 策略模式:1 在查询到数据后,让方法的调用者来处理 获取db数据和映射实体之间转换工作, 2 定义公共接口约定调用者实现细则时要遵守的细则
	 * DBUtils工具类的 查询 原理代码 
	 */
	public static Object query(String sql,Object params[],ResultSetHandler rh) throws SQLException{
		Connection conn = null;
		PreparedStatement st = null;
		ResultSet rs = null;
		try{
			conn = JdbcUtils.getConnection();
			st = conn.prepareStatement(sql);
			for(int i=0;i<params.length;i++){
				st.setObject(i+1,params[i]);
			}
			rs = st.executeQuery();
			// 交给调用者传递的处理类将db返回结果和业务实体bean封装
			return rh.handler(rs);
		}finally{
			JdbcUtils.release(rs, st, conn);
		}
	}
	
	
}

5 常用O-R Mapping映射工具


a) Hibernate:现在用的少了
b) Ibatis: 现在一般用的是 mybatis
c) Commons DbUtils(只是对JDBC简单封装)

猜你喜欢

转载自chengjianxiaoxue.iteye.com/blog/2078839