`

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

    博客分类:
  • jdbc
 
阅读更多

 

类似于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简单封装)

 

 

 

分享到:
评论

相关推荐

    自制ORM框架源代码

    1. 注解编程:此框架的核心思想是利用JDK 6.0引入的注解特性,为类和字段添加特定的元数据,这些元数据在运行时被解析,用以驱动程序行为。例如,`@TableAnnotation`用于标记实体类与数据库表的对应关系,而`@...

    SSM框架实体类生成器Generator-Oracle版

    它利用Oracle数据库的元数据信息,自动生成与数据库表对应的Java实体类,大大减少了手动编写这些基础代码的时间。通过这个工具,开发者可以快速地将数据库中的表结构转化为可直接使用的业务模型,从而集中精力处理更...

    orm框架的底层实现机制共.pdf

    ORM(Object-Relational Mapping,对象关系映射)框架是一种技术,它允许程序员使用面向对象的方式来操作数据库,而无需直接编写SQL语句。ORM框架的主要目的是解决编程语言(特别是面向对象语言)和关系型数据库之间...

    base-core.rar

    它可能通过读取数据库元数据来生成SQL映射文件,并根据实体类自动生成对应的Mapper接口。开发者只需要提供数据库连接信息,工具就能自动完成大部分配置工作,大大提高了开发效率。 此类工具的实现原理可能包括以下...

    hibernate培训

    - Hibernate是一个强大的O/R Mapping框架,提供了对象到数据库表的映射以及查询功能。 - Hibernate的优势还包括其自定义API和广泛的社区支持。 4. **Hibernate开发步骤**: - 设计持久化类:根据业务需求创建...

    hibernate教程

    - **元数据生成**:使用 XDoclet 工具自动生成实体类和映射文件中的注解或 XML 元数据。 #### 五、基本 O/R 映射 ##### 5.1 映射声明 - **文档类型**:映射文件的文档类型声明。 - **根元素**:`hibernate-mapping`...

    hibernate_src.zip

    Hibernate是一个开源的ORM(Object-Relational Mapping)框架,它通过提供一种对象-关系映射机制,实现了Java对象与数据库表之间的映射,从而避免了传统的JDBC繁琐的SQL操作。Hibernate的核心理念是“对象-关系”...

    J2EE企业级项目开发-3期(KC007) 6.1 ORM和MyBatis考试.doc

    4. **元数据工具**:元数据通常以XML或注解的形式描述对象和数据库表之间的映射关系,ORM框架使用这些元数据来生成和执行SQL语句。 5. **事务管理和优化操作**:ORM框架还负责事务管理,确保数据的一致性。它可能...

    hibernate中文官方文档3.6

    #### 五、对象/关系数据库映射基础(Basic O/R Mapping) 这部分深入探讨了对象/关系映射的基础知识,包括: - **映射定义**:介绍如何定义实体类与数据库表之间的映射关系。 - **Entity**:解释实体类的概念及其在...

    Hiernate课件

    简而言之,它通过元数据描述对象和数据库之间的映射关系,从而实现Java对象到数据库记录的自动转换。 - **目的**:简化数据库操作,让开发者更专注于业务逻辑而不是底层的数据存储细节。 **2.2 ORM的视角** - **...

    系统java学习

    - **ORM技术**:理解对象关系映射(Object-Relational Mapping)的基本概念。 - **Hibernate框架搭建**:配置并初始化Hibernate框架。 - **工作原理**:深入了解Hibernate如何实现ORM。 - **源码分析**:分析...

    手写myHibernate的代码(可以直接使用)

    在这个自定义的myHibernate中,我们可能需要创建一个XML文件,如`User.hbm.xml`,其中包含关于`User`表的元数据。 4. **数据访问层(DAO)**:这是myHibernate的核心部分,负责与数据库进行交互。我们需要编写一...

    hibernate基本配置及使用方法

    ### 一、对象关系映射(O/R Mapping) 1. **O/R Mapping是什么?** 对象关系映射是将Java应用程序中的对象模型与关系数据库中的表结构之间进行映射的技术。通过元数据(metadata),Hibernate可以自动处理对象的...

    ibatis框架源代码

    Ibatis,全称为“SQL Maps”,是一个开源的Java持久层框架,它允许程序员将SQL查询映射到Java对象,从而避免了对JDBC的直接操作。这个框架的主要优点在于它简化了数据库操作,使得开发者能够更专注于业务逻辑,而...

    数据库实体类代码生成

    - **获取元数据**:工具首先需要连接到数据库,通过JDBC(Java Database Connectivity)获取表的结构信息,包括表名、字段名、数据类型等。 - **模板引擎**:然后,工具会使用模板引擎(如FreeMarker或Velocity)...

    hibernate-reference

    - **动态模型**:介绍如何创建和使用动态的映射元数据,以适应灵活的数据模型。 - **Tuplizer使用**:探讨高级主题,如自定义Tuplizer,用于更复杂的查询结果转换。 ##### 7. **基本ORM映射** - **映射声明**:...

Global site tag (gtag.js) - Google Analytics