Hibernate使用简介
Hibernate的优点是:符合Java习惯的关系数据库持久化;直接、方便;基于JDBC抽象,适合大多数系统,无需关心具体实现。缺点:项目复杂时,需要可视化工具支持,否则效率降低。
持久化
- 持久化:持久保存,掉电等情况下可重新获得数据。
- 持久化实现:
- 硬盘文件、数据库。
- 关系数据库与对象数据库区别,关系数据库定义。
- 持久化是状态保存的一种形式。
持久化和对象
- 实现方式:JDBC、实体Bean和O/R Mapping
- 对象通过JDBC SQL语句逐个字段保存到数据库中。
- O/R mapping:?Hibernate/TopLink?JDO
- 实体Bean中CMP,类似O/R Mapping,有着非常坚实的事务机制,支持ACID。
SQL优缺点
- 优点:精简,类似数学公式,通过抽象符合完成逻辑操作。
- 缺点:理解和维护不便,因为对于抽象符号的逻辑表达,不是每个人理解;如果存储过程很复杂,可能只有作者理解。
阻抗
- 关系数据库和对象存在阻抗。
- 关系数据库是一种数学范畴解决方案,使用数据结构以及关系等类似数学公式抽象方案。
- 对象方法则是符合人类自然思维方式,例如:归纳、分类。代表一种哲学范畴解决方案。
- 两者思考路径不一致。
- 历史原因。数据库出现较早,先入为主。
mapping技术?
- 对象
- 普通对象 POJO:
Package com.jdon.sample;
public class Perso{
private String id;
private String name;
public String getId() {?returid;?}
private void setId(String id) {?this.id = id;?}
public String getName() {?returname;?}
public void setName(String name) {
this.name = name;
}
}
映射配置文件
<?xml version="1.0" encoding="UTF-8"?>
<mapping>
<description>这是Person映射</description>
<class name=" com.jdon.sample.Person">
<map-to xml="body"/>
<field name=“id" type="string" />
<field name=“name" type="string" />
</class>
</mapping>
结果通过Castor 等Mapping工具映射输出
<person>
<id>12345678</id>
<name>xxx</name>
</person>
该XML可作为文件保存到硬盘,实现硬盘文件的持久化。
数据表定义
数据表名为person_table
Id?| character(32) | not null
name | character varying(16) | not null Indexes: pkey primary key btree (id) ;
数据库名XXXX。
数据库Mapping实现
SQL插入:
String sql =“insert into person_table (id, name) values(?, ?)”;
prepstmt = conn.prepareStatement(sql);
prepstmt.setString(1, person.getId());
prepstmt.setString(2, person.getName());
需要分解Java对象,当Java对象字段很多时,非常琐碎。
使用O/R mapping技术,只需要一句话:
session.save(person);
Hibernate实现
<hibernate-mapping>
<class name=“com.jdon.sample.Person" table=" person_table ">
<property name=“id”/>?//映射相同id
<property name=“name”> //person定义
<columname=“NAME” length=“16” not-null=“true”/>//数据表
</property>
</class>
</hibernate-mapping>
Hibernate实现映射代码
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
//获得一个Sessio
Session?sessio= sessionFactory.openSession();
Transactiotx= session.beginTransaction();
Persoprincess = new Person();
princess.setId(“123456");
princess.setName(“彭晨阳");
session.save(princess);
tx.commit();
session.close(); //关闭一个Sessio
JDBC比较
Sessiosessio= sf.openSession();?
相当于Connectiocon, 开启数据库连接
Transactiotx = session.beginTransactioin(); ...
相当于 conn.setAutoCommit(false);
session.flush();
tx.commit();
相当于conn.setAutoCommit(true);
session.close();
相当于conn.close(); 连接关闭
Session是一个操作过程,类似connectio
SessionFactory是全局的,类似容器,工厂模式。
为了使上述代码运行,需要一些全局应用配置。如如何让转换代码寻找到映射配置文件hibernate.cfg.xml ?
Hibernate配置文件
全局性配置:数据库服务器的IP地址;访问用户和密码等通用配置。 hibernate.cfg.xml
映射Mapping配置:对象和相应数据表字段之间的映射。配置文件自己定义。
hibernate.cfg.xml配置
<hibernate-configuration>
<session-factory>
<property name="connection.datasource">
java:comp/env/jdbc/quickstart
</property>
<property name="show_sql">false</property>
<property name="dialect">
net.sf.hibernate.dialect.PostgreSQLDialect
</property>
<!-- Mapping files 配置映射文件 -->
<mapping resource=“Person.hbm.xml"/>
</session-factory> </hibernate-configuration>
HIBernate启动
SessioFactory 和配置Configuration等类是启动 Hibernate 的主要功能类。
SessionFactory sessionFactory = new Configuration().configure()
SessionFactory实例比较重或大,第一次创建后保存在容器的Application或Singleton, 如struts的HibernatePlugIn。
配置对象映射方法:
将对象映射放入主配置Hibernate-cfg.xml 优点是集中化,但是大型项目无伸缩性。
配置对象映射在分离的XML文件中,每个对象一个配置文,然后在Hibernate-cfg.xml增加这些配置指向;或在Configuratio通过编程注册。
在SessionFactory 创建时,通过程序注册。
插入数据库
Cat cat = new Cat();
cat.setColor(Color.GINGER);
cat.setSex('M');
cat.setName("Fritz");
Long generatedID = (Long) sess.save(cat);
sess.save( pk, new Long(1234) );
Hibernate查询
Load三种不同用法:
Cat fritz = (Cat) sess.load(Cat.class, generatedId);
long pkId = 1234;
DomesticCat pk = (DomesticCat) sess.load( Cat.class, new Long(pkId) );
Cat cat = new DomesticCat();
// load pk's state into cat
sess.load( cat, new Long(pkId) );
Set kittens = cat.getKittens();//真正访问数据库
如果没有匹配的数据库记录,load()方法抛出exceptio
Load返回一个对象,这是一个未初始化的代理,并且直到你调用该对象的某方法时才会去访问数据库
String name = Fritz.getName();
Hibernate查询
get()方法,它会立刻访问数据库,如果没有对应的行,返回null。
Cat cat = (Cat) sess.get(Cat.class, id);
if (cat==null) {
cat = new Cat();
sess.save(cat, id);
}
returcat;
任何时候都可以使用refresh()方法重新装载对象和它的集合。如果你使用数据库触发器更改了对象的某些属性,这就很有用。
sess.save(cat);
sess.flush(); //force the SQL INSERT
sess.refresh(cat); //re-read the state (after the trigger executes)
懒加载Lazy
防止加载对象时取出暂时无用的大量数据。
Load完全使用lazy
Get主对象不是使用lazy,但是主对象中子对象是lazy。
为获得主对象下子对象有三种方式:
1. OpeSessioiView (J2EE)
2. Hibernate.initialize(user.get子对象());
3. 设置子对象映射关系lazy= false,失效lazy
Lazy和缓存
Lazy是一种代理,以JDK动态代理。
类似树形结构,如果没有lazy,获得一个Tree根节点,会将其下所有节点都加载,影响性能,浪费内存。
Lazy对Tree中的枝有效用,可防止将枝下面节点全部加载。
Lazy和缓存是hibernate基本要点。
Lazy基于模型对象优化建模。
更新对象
在同一Session中更新 ,直接的更改一个对象的方法就是load()它,保持Session打开,然后直接修改即可:
Cat cat = (Cat) sess.load( Cat.class, new Long(69) );
//update db
cat.setName("PK");
sess.flush();