一、持久化,ORM概念
1. Persistence: 使数据的存活时间超过(outlive)应用程序的生命周期,也就是存储在数据库或磁盘上,不消失
2. ORM: Object/ Relation Mapping: 解决数据库数据到Object的映射问题,
使用Hibernate的好处:
(1) Productivity, 提高生产效率,使developer从重复繁重的sql查询到组装object中释放出来
(2) Maintainable, 可维护性,使用统一规范查询方法,可移植性强,可以一处写好查询,而不用关心底层用了什么数据库,做了很好的兼容性封装
(3) Performance, 性能比自己手写卓越,专业的数据处理团队,将best practice应用于框架中,如使用pooling statement能提高db2 jdbc效率,但是影响其他的数据库性能等
3. 注意事项:
(1) 多层mapping的获取和缓存方法,如User的表结构:
name varchar
email varchar
country varchar # Ref to Country Object
此时,获取mapping的时候,是先执行User表的查询,使用getCountry()方法后再调用Country表查询,还是一开始把所有关联表遍历查询,这涉及到了不同的设计strategy
二、Hibernate基本用法
1. 配置文件路径:
hibernate.cfg.xml需要放在根目录一下,便于后期自动加载使用,而xx.hbm.xml等映射文件可以使用hbm包整理管理
2. 基础配置文件:hibernate.cfg.xml, 包含jdbc驱动配置,数据库连接池配置等,默认内部使用c3p0数据库连接池,以及mapping(这里配置的是Message.hbm.xml)。其中有show_sql开关的判断,用于是否输出标准sql,便于开发人员调试使用。
<!DOCTYPE hibernate-configuration SYSTEM
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/estore</property>
<property name="hibernate.connection.username">clops</property>
<property name="hibernate.connection.password">xxx</property>
<property name="hibernate.dialect"> org.hibernate.dialect.MySQLDialect</property>
<!-- Use the C3P0 connection pool provider -->
<property name="hibernate.c3p0.min_size">5</property>
<property name="hibernate.c3p0.max_size">20</property>
<property name="hibernate.c3p0.timeout">300</property>
<property name="hibernate.c3p0.max_statements">50</property>
<property name="hibernate.c3p0.idle_test_period">3000</property>
<!-- Show and print nice SQL on stdout -->
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<!-- List of XML mapping files -->
<mapping resource="hbm/Message.hbm.xml"/>
</session-factory>
</hibernate-configuration>
3. 基础工具类(可选)HibernateUtil, 用于统一生成和关闭SessionFactory
package com.cisco.eStore.test.hello;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateUtil {
private static SessionFactory sessionFactory;
static{
try{
sessionFactory = new Configuration().configure().buildSessionFactory();
}catch (Throwable ex){
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory(){
return sessionFactory;
}
public static void shutdown(){
getSessionFactory().close();
}
}
4. 构建JavaBean:Message.java, 这里id是Long型的,当然你也可以选择使用别的hibernate支持的identify类型
package com.cisco.eStore.test.hello;
public class Message {
private Long id;
private String text;
private Message nextMessage;
Message(){}
public Message(String text){
this.text = text;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public Message getNextMessage() {
return nextMessage;
}
public void setNextMessage(Message nextMessage) {
this.nextMessage = nextMessage;
}
}
5. 构建映射文件(mapping)Message.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.cisco.eStore.test.hello.Message" table="MESSAGE">
<id name="id" column="MESSAGE_ID">
<generator class="increment"/>
</id>
<property name="text" column="MESSAGE_TEXT"/>
<many-to-one name="nextMessage" cascade="all" column="NEXT_MESSAGE_ID" foreign-key="FK_NEXT_MESSAGE"/>
</class>
</hibernate-mapping>
6. 测试类HelloWorld.java, Session作为hibernate中重要概念,是单线程不共享的对象,存储同一时刻(same point)的一些列sqlstatement动作,以及整套映射关系的持久化实例(map of persistence instances).
package com.cisco.eStore.test.hello;
import org.hibernate.Session;
import org.hibernate.Transaction;
import java.util.Iterator;
import java.util.List;
public class HelloWorld {
public static void main(String[] args){
// first unit of work
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction tx = session.beginTransaction();
Message message = new Message("Hello World");
Long msgId = (Long)session.save(message);
tx.commit();
session.close();
// second unit of work
Session newSession = HibernateUtil.getSessionFactory().openSession();
Transaction newTransaction = newSession.beginTransaction();
List messageList = newSession.createQuery("from Message m order by m.text asc").list();
System.out.println("size: "+messageList.size());
for(Iterator iter = messageList.iterator(); iter.hasNext();){
Message loadMsg = (Message) iter.next();
System.out.println(loadMsg.getText());
}
newTransaction.commit();
newSession.close();
}
}
三、使用Annotations注解,实现ORM:
比之二中,需要做三个步骤,
1. 修改Message.java为 标记注解后的类:
package com.cisco.eStore.test.anotation;
import javax.persistence.*;
@Entity
@Table(name="MESSAGE")
public class Message {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="MESSAGE_ID")
private Long id;
@Column(name="MESSAGE_TEXT")
private String text;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "NEXT_MESSAGE_ID")
private Message nextMessage;
Message(){}
public Message(String text){
this.text = text;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public Message getNextMessage() {
return nextMessage;
}
public void setNextMessage(Message nextMessage) {
this.nextMessage = nextMessage;
}
2. 修改hibernate.cfg.xml
<!-- List of XML mapping files -->
<!--<mapping resource="hbm/Message.hbm.xml"/>-->
<mapping class="com.cisco.eStore.test.anotation.Message"/>
3. Run 测试类HelloWorld, 会正确打印测试信息