Hibernate是一个非常著名的的对象--关系映射工具,本文使用的是Hibernate3.6的版本。本文通过建立一个工程,来引导大家学习hibernate,对hibernate有个认识。有些代码、概念不清楚没关系,后文会慢慢的介绍。文中也有大量的注释,附件会上传本文所有的源码。
首先建立一个Web Project,然后在WEB-INF/lib下添加相关的jar包。项目结构如下图1所示。jar包介绍如下:
图1
hibernate-distribution-3.6.0.Final-dist\hibernate-distribution-3.6.0.Final\lib\required 目录下相应的jar包:
- antlr-2.7.6.jar:HQL-->SQL的转换
- commons-collections-3.1.jar:Apache的集合类工具
- dom4j.jar:解析XML文档
- hibernate3.jar:hibernate核心API实现
- javassist-3.12.0.GA.jar:动态Java代码生成工具
- jta-1.1.jar:标准的Java事务处理接口
- slf4j-api-1.6.1.jar:日志管理API
- slf4j-nop-1.6.1.jar:日志管理。
一.持久化类如下:
Customer.java
- package com.yaxing.entity;
- import java.util.HashSet;
- import java.util.Set;
- /**
- * 顾客类
- * */
- public class Customer {
- private Long id;
- private String name;
- private Set<Order> orders = new HashSet<Order>();
- public Long getId() {
- return id;
- }
- public void setId(Long id) {
- this.id = id;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public Set<Order> getOrders() {
- return orders;
- }
- public void setOrders(Set<Order> orders) {
- this.orders = orders;
- }
- }
Order.java
- package com.yaxing.entity;
- /**
- * 订单类
- * */
- public class Order {
- private Long id;
- private Customer customer;
- private String orderNumber;
- public Long getId() {
- return id;
- }
- public void setId(Long id) {
- this.id = id;
- }
- public Customer getCustomer() {
- return customer;
- }
- public void setCustomer(Customer customer) {
- this.customer = customer;
- }
- public String getOrderNumber() {
- return orderNumber;
- }
- public void setOrderNumber(String orderNumber) {
- this.orderNumber = orderNumber;
- }
- }
说明如下:这是一种典型的一对多的关联关系。即一个客户会有多个订单,而一个订单必然会属于一个客户,因此对于一个订单来说,如果其客户不存在,则此订单是没有任何意义的。这里设置的是双向的关联关系。因为可能业务中会存在大量的这样的需求:
- 查询客户的所有订单
- 根据所给的订单,查询订单所属的客户
类与类之间建立关联关系,可以很方便的从一个对象导航到另外一个对象,建立关系如下:
- /**
- * 订单类
- * */
- public class Order {
- private Long id;
- private Customer customer;
- //...
- }
这样就从order对象导航到了customer对象,
从order对象到customer对象的导航如下:即给定了order对象,获得了与他所关联的costomer对象.
- Customer customer = order.getCustomer();
那么对于给定的costomer对象,如何从customer对象导航到order对象呢?因为customer对象里面包含一组order,即一个客户会存在多个订单。
因此对于给定的客户,要查询所有的订单,代码如下:
返回的是一个Set集合。
- customer.getOrders();//返回一个set集合,用迭代器访问。
关于集合类的操作,也不是本文的内容,读者可以参考其他文章。不清楚的,可以本文后面留言。
二.数据库和配置文件.
建立的数据库如图2所示下:
图2
注意,Id都是自增numeric类型。这里的Orders表的取名问题:因为order是关键字,作为表名的时候,会报错的,Sql Server 中对关键字作为表名字段名的处理是:使用的时候加上中括号[],有时开发中也没注意到这点,判断错误起来也麻烦,关于这点,参见博客另外一篇文章:因使用关键字做为表名引起的Hibernate报错。
配置文件如下:Customer.hbm.xml
- <?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="com.yaxing.entity.Customer" table="Customer">
- <id name="id" type="java.lang.Long" column="Id">
- <generator class="identity"></generator>
- </id>
- <property name="name" column="Name" type="string"></property>
- <set name="orders" cascade="all" inverse="true">
- <key column="CustomerId"/><!-- 对应着外键 -->
- <one-to-many class="com.yaxing.entity.Order"/>
- </set>
- </class>
- </hibernate-mapping>
说明如下:
①<class>元素指定类和表的映射,如果没有指定table属性,则hibernate将类名做为表名。一个<class>包括一个<id>子元素和多个<property>子元素。
②<id>元素设定持久化类的OID(Object Identifier)和表的主键的映射,上述配置代码表示Customer类的id属性和Customer表的Id字段对应。
③<id>元素的<generator>子元素用于指定对象标识符生成器,它负责为OID生成唯一标识符。后文将介绍常见的对象标识符生成器的介绍。本文使用的是 native表示hibernate根据底层数据库来选择。
④<property>子元素设定类的属性和表的字段的映射,常见的属性包括
- name:指定持久化类的属性的名字
- type:指定hibernate映射类型,hibernate映射类型是在java类型和Sql类型之间的一个桥梁。比如java.lang.String 对应 type则为string。详细情况可以参见三者之间的对应关系。如果没有为某个属性设置映射类型,hibernate会利用java的放射机制先识别出持久化类的属性的java的类型,然后自动使用与之对应的hibernate映射类型。
- column:指定与持久化类的属性映射的表的字段名,上述代码表示Customer类的name属性对应的是Customer表的Name字段。
- not-null:是否允许为空,默认为false。程序中经常碰到为空的异常,此处的配置需特别引起注意!
- <set>元素:表示Customer类的orders属性为Set集合,<one-to-many>表示orders里面存放的是一组Order对象,<key>表示数据库中Orders表通过外键CustomerId参照Customer表。<cascade>表示级联保存,默认为none,取值可以有all 、 save-update 、delete、 delete-orphan ,各参数具体的含义后文有介绍。
Order.hbm.xml
- <?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="com.yaxing.entity.Order" table="Orders">
- <id name="id" type="java.lang.Long" column="Id">
- <generator class="identity"></generator>
- </id>
- <property name="orderNumber" column="OrderNumber" type="string"></property>
- <many-to-one name="customer" column="CustomerId"
- class="com.yaxing.entity.Customer" cascade="all" lazy="false"
- not-null="true"></many-to-one>
- </class>
- </hibernate-mapping>
说明:<many-to-one>表示 建立了customer属性和Orders表的外键CustomerId之间的映射,name为持久化类的属性的名字,column为持久化类的属性对应的表的外键CustomerId,class为持久化类的属性的类型,not-null表示是否允许为空,默认值为false.lazy是hibernate的检索策略,后文将有介绍。
三.测试代码和测试结果.
CustomerAction.java
- package com.yaxing.test;
- import java.util.Iterator;
- import java.util.List;
- import org.hibernate.Query;
- import org.hibernate.Session;
- import org.hibernate.Transaction;
- import com.yaxing.entity.Customer;
- import com.yaxing.util.HibernateUtil;
- public class CustomerAction {
- private Customer customer;
- private List<Customer> listCustomer;
- public Customer getCustomer() {
- return customer;
- }
- public void setCustomer(Customer customer) {
- this.customer = customer;
- }
- public List<Customer> getListCustomer() {
- return listCustomer;
- }
- public void setListCustomer(List<Customer> listCustomer) {
- this.listCustomer = listCustomer;
- }
- /**
- * 添加客户
- * */
- public void addCustomer(Customer customer) {
- Session s = null;
- Transaction tx = null;
- try {
- s = HibernateUtil.getSession();
- tx = s.beginTransaction();
- s.save(customer);
- tx.commit();
- }catch(Exception e){
- if(tx!=null){
- tx.rollback();
- }
- e.printStackTrace();
- }finally{
- if(s!=null){
- s.close();
- }
- }
- }
- /**
- * 删除客户
- * */
- public void deleteCustomer(Customer customer) {
- Session s = null;
- Transaction tx = null;
- try {
- s = HibernateUtil.getSession();
- tx = s.beginTransaction();
- s.delete(customer);
- tx.commit();
- }catch(Exception e){
- if(tx!=null){
- tx.rollback();
- }
- e.printStackTrace();
- }finally{
- if(s!=null){
- s.close();
- }
- }
- }
- /**
- * 更新客户
- * */
- public void update(Customer customer,String name) {
- Session s = null;
- Transaction tx = null;
- try {
- s = HibernateUtil.getSession();
- tx = s.beginTransaction();
- customer.setName(name);
- s.update(customer);
- tx.commit();
- }catch(Exception e){
- if(tx!=null){
- tx.rollback();
- }
- e.printStackTrace();
- }finally{
- if(s!=null){
- s.close();
- }
- }
- }
- /**
- * 查询客户
- * */
- public Customer findCustomer(Long id) {
- Session s = null;
- Transaction tx = null;
- try {
- s = HibernateUtil.getSession();
- tx = s.beginTransaction();
- customer = (Customer) s.get(Customer.class, id);
- tx.commit();
- }catch(Exception e){
- if(tx!=null){
- tx.rollback();
- }
- e.printStackTrace();
- }finally{
- if(s!=null){
- s.close();
- }
- }
- return customer;
- }
- /**
- * 查找所有的客户
- * */
- public List<Customer> findAll() {
- Session s = null;
- Transaction tx = null;
- try {
- s = HibernateUtil.getSession();
- tx = s.beginTransaction();
- Query query = s.createQuery("from Customer as a order by id asc");
- listCustomer = query.list();
- for(Iterator iter=listCustomer.iterator();iter.hasNext();){
- Customer customer = (Customer) iter.next();
- System.out.println("客户ID是:"+customer.getId()+"客户姓名是:"+customer.getName());
- }
- tx.commit();
- }catch(Exception e){
- if(tx!=null){
- tx.rollback();
- }
- e.printStackTrace();
- }finally{
- if(s!=null){
- s.close();
- }
- }
- return listCustomer;
- }
- }
OrderAction.java的代码和Customer.java代码类似。
- package com.yaxing.test;
- import java.util.Iterator;
- import java.util.List;
- import org.hibernate.Query;
- import org.hibernate.Session;
- import org.hibernate.Transaction;
- import com.yaxing.entity.Order;
- import com.yaxing.util.HibernateUtil;
- public class OrderAction {
- private Order order;
- private List<Order> listorder;
- public Order getorder() {
- return order;
- }
- public void setorder(Order order) {
- this.order = order;
- }
- public List<Order> getListorder() {
- return listorder;
- }
- public void setListorder(List<Order> listorder) {
- this.listorder = listorder;
- }
- public void addorder(Order order) {
- Session s = null;
- Transaction tx = null;
- try {
- s = HibernateUtil.getSession();
- tx = s.beginTransaction();
- s.save(order);
- tx.commit();
- }catch(Exception e){
- if(tx!=null){
- tx.rollback();
- }
- e.printStackTrace();
- }finally{
- if(s!=null){
- s.close();
- }
- }
- }
- /**
- * 删除用户
- * */
- public void deleteorder(Order order) {
- Session s = null;
- Transaction tx = null;
- try {
- s = HibernateUtil.getSession();
- tx = s.beginTransaction();
- s.delete(order);
- tx.commit();
- }catch(Exception e){
- if(tx!=null){
- tx.rollback();
- }
- e.printStackTrace();
- }finally{
- if(s!=null){
- s.close();
- }
- }
- }
- public void update(Order order,String number) {
- Session s = null;
- Transaction tx = null;
- try {
- s = HibernateUtil.getSession();
- tx = s.beginTransaction();
- order.setOrderNumber(number);
- s.update(order);
- tx.commit();
- }catch(Exception e){
- if(tx!=null){
- tx.rollback();
- }
- e.printStackTrace();
- }finally{
- if(s!=null){
- s.close();
- }
- }
- }
- public Order findorder(Long id) {
- Session s = null;
- Transaction tx = null;
- try {
- s = HibernateUtil.getSession();
- tx = s.beginTransaction();
- order = (Order) s.get(Order.class, id);
- tx.commit();
- }catch(Exception e){
- if(tx!=null){
- tx.rollback();
- }
- e.printStackTrace();
- }finally{
- if(s!=null){
- s.close();
- }
- }
- return order;
- }
- public List<Order> findAll() {
- Session s = null;
- Transaction tx = null;
- try {
- s = HibernateUtil.getSession();
- tx = s.beginTransaction();
- Query query = s.createQuery("from Order as a order by id asc");
- listorder = query.list();
- for(Iterator iter=listorder.iterator();iter.hasNext();){
- Order order = (Order) iter.next();
- System.out.println("订单ID是:"+order.getId()+"订单数目是:"+order.getOrderNumber());
- }
- tx.commit();
- }catch(Exception e){
- if(tx!=null){
- tx.rollback();
- }
- e.printStackTrace();
- }finally{
- if(s!=null){
- s.close();
- }
- }
- return listorder;
- }
- }
HibernateUtil.java如下:
- package com.yaxing.hibernate.util;
- import org.hibernate.Session;
- import org.hibernate.SessionFactory;
- import org.hibernate.cfg.Configuration;
- public final class HibernateUtil {
- private static SessionFactory sessionFactory;
- private HibernateUtil(){
- }
- static {
- Configuration cfg = new Configuration();
- cfg.configure();
- sessionFactory=cfg.buildSessionFactory();
- }
- public static SessionFactory getSessionFactory() {
- return sessionFactory;
- }
- public static Session getSession(){
- return sessionFactory.openSession();
- }
- }
测试代码如下:
- package com.yaxing.test;
- import com.yaxing.entity.Customer;
- public class Test {
- public static void main(String args[]){
- Customer customer = new Customer();
- customer.setName("51CTO");
- CustomerAction ca = new CustomerAction();
- /**
- * 添加对象
- * */
- ca.addCustomer(customer);
- }
允许之后,打印出来的SQL语句如下:
- Hibernate:
- insert
- into
- Customer
- (Name)
- values
- (?)
接下来,我们到数据库中看看记录被插入进来了没有:
图3
可以看到,如图3所示,记录插入成功!
接下来我们看看查询所有的:
- /**
- * 查询所有
- * */
- ca.findAll();
输出:
- Hibernate:
- select
- customer0_.Id as Id1_,
- customer0_.Name as Name1_
- from
- Customer customer0_
- order by
- customer0_.Id asc
- 客户ID是:2客户姓名是:null
- 客户ID是:4客户姓名是:51CTO
- 客户ID是:5客户姓名是:51CTO
- 客户ID是:6客户姓名是:51CTO
- 客户ID是:7客户姓名是:51CTO
- 客户ID是:8客户姓名是:51CTO
接下来,我们删除刚测试的ID为8的记录,
- /**
- * 删除指定对象
- * */
- Customer customer = ca.findCustomer(8L);
- ca.deleteCustomer(customer);
运行的SQL语句如下:
- Hibernate:
- select
- customer0_.Id as Id1_0_,
- customer0_.Name as Name1_0_
- from
- Customer customer0_
- where
- customer0_.Id=?
- Hibernate:
- select
- orders0_.CustomerId as CustomerId1_1_,
- orders0_.Id as Id1_,
- orders0_.Id as Id0_0_,
- orders0_.OrderNumber as OrderNum2_0_0_,
- orders0_.CustomerId as CustomerId0_0_
- from
- Orders orders0_
- where
- orders0_.CustomerId=?
- Hibernate:
- delete
- from
- Customer
- where
- Id=?
可以查看下,Id为8的记录删除了!
最后来个级联保存的:
- /**
- * 保存订单
- * 级联保存
- * */
- Customer customer = new Customer();
- customer.setName("google");
- ca.addCustomer(customer);
- Order order = new Order();
- order.setOrderNumber("5箱");
- order.setCustomer(customer);
- oa.addorder(order);
执行的SQL语句如下:
- Hibernate:
- insert
- into
- Customer
- (Name)
- values
- (?)
- Hibernate:
- insert
- into
- Orders
- (OrderNumber, CustomerId)
- values
- (?, ?)
- Hibernate:
- update
- Customer
- set
- Name=?
- where
- Id=?
可以查看下记录:
最后帖上hibernate的配置代码:
- <?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="dialect">
- org.hibernate.dialect.SQLServerDialect
- </property>
- <property name="connection.url">
- jdbc:jtds:sqlserver://server:1434/hibernateTest
- </property>
- <property name="connection.username">sa</property>
- <property name="connection.password">711</property>
- <property name="connection.driver_class">
- net.sourceforge.jtds.jdbc.Driver
- </property>
- <property name="hibernate.show_sql">true</property>
- <property name="format_sql">true</property>
- <property name="myeclipse.connection.profile">jtds</property>
- <mapping resource="com/yaxing/entity/Order.hbm.xml" />
- <mapping resource="com/yaxing/entity/Customer.hbm.xml" />
- </session-factory>
- </hibernate-configuration>