Hibernate中的单项n 到 1说明
Customer.java:
package hibernate.sessiondemo; public class Customer { private Integer customerId; private String customerName; public Integer getCustomerId() { return customerId; } public void setCustomerId(Integer customerId) { this.customerId = customerId; } public String getCustomerName() { return customerName; } public void setCustomerName(String customerName) { this.customerName = customerName; } @Override public String toString() { return "Customer [customerId=" + customerId + ", customerName=" + customerName + "]"; } }
Order.java
package hibernate.sessiondemo; public class Order { private Integer orderId; private String orderName; private Customer customer; public Integer getOrderId() { return orderId; } public void setOrderId(Integer orderId) { this.orderId = orderId; } public String getOrderName() { return orderName; } public void setOrderName(String orderName) { this.orderName = orderName; } public Customer getCustomer() { return customer; } public void setCustomer(Customer customer) { this.customer = customer; } @Override public String toString() { return "Order [orderId=" + orderId + ", orderName=" + orderName + ", customer=" + customer + "]"; } }
Customer.hbm.xml:
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <!-- Generated Feb 20, 2016 5:38:35 PM by Hibernate Tools 3.5.0.Final --> <hibernate-mapping> <class name="hibernate.sessiondemo.Customer" table="CUSTOMERS"> <id name="customerId" type="java.lang.Integer"> <column name="CUSTOMER_ID" /> <generator class="native" /> </id> <property name="customerName" type="java.lang.String"> <column name="CUSTOMER_NAME" /> </property> </class> </hibernate-mapping>
Order.hbm.xml:
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <!-- Generated Feb 20, 2016 5:38:35 PM by Hibernate Tools 3.5.0.Final --> <hibernate-mapping package="hibernate.sessiondemo"> <class name="Order" table="ORDERS"> <id name="orderId" type="java.lang.Integer"> <column name="ORDER_ID" /> <generator class="native" /> </id> <property name="orderName" type="java.lang.String"> <column name="ORDER_NAME" /> </property> <!-- 在这个例子中,每个单子值能属于一个客户,而一个客户可以拥有多个单子,所以这个是一个n-1的关系 order是n, customer是1 映射多对一的关联关系, 使用many-to-one 来映射多对一的关联关系 name: 多这一端关联的一的那一端的属性的名字 column: 一那一端在多的一端对应的数据表中的外键的名字 --> <many-to-one name="customer" class="Customer" column="CUSTOMER_ID"></many-to-one> </class> </hibernate-mapping>
hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- 配置链接数据库的基本信息 --> <property name="connection.username">root</property> <property name="connection.password">86915310</property> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <property name="connection.url">jdbc:mysql://localhost:3306/user</property> <!-- 配置hibernate的基本信息 --> <!-- hibernate所使用的数据库方言 --> <property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property> <!-- 是否在控制台打印SQL --> <property name="show_sql">true</property> <!-- 是否对SQL进行格式化 --> <property name="format_sql">true</property> <!-- 指定自动生成数据表的策略 --> <property name="hbm2ddl.auto">update</property> <!-- 设置hibernate的事务隔离级别 --> <property name="connection.isolation">2</property> <!-- 在执行完delete后可以把OID 设置为空 --> <!-- <property name="use_identifier_rollback">true</property> --> <!-- 指定关联的.hbm.xml文件 --> <mapping resource="hibernate/sessiondemo/Order.hbm.xml"/> <mapping resource="hibernate/sessiondemo/Customer.hbm.xml"/> </session-factory> </hibernate-configuration>
HibernateTest.java
package hibernate.sessiondemo; import java.sql.Connection; import java.sql.SQLException; import java.util.Date; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.boot.Metadata; import org.hibernate.boot.MetadataSources; import org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl; import org.hibernate.boot.registry.StandardServiceRegistry; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.jdbc.Work; import org.junit.After; import org.junit.Before; import org.junit.Test; public class HibernateTest { private SessionFactory sessionFactory; private Session session; private Transaction transaction; @Before public void init(){ // 1. 创建一个 SessionFactory 对象 StandardServiceRegistry standardServiceRegistry = new StandardServiceRegistryBuilder() .configure("hibernate.cfg.xml").build(); Metadata metadata = new MetadataSources(standardServiceRegistry).addAnnotatedClass(Customer.class) .addAnnotatedClassName("hibernate.sessiondemo.Customer").addResource("/hibernate/sessiondemo/Customer.hbm.xml") .getMetadataBuilder().applyImplicitNamingStrategy(ImplicitNamingStrategyJpaCompliantImpl.INSTANCE) .build(); sessionFactory = metadata.getSessionFactoryBuilder().build(); // 2. 创建一个 Session对象 session = sessionFactory.openSession(); System.out.println(session); // 3. 开启事务 transaction = session.beginTransaction(); } @After public void destroy(){ // 5. 提交事务 transaction.commit(); // 6. 关闭session session.close(); // 7. 关闭sessionFactory对象 sessionFactory.close(); } @Test public void testDelete(){ //在不设定级联关系的情况下,且1 这一端的对象有 n端的引用, 不能直接删除1 这一端的对象 Customer customer = session.get(Customer.class, 5); session.delete(customer); } @Test public void testUpdate(){ /* Hibernate: select order0_.ORDER_ID as ORDER_ID1_1_0_, order0_.ORDER_NAME as ORDER_NA2_1_0_, order0_.CUSTOMER_ID as CUSTOMER3_1_0_ from ORDERS order0_ where order0_.ORDER_ID=? Hibernate: select customer0_.CUSTOMER_ID as CUSTOMER1_0_0_, customer0_.CUSTOMER_NAME as CUSTOMER2_0_0_ from CUSTOMERS customer0_ where customer0_.CUSTOMER_ID=? Hibernate: update CUSTOMERS set CUSTOMER_NAME=? where CUSTOMER_ID=? */ Order order = (Order) session.get(Order.class, 1); order.getCustomer().setCustomerName("Liang Yongqi"); } @Test public void testManyToOneGet(){ /* Hibernate: select order0_.ORDER_ID as ORDER_ID1_1_0_, order0_.ORDER_NAME as ORDER_NA2_1_0_, order0_.CUSTOMER_ID as CUSTOMER3_1_0_ from ORDERS order0_ where order0_.ORDER_ID=? Hibernate: select customer0_.CUSTOMER_ID as CUSTOMER1_0_0_, customer0_.CUSTOMER_NAME as CUSTOMER2_0_0_ from CUSTOMERS customer0_ where customer0_.CUSTOMER_ID=? Order [orderId=1, orderName=ORDER_1, customer=Customer [customerId=5, customerName=Zhang Xueyou]] */ /* Order order = session.get(Order.class, 1); System.out.println(order);*/ //1. 若查询多的一端的一个对象,则默认情况下,只查询了多的一端的对象,而没有查询关联的那一端的对象 Order order = (Order) session.load(Order.class, 1); System.out.println(order.getOrderName()); //2. 在需要使用到关联的对象时,才会发送对应的SQL 语句。 Customer customer = order.getCustomer(); System.out.println(customer.getCustomerName()); System.out.println(order.getCustomer().getClass().getName()); //3. 再查询Customer 对象时, 由多的一端导航到1的一端时候, // 若此时session 已被关闭, 则默认情况下,会发生懒加载异常 //4. 获取Order 对象时, 默认情况下, 其关联的Customer 对象是一个代理对象! } /** Hibernate: create table CUSTOMERS ( CUSTOMER_ID integer not null auto_increment, CUSTOMER_NAME varchar(255), primary key (CUSTOMER_ID) ) ENGINE=InnoDB Hibernate: create table ORDERS ( ORDER_ID integer not null auto_increment, ORDER_NAME varchar(255), CUSTOMER_ID integer, primary key (ORDER_ID) ) ENGINE=InnoDB Hibernate: alter table ORDERS add constraint FKflgddyesjyik2ro2p501yys8r foreign key (CUSTOMER_ID) references CUSTOMERS (CUSTOMER_ID) */ @Test public void testManyToOneSaveFirstSave1(){ //若先插入customer 再插入order, 会直接执行3条INSERT 语句 /*Hibernate: insert into CUSTOMERS (CUSTOMER_NAME) values (?) Hibernate: insert into ORDERS (ORDER_NAME, CUSTOMER_ID) values (?, ?) Hibernate: insert into ORDERS (ORDER_NAME, CUSTOMER_ID) values (?, ?)*/ Customer customer = new Customer(); customer.setCustomerName("Zhang Xueyou"); Order order1 = new Order(); order1.setOrderName("ORDER_1"); order1.setCustomer(customer); Order order2 = new Order(); order2.setOrderName("ORDER_2"); order2.setCustomer(customer); session.save(customer); session.save(customer); session.save(customer); session.save(customer); session.save(order1); session.save(order2); } @Test public void testManyToOneSaveFirstSaveN(){ //若先插入order 再插入customer, 会先执行3条INSERT 语句,再执行2条UPADTE 语句, 因为在CUSTOMER执行保存以前, CUSTOMER_ID是一个空值,还没办法确定外键值。 /*Hibernate: insert into ORDERS (ORDER_NAME, CUSTOMER_ID) values (?, ?) Hibernate: insert into ORDERS (ORDER_NAME, CUSTOMER_ID) values (?, ?) Hibernate: insert into CUSTOMERS (CUSTOMER_NAME) values (?) Hibernate: update ORDERS set ORDER_NAME=?, CUSTOMER_ID=? where ORDER_ID=? Hibernate: update ORDERS set ORDER_NAME=?, CUSTOMER_ID=? where ORDER_ID=?*/ Customer customer = new Customer(); customer.setCustomerName("Zhang Xinzhe"); Order order3 = new Order(); order3.setOrderName("ORDER_3"); order3.setCustomer(customer); Order order4 = new Order(); order4.setOrderName("ORDER_4"); order4.setCustomer(customer); session.save(order3); session.save(order4); session.save(customer); } }