Hibernate5.2之单向一对多
一. 简介
Hibernate中最复杂的应该就是各种关联(单向一对多、单向多对一、双向一对多、一对一、多对多)关系的映射,于是笔者就想着去写一些关于Hibernate相关的系列文章,可能最近今年项目上基本上没怎么用Hibernate,包括身边的很多人都在唱衰Hibernate,觉得他笨重、低效,但是笔者认为这都不影响其在我心目中的地位,以及他当初给笔者所带来的震撼,也影响千千万万的程序员。本系列博客中没有关于Hibernate原理性的东西的讲解,只是一些基本的示例,其实经验稍微丰富一点的程序员其实也能够想象的到其底层的一个实现原理。此篇文章为Hibernate系列的第一篇,在第二节中所创建的基础代码会贯穿着整个系列文章,在后续的博客中笔者将不在作任何的赘述。而关于第三节的数据库的创建会贯穿着一对多、HQL查询、SQL查询、QBC查询系列篇章,故在这些相关篇章中笔者将会依然使用此处所创建的数据库。本系列教程中所使用的数据库为Oracle,Hibernate的版本为5.2.0。
二. 基础代码的创建
2.1 Session工具类
public class OracleSessionUtils { //获取SessionFactory public static SessionFactory getSessionFactory(){ StandardServiceRegistry registry = null; SessionFactory sessionFactory = null; try{ registry = new StandardServiceRegistryBuilder().configure("hibernate-oracle.xml").build(); sessionFactory = new MetadataSources(registry).buildMetadata().buildSessionFactory(); }catch(Exception ex){ ex.printStackTrace(); StandardServiceRegistryBuilder.destroy(registry); } return sessionFactory; } //打开并返回一个Session public static Session openSession(){ return getSessionFactory().openSession(); } //关闭Session public static void closeSession(Session session){ if(null != session){ session.close(); } } }
2.2 基础单元测试代码
public class HibernateTest { private Session session; @Before public void openSession(){ session = OracleSessionUtils.openSession(); //打开会话 } @After public void closeSession(){ OracleSessionUtils.closeSession(session); } }
三. 数据库的创建
create table CUSTOMER ( id NUMBER(10) not null, name VARCHAR2(255 CHAR), phone_number VARCHAR2(255 CHAR), primary key (ID) );
create table ORDERS ( id NUMBER(10), order_id VARCHAR2(255 CHAR), create_time TIMESTAMP(6), customer_id NUMBER(10), primary key (ID) );
四. hbm文件的方式
4.1 POJO类的创建
public class Customer { private int id; private String name; private String phoneNum; private Set<Order> orderSet; //setter and getter } public class Order { private int id; private String orderId; private Date createTime; //setter and getter }
4.2 hbm文件的创建
Customer.hbm.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.demo.hibernate.one2many.Customer" table="customer"> <id name="id" type="int"> <generator class="sequence"> <param name="sequence">cus_order_seq</param> </generator> </id> <property name="name" type="string" column="name"></property> <property name="phoneNum" type="string" column="phone_number"></property> <set name="orderSet"> <key column="customer_id"></key> <one-to-many class="com.demo.hibernate.one2many.Order"/> </set> </class> </hibernate-mapping>
Order.hbm.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.demo.hibernate.one2many.Order" table="orders"> <id name="id" type="int"> <generator class="sequence"> <param name="sequence">cus_order_seq</param> </generator> </id> <property name="orderId" column="order_id" type="string"></property> <property name="createTime" column="create_time" type="timestamp"></property> </class> </hibernate-mapping>
五.注解的方式
注解的方式已经逐渐替代了以前的XML文件配置的方式,摈弃了以往每修改一次POJO类就必须修改XML文件的繁琐的方式。注:注解可以放在成员变量的上面,也可以放在对应的get方法上面。
Customer.java
@Entity @Table(name="customer") public class Customer { @Id @Column(name="id") @GenericGenerator(name="sequenceGenerator", strategy="sequence", parameters={@Parameter(name="sequence", value="cus_order_seq")}) @GeneratedValue(generator="sequenceGenerator") private int id; @Column(name="name") private String name; @Column(name="phone_number") private String phoneNum; @OneToMany @JoinColumn(name="customer_id") private Set<Order> orderSet; //setter and getter }
Order.java
@Entity @Table(name="orders") public class Order { @Id @Column(name="id") @GenericGenerator(name="sequenceGenerator", strategy="sequence", parameters={@Parameter(name="sequence", value="cus_order_seq")}) @GeneratedValue(generator="sequenceGenerator") private int id; @Column(name="order_id") private String orderId; @Column(name="create_time") @Type(type="timestamp") private Date createTime; //setter and getter }
六. 代码测试
A.保存
@Test public void save(){ Transaction tx = session.beginTransaction(); Customer customer = new Customer(); customer.setName("AAAAA"); customer.setPhoneNum("334411"); Order order = new Order(); order.setCreateTime(new Date()); order.setOrderId("A"); Order order1 = new Order(); order1.setCreateTime(new Date()); order1.setOrderId("B"); Set<Order> orderSet = new HashSet<Order>(); orderSet.add(order); orderSet.add(order1); customer.setOrderSet(orderSet); session.save(customer); session.save(order); session.save(order1); tx.commit(); }
B.get查询
@Test public void get(){ Customer customer = session.get(Customer.class, 42); System.out.println("查询Customer的SQL已经发送"); System.out.println(customer.getPhoneNum() + "::" + customer.getName()); Set<Order> set = customer.getOrderSet(); System.out.println("查询Order的SQL还未发送,因为延迟加载,只有当在使用Order的时候才会发送SQL"); for(Order o : set){ System.out.println(o.getOrderId() + "::" + o.getCreateTime()); } }
C.load查询
@Test public void load(){ Customer customer = session.load(Customer.class, 42); System.out.println("查询Customer的SQL还未发送,只有当使用的时候才会放松SQL"); System.out.println(customer.getPhoneNum() + "::" + customer.getName()); Set<Order> set = customer.getOrderSet(); System.out.println("查询Order的SQL还未发送,因为延迟加载,只有当在使用Order的时候才会发送SQL"); for(Order o : set){ System.out.println(o.getOrderId() + "::" + o.getCreateTime()); } }
D.删除
@Test public void delete(){ Customer customer = new Customer(); customer.setId(42); /* 如果设置了Order则会先执行更新 Order order = new Order(); order.setId(43); Order order1 = new Order(); order1.setId(44); Set<Order> orderSet = new HashSet<Order>(); orderSet.add(order); orderSet.add(order1); customer.setOrderSet(orderSet); */ Transaction tx = session.beginTransaction(); session.delete(customer); tx.commit(); }
E.更新
@Test public void update(){ Customer customer = new Customer(); customer.setId(45); //如果没有设置Id会报错 customer.setName("BBBNNN"); customer.setPhoneNum("990088"); Order order = new Order(); order.setId(46); //如果没有Id则会执行插入 order.setCreateTime(new Date()); order.setOrderId("N"); Order order1 = new Order(); order1.setId(47); //如果没有Id则会执行插入 order1.setCreateTime(new Date()); order1.setOrderId("G"); Set<Order> orderSet = new HashSet<Order>(); orderSet.add(order); orderSet.add(order1); //如果Customer中设置了Order,会先将Order表的customer_id置空,然后再更新customer_id //但是不会更新其他的数据 customer.setOrderSet(orderSet); Transaction tx = session.beginTransaction(); session.update(customer); tx.commit(); }