下面以一个简单的例子描述hibernate的使用。
软件配置:jdk1.6+hibernate4.1+oracle10g
1.hibernate包下载
先到hibernate官网下载hibernate的开发包hibernate-search-4.1.1.Final-dist.zip,解压缩此包,dist\lib目录下是开发所需的jar包。
2.在eclipse中创建java项目
项目创建后,需要引入依赖的jar包:
hibernate包:required下全部jar包,provided下的hibernate-jpa-2.0-api-1.0.1.Final.jar和jta-1.1.jar包
oracle包:ojdbc6.jar
日志包(可选,如果不添加则看不到hibernate的日志输出):slf4j-api-1.6.3.jar、logback-core-1.0.0.jar、logback-classic-1.0.0.jar
创建包:test,test.hibernate,test.model
3.创建数据库表
本示例使用oracle,其他数据库的特性和sql可参考一下代码稍作改变即可:
创建House表:
CREATE TABLE House ( id NUMBER(8) NOT NULL, name VARCHAR2(50), address VARCHAR2(50) NOT NULL ) ; ALTER TABLE House ADD CONSTRAINT PK_House PRIMARY KEY (id) USING INDEX ; CREATE SEQUENCE SEQ_House_id INCREMENT BY 1 START WITH 1 NOMAXVALUE MINVALUE 1 NOCYCLE NOCACHE NOORDER ;
创建Person表:
CREATE TABLE Person ( id NUMBER(8) NOT NULL, name VARCHAR2(50), age NUMBER(3) ) ; ALTER TABLE Person ADD CONSTRAINT PK_Person PRIMARY KEY (id) USING INDEX ;
4.编写hibernate配置文件
在src目录下创建hibernate.cfg.xml文件:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="connection.url">jdbc:oracle:thin:@localhost:1521:orcl</property> <property name="connection.username">hi</property> <property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property> <property name="dialect">org.hibernate.dialect.Oracle10gDialect</property> <property name="connection.password">hi</property> <property name="transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property> <property name="current_session_context_class">thread</property> <!-- this will show us all sql statements --> <property name="hibernate.show_sql">true</property> <!-- mapping files --> <mapping resource="test/model/House.hbm.xml"/> <mapping class="test.model.Person"/> </session-factory> </hibernate-configuration>
注意看上面的mapping节点:第一个使用的是mapping映射文件,第二个使用java注解映射方式。这两个文件将在后面创建。
5.编写SessionFactoryUtil类
在test.hibernate包下建立SessionFactoryUtil类,此类用于获取session:
package test.hibernate; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.AnnotationConfiguration; public class SessionFactoryUtil { private static org.hibernate.SessionFactory sessionFactory; private SessionFactoryUtil() { } static { // 使用xml文件或者注解方式加载hibernate配置 sessionFactory = new AnnotationConfiguration().configure() .buildSessionFactory(); // 只是用xml文件方式加载hibernate配置 // sessionFactory = new Configuration().configure().buildSessionFactory(); } public static SessionFactory getInstance() { return sessionFactory; } /** * 打开会话但不绑定到会话上下文中 * @return the session */ public Session openSession() { return sessionFactory.openSession(); } /** * 从会话上下文中返回会话,如果上下文中不存在会话示例则先创建一个会话示例并保存到上下文中,然后再返回。 * <br> * 会话上下文与hibernate配置中的current_session_context_class属性值有关。 * @return the session */ public Session getCurrentSession() { return sessionFactory.getCurrentSession(); } /** * 关闭会话工厂 */ public static void close() { if (sessionFactory != null) sessionFactory.close(); sessionFactory = null; } }
6.创建映射文件和类
本例示范两种方式的映射,mapping文件和java注解方式。
House采用mapping文件映射方式,Person采用java注解映射方式。
在test.model包下新建House类(POJO):
package test.model; public class House { private Integer id; private String name; private String address; /** * @return the id */ public Integer getId() { return id; } /** * @param id the id to set */ public void setId(Integer id) { this.id = id; } /** * @return the name */ public String getName() { return name; } /** * @param name the name to set */ public void setName(String name) { this.name = name; } /** * @return the address */ public String getAddress() { return address; } /** * @param address the address to set */ public void setAddress(String address) { this.address = address; } /* (non-Javadoc) * @see java.lang.Object#toString() */ @Override public String toString() { return "House [id=" + id + ", name=" + name + ", address=" + address + "]"; } }
同时在此包下新建House.hbm.xml映射文件,通过此文件描述House类和数据库中的House表之间的映射关系:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD
3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping>
<class name="test.model.House" table="house">
<id name="id" column="id">
<generator class="sequence">
<param name="sequence">SEQ_HOUSE_ID</param>
</generator>
</id>
<property name="name" column="name" />
<property name="address" column="address" />
</class>
</hibernate-mapping>
house表在数据库中使用名为SEQ_HOUSE_ID的序列作为主键id的值。如果表的主键生成方式不同,generator节点需要修改,网上有很多相关资料。
在test.model包下新建Person类(POJO),并添加注解来表述语数据库中Person表的映射关系,不做特殊说明时,默认数据库中的名车和类中名称一致。
package test.model; import javax.persistence.AttributeOverride; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name="PERSON")//表名称和类名称相同时可以不添加此注解来说明 public class Person { @Id private Integer id; private String name; @AttributeOverride(column = @Column, name = "AGE")//字段名称和属性名称相同可以不添加此注解来说明 private int age; /** * @return the id */ public Integer getId() { return id; } /** * @param id the id to set */ public void setId(Integer id) { this.id = id; } /** * @return the name */ public String getName() { return name; } /** * @param name the name to set */ public void setName(String name) { this.name = name; } /** * @return the age */ public int getAge() { return age; } /** * @param age the age to set */ public void setAge(int age) { this.age = age; } }
7.编写测试方法
package test; import org.hibernate.Session; import org.hibernate.Transaction; import test.hibernate.SessionFactoryUtil; import test.model.House; import test.model.Person; public class Test { // private static Logger logger = LoggerFactory.getLogger(Test.class);//slf4j logging public static void main(String[] args) { Session session = SessionFactoryUtil.getInstance().getCurrentSession(); Transaction tx = session.beginTransaction(); House house = new House();//瞬态 house.setName("forest honey"); house.setAddress("beijing"); session.save(house);//持久态 //对持久态对象进行修改 house.setAddress("yj1212"); Person person = new Person();//瞬态 person.setId(1); person.setAge(24); person.setName("张三"); session.save(person);//持久态 session.delete(person);//session关闭后此person便会成为托管态对象 tx.commit();//提交事务,提交后会自动关闭session // session.close(); } }
执行上面的main方法,控制台输出:
Hibernate: select SEQ_HOUSE_ID.nextval from dual Hibernate: insert into house (name, address, id) values (?, ?, ?) Hibernate: insert into PERSON (age, name, id) values (?, ?, ?) Hibernate: update house set name=?, address=? where id=? Hibernate: delete from PERSON where id=?
测试类中紊乱的“业务逻辑”代码只是为了说明hibernate的使用方式,请忽略!呵呵。
hibernate拥有缓存机制,其中session便是一级缓存,还可以配置二级缓存。要想充分利用hibernate的优势,还需要深入了解hibernate的session,事务,缓存,延迟加载,以及各种对象尤其是session的生命周期等。后续再慢慢总结。