hibernate之模拟Hibernate持久化操作

简介:

【Hibernate】之模拟Hibernate持久化操作


 使用过Hibernate,大家都知道,由于其面向对象的设计,用起来非常方便,且具有很好的跨数据库性,那么Hibernate的底层是怎么实现的呢?其实也就是将对象模型转化为关系模型,最终还是得sql语句来执行。 

 看过Hibernate源码的同学应该发现, Hibernate底层的核心是代理和反射,那么由此这样我们就可以理解为什么使用Hibernate在效率上始终是致命的。

 

 Ok,下面是一个简单的模拟Hibernate-ORMsave()方法,来管中窥豹,略了解一下Hibernate的底层实现。其中这里我主要演示Hibernate是如何使用反射获取数据,类型等,到这里不得不提,广大Java从业者,想在Java技术道路上有所突破,Java的反射机制,是必须掌握的。

 

首先模拟出新建一个Session实体类,模拟一个save()方法

为了方便,我这边就不写配置文件了,如果各位想写,可以参考Hibernate


1
2
3
Configuration cfg= new  Configuration();
cfg.configure();
sessionFactory=cfg.buildSessionFactory();

Hiberane的源码导进去,自己看一下它如何利用dom4j解析实现的。


首先创建一个实体类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package  csg.hibernate.entity;
/**
 
  * @author Caesar.hu
  * @Date  2014-11-28
  * @Time  上午09:32:08
  * @TODO
  */
public  class  Student {
     private  Integer id;
     private  String name;
     private  Integer age;
     public  Integer getId() {
         return  id;
     }
     public  void  setId(Integer id) {
         this .id = id;
     }
     public  String getName() {
         return  name;
     }
     public  void  setName(String name) {
         this .name = name;
     }
     public  Integer getAge() {
         return  age;
     }
     public  void  setAge(Integer age) {
         this .age = age;
     }
     
 
}


看代码:然后我们模拟一个Session类,里面构造一个save()方法,

下面这段代码,就是核心,每行代码的注释已经写清楚

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package  csg.hibernate.entity;
 
import  java.lang.reflect.Method;
import  java.sql.Connection;
import  java.sql.DriverManager;
import  java.sql.PreparedStatement;
import  java.util.HashMap;
import  java.util.Map;
 
/**
 
  * @author Caesar.hu
  * @Date 2014-11-27
  * @Time 下午06:02:05
  * @TODO模拟一个Session
  */
public  class  Session {
     // 1、写好一个表名,这个表名,理论上应该在Student.hbm.xml中读出来,或者是注解JPA映射
     // 我这里直接写出来,意思就是说,数据存到数据库的表对应的就是这个
     String tableName =  "_student" ;
     // 2、为什么创建一个String类型的Map?
     // 这个map存放的就是实体的字段属性和数据库字段匹配,本身也是配置在文件中
     Map<String, String> cfs =  new  HashMap<String, String>();
     String[] methodNames; // new一个空集合主要是方便反射使用
 
     public  Session() {
         cfs.put( "_id" "id" );
         cfs.put( "_name" "name" );
         cfs.put( "_age" "age" );
         methodNames =  new  String[cfs.size()];
     }
 
     public  void  save(Student s)  throws  Exception {
         // 3、创建SQL语句
         String sql = createSQL();
         String url =  "jdbc:mysql://localhost/hibernate" ;
         String username =  "root" ;
         String password =  "root" ;
         Class.forName( "com.mysql.jdbc.Driver" );
         Connection conn = DriverManager.getConnection(url, username, password);
         PreparedStatement ps = conn.prepareStatement(sql);
         // 9,sql写好之后,这里是是不是需要设置?
         // 类似ps.setName(1,s.getId);
         // ps.setInterge(2,s.getAge)
         //怎么设置?你怎么知道传进来的是什么类型呢?所以这里最重要的是需要用到反射类型
         for  ( int  i =  0 ; i < methodNames.length; i++) {
             System.out.println(methodNames[i]); // 首先取到存进到数据中的getAge getInt
             //10、 通过反射机制根据实体的方法反射出实体一系列的方法getAge,getName,getId和返回类型Integer,String,Integer
             Method m = s.getClass().getMethod(methodNames[i]);
             System.out.println(m);
             System.out.println(s.getClass() +  "-------"  + m +  "---------"
                     + m.getName() +  "-----"  + m.getReturnType());
             //11、获取数组里面getAge,getInt,getName 的返回类型
             Class r = m.getReturnType();
             //12、根据返回类型判断其应该ps.setString,还是ps.setInteger
             if  (r.getName().equals( "java.lang.String" )) {
                 //13、invoke是反射里面的一个方法,其作用是通过类的返回值类型反射出属性值
                 //14、getAge.invoke(s);同样也可以通过值反射出返回类型
                 String returnValue = (String) m.invoke(s);
                 System.out.println(returnValue);
                 ps.setString(i +  1 , returnValue);
             }
             //15、同样如果判断是Integer类型,就ps.setInteger
             if  (r.getName().equals( "java.lang.Integer" )) {
                 System.out.println(m.invoke(s));
                 Integer returnValue = (Integer) m.invoke(s);
                 // System.out.println(returnValue);
                 ps.setInt(i +  1 , returnValue);
             }
         }
         // ps.executeUpdate();
         ps.close();
         conn.close();
     }
 
     private  String createSQL() {
         String str1 =  "" ;
         int  index =  0 ;
         for  (String s : cfs.keySet()) {
             // 4、通过Map中的key得到Value
             String v = cfs.get(s);
             // 5、根据get,set方法我们可以知道字段首字母是需要大写的,
             // 6、这段代码就是将取出来的value首字母大写加上get
             v = Character.toUpperCase(v.charAt( 0 )) + v.substring( 1 );
             // 7、这样new出来的空集合里面就放上了getId,getName,getAge
             methodNames[index] =  "get"  + v;
             str1 += s +  "," ;
             index++;
         }
         str1 = str1.substring( 0 , str1.length() -  1 );
         String str2 =  "" ;
         for  ( int  i =  0 ; i < cfs.size(); i++) {
             str2 +=  "?," ;
         }
         str2 = str2.substring( 0 , str2.length() -  1 );
         String sql =  "insert into "  + tableName +  "("  + str1 +  ")"  "values("
                 + str2 +  ")" ;
         // 8、这段sql==
         // insert into _table(id,name,age)values(?,?,?);
         return  sql;
     }
 
}


最后测试代码:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package  JunitTest;
 
import  csg.hibernate.entity.Session;
import  csg.hibernate.entity.Student;
/**
 
  * @author Caesar.hu
  * @Date  2014-11-28
  * @Time  上午09:32:15
  * @TODO
  */
public  class  Test {
     public  static  void  main(String[] args)  throws  Exception{
         Student student= new  Student();
         Session s= new  Session();
         student.setId( 1 );
         student.setAge( 12 );
         student.setName( "张三" );
         s.save(student);
     }
 
}


Ok,到这里,大家应该能明白,为什么说HibernateJDBC的封装?尤其是在考虑web性能的问题上为什么Hibernate不能满足开发需求,反射机制对于Java是多么重要

其实Hibernate的源码写法也莫不于此,只不过其在底层进行大量的封装,同时为了性能Hibernate也有采用直接将数据生成二进制流进行操作。对于配置文件大家可以看Hibernate 源码是如何利用dom4j解析Hibernate.cfg.xml这个文件,写的尤其经典,Ok

   Java从业者,想在技术上突破,反射机制是必须掌握的!











本文转自 小夜的传说 51CTO博客,原文链接:http://blog.51cto.com/1936625305/1583938,如需转载请自行联系原作者
目录
相关文章
|
3月前
|
Java 数据库连接 数据库
从零到精通:揭秘 Hibernate 构建持久层服务的全过程,你离数据持久化大师还有多远?
【8月更文挑战第31天】本文详细介绍了如何从零开始使用 Hibernate 构建一个持久层服务。首先,通过在 Maven 项目中添加必要的依赖,确保项目具备使用 Hibernate 的条件。接着,配置 `hibernate.cfg.xml` 文件以连接 MySQL 数据库,并设置了基本属性。然后定义了一个简单的 `User` 实体类及其映射关系。此外,还创建了一个 `HibernateUtil` 工具类来管理 `SessionFactory`。
41 0
|
3月前
|
Java 数据库连接 微服务
揭秘微服务架构下的数据魔方:Hibernate如何玩转分布式持久化,实现秒级响应的秘密武器?
【8月更文挑战第31天】微服务架构通过将系统拆分成独立服务,提升了可维护性和扩展性,但也带来了数据一致性和事务管理等挑战。Hibernate 作为强大的 ORM 工具,在微服务中发挥关键作用,通过二级缓存和分布式事务支持,简化了对象关系映射,并提供了有效的持久化策略。其二级缓存机制减少数据库访问,提升性能;支持 JTA 保证跨服务事务一致性;乐观锁机制解决并发数据冲突。合理配置 Hibernate 可助力构建高效稳定的分布式系统。
67 0
|
6月前
|
SQL Java 数据库连接
使用Hibernate进行数据库持久化操作
【4月更文挑战第15天】Hibernate 是一款开源 ORM 框架,简化数据库操作,通过映射将 Java 对象与表交互。核心接口包括 SessionFactory、Session、Transaction、Query 和 Criteria。使用 Hibernate 需添加依赖,配置 hibernate.cfg.xml 文件,设置数据库信息,并创建实体类及映射文件。
76 0
|
6月前
|
存储 缓存 Java
Hibernate - Session方法与持久化对象详解
Hibernate - Session方法与持久化对象详解
148 0
|
SQL Java 数据库连接
【java】——Hibernate持久化对象的三个状态
当我正在上课的时候这时老师出去去厕所了(session关闭),这个时候我的心飞向了外面的远方,这时我就处于离线状态。
|
SQL Java 数据库连接
Java Web Spring核心之AOP的解析及实战(AOP的实现、切入点、Aspect Spring的持久化 Hibernate)
Java Web Spring核心之AOP的解析及实战(AOP的实现、切入点、Aspect Spring的持久化 Hibernate)
203 0
Java Web Spring核心之AOP的解析及实战(AOP的实现、切入点、Aspect Spring的持久化 Hibernate)
|
SQL 缓存 Java
【持久化框架】Mybatis与Hibernate的详细对比
最近做了一个hibernate与MyBatis的对比总结,希望大家指出不对之处。 一.   Hibernate与MyBatis Hibernate 是当前最流行的O/R mapping框架,它出身于sf.NET,现在已经成为Jboss的一部分。 Mybatis 是另外一种优秀的O/R mapping框架。目前属于apache的一个子项目。 MyBatis 参考资
2900 0
|
缓存 Java 数据库连接
【SSH系列】-- Hibernate持久化对象的三种状态
       在上一篇博文中,小编主要简单的介绍了【SSH系列】--hibernate基本原理&&入门demo ,今天小编来继续介绍hibernate的相关知识, 大家知道,Java对象的生命周期,是从通过new语句创建开始,到不再被任何引用变量引用结束,结束后它占用的内存将被JVM垃圾回收机制收回。
1250 0