Hibernate(八):基于外键映射的1-1关联关系
- 背景:
一个部门只有一个一把手,这在程序开发中就会设计数据映射应该设置为一对一关联。
在hibernate代码开发中,实现这个业务有两种方案:
1)基于外键映射的1-1关联;
2)基于主键映射的1-1关联。
本篇文章主要是用来学习如何使用外键实现1-1关联关系。
- 新建项目hibernate05
新建java project,引入依赖包,在src下添加hibernate.cfg.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-configuration PUBLIC 3 "-//Hibernate/Hibernate Configuration DTD 3.0//EN" 4 "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> 5 <hibernate-configuration> 6 <session-factory> 7 <property name="hibernate.connection.username">root</property> 8 <property name="hibernate.connection.password">123456</property> 9 <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> 10 <property name="hibernate.connection.url">jdbc:mysql://localhost/hibernate_01</property> 11 12 <!-- <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> 13 <property name="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</property> --> 14 <property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property> 15 16 <property name="hibernate.show_sql">true</property> 17 18 <property name="hibernate.format_sql">true</property> 19 20 <property name="hibernate.hbm2ddl.auto">update</property> 21 22 <property name="hibernate.current_session_context_class">thread</property> 23 24 <property name="hibernate.c3p0.max_size">500</property> 25 <property name="hibernate.c3p0.min_size">20</property> 26 <property name="hibernate.c3p0.max_statements">10</property> 27 <property name="hibernate.c3p0.timeout">2000</property> 28 <property name="hibernate.c3p0.idle_test_period">2000</property> 29 <property name="hibernate.c3p0.acquire_increment">10</property> 30 31 <mapping resource="com/dx/hibernate005/onetoonebyforigenkey/Deparment.hbm.xml" /> 32 <mapping class="com.dx.hibernate005.onetoonebyforigenkey.Deparment" /> 33 <mapping resource="com/dx/hibernate005/onetoonebyforigenkey/Manager.hbm.xml" /> 34 <mapping class="com.dx.hibernate005.onetoonebyforigenkey.Manager" /> 35 </session-factory> 36 </hibernate-configuration>
在src下新建包com.dx.hibernate005.onetoonebyforigenkey
在com.dx.hibernate005.onetoonebyforigenkey包下创建
Deparment.java
1 package com.dx.hibernate005.onetoonebyforigenkey; 2 3 public class Deparment { 4 private Integer departId; 5 private String departName; 6 private Manager manager; 7 8 public Deparment() { 9 super(); 10 } 11 12 public Deparment(Integer departId, String departName) { 13 super(); 14 this.departId = departId; 15 this.departName = departName; 16 } 17 18 public Integer getDepartId() { 19 return departId; 20 } 21 22 public void setDepartId(Integer departId) { 23 this.departId = departId; 24 } 25 26 public String getDepartName() { 27 return departName; 28 } 29 30 public void setDepartName(String departName) { 31 this.departName = departName; 32 } 33 34 public Manager getManager() { 35 return manager; 36 } 37 38 public void setManager(Manager manager) { 39 this.manager = manager; 40 } 41 42 }
Deparment.hbm.xml
1 <?xml version="1.0"?> 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 4 <!-- Generated 2017-6-2 10:54:26 by Hibernate Tools 3.5.0.Final --> 5 <hibernate-mapping> 6 <class name="com.dx.hibernate005.onetoonebyforigenkey.Deparment" table="DEPARMENTS"> 7 <id name="departId" type="java.lang.Integer"> 8 <column name="DEPART_ID" /> 9 <generator class="native" /> 10 </id> 11 <property name="departName" type="java.lang.String"> 12 <column name="DEPART_NAME" /> 13 </property> 14 15 <!-- 在Deparment中定义一个Many-to-one就可以实现在Deparments表中多一个外键列 --> 16 <many-to-one name="manager" class="com.dx.hibernate005.onetoonebyforigenkey.Manager" column="MANAGER_ID" unique="true"></many-to-one> 17 </class> 18 </hibernate-mapping>
Manager.java
1 package com.dx.hibernate005.onetoonebyforigenkey; 2 3 public class Manager { 4 private Integer managerId; 5 private String managerName; 6 private Deparment deparment; 7 8 public Manager() { 9 super(); 10 } 11 12 public Manager(Integer managerId, String managerName) { 13 super(); 14 this.managerId = managerId; 15 this.managerName = managerName; 16 } 17 18 public Integer getManagerId() { 19 return managerId; 20 } 21 22 public void setManagerId(Integer managerId) { 23 this.managerId = managerId; 24 } 25 26 public String getManagerName() { 27 return managerName; 28 } 29 30 public void setManagerName(String managerName) { 31 this.managerName = managerName; 32 } 33 34 public Deparment getDeparment() { 35 return deparment; 36 } 37 38 public void setDeparment(Deparment deparment) { 39 this.deparment = deparment; 40 } 41 42 }
Deparment.hbm.xml
1 <?xml version="1.0"?> 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 4 <!-- Generated 2017-6-2 10:54:26 by Hibernate Tools 3.5.0.Final --> 5 <hibernate-mapping> 6 <class name="com.dx.hibernate005.onetoonebyforigenkey.Manager" table="MANAGERS"> 7 <id name="managerId" type="java.lang.Integer"> 8 <column name="MANAGER_ID" /> 9 <generator class="native" /> 10 </id> 11 <property name="managerName" type="java.lang.String"> 12 <column name="MANAGER_NAME" /> 13 </property> 14 15 <!-- 在对应的数据表中已经有了外键,当前持久化类使用one-to-one进行映射 --> 16 <one-to-one name="deparment" class="com.dx.hibernate005.onetoonebyforigenkey.Deparment" property-ref="manager"></one-to-one> 17 </class> 18 </hibernate-mapping>
TestMain.java测试类,并引入JUnit4所需的依赖包。
package com.dx.hibernate005.onetoonebyforigenkey; 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.ImplicitNamingStrategyComponentPathImpl; import org.hibernate.boot.registry.StandardServiceRegistry; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.junit.After; import org.junit.Before; import org.junit.Test; public class TestMain { private SessionFactory sessionFactory = null; private Session session = null; private Transaction transaction = null; @Before public void init() { StandardServiceRegistry standardRegistry = new StandardServiceRegistryBuilder().configure().build(); Metadata metadata = new MetadataSources(standardRegistry).getMetadataBuilder().applyImplicitNamingStrategy(ImplicitNamingStrategyComponentPathImpl.INSTANCE).build(); sessionFactory = metadata.getSessionFactoryBuilder().build(); session = sessionFactory.getCurrentSession(); transaction = session.beginTransaction(); } @After public void destory() { transaction.commit(); session.close(); sessionFactory.close(); } }
运行空测试类,初始化sql:
1 Hibernate: 2 3 create table DEPARMENTS ( 4 DEPART_ID integer not null auto_increment, 5 DEPART_NAME varchar(255), 6 MANAGER_ID integer, 7 primary key (DEPART_ID) 8 ) engine=InnoDB 9 Hibernate: 10 11 create table MANAGERS ( 12 MANAGER_ID integer not null auto_increment, 13 MANAGER_NAME varchar(255), 14 primary key (MANAGER_ID) 15 ) engine=InnoDB 16 Hibernate: 17 18 alter table DEPARMENTS 19 drop index UK_j9bdvgylyeboig73ntlfcuyf6 20 Hibernate: 21 22 alter table DEPARMENTS 23 add constraint UK_j9bdvgylyeboig73ntlfcuyf6 unique (MANAGER_ID) 24 Hibernate: 25 26 alter table DEPARMENTS 27 add constraint FKnlmf88ii3maigw7hgc182cqi4 28 foreign key (MANAGER_ID) 29 references MANAGERS (MANAGER_ID)
- 测试:
1)测试insert:
1 @Test 2 public void testInsert(){ 3 Deparment deparment=new Deparment(); 4 deparment.setDepartName("Depart1"); 5 6 Manager manager=new Manager(); 7 manager.setManagerName("manager1"); 8 9 deparment.setManager(manager); 10 manager.setDeparment(deparment); 11 12 session.save(manager); 13 session.save(deparment); 14 } 15
测试通过,测试打印sql
1 Hibernate: 2 insert 3 into 4 MANAGERS 5 (MANAGER_NAME) 6 values 7 (?) 8 Hibernate: 9 insert 10 into 11 DEPARMENTS 12 (DEPART_NAME, MANAGER_ID) 13 values 14 (?, ?)
2)测试select
1 @Test 2 public void testSelect() { 3 // 1.查询时,采用懒加载。 4 Deparment deparment = (Deparment) session.get(Deparment.class, 1); 5 System.out.println(deparment.getDepartName()); 6 7 // // 2.会出现懒加载异常问题 8 // session.close(); 9 // Manager manager = deparment.getManager(); 10 // System.out.println(manager.getClass()); 11 // System.out.println(manager.getManagerName()); 12 }
3)测试Select Manager
1 @Test 2 public void testSelectManager() { 3 // 1.查询时,没采用懒加载。 4 Manager manager = session.get(Manager.class, 1); 5 System.out.println(manager.getManagerName()); 6 7 // 2.不会出现懒加载异常问题 8 session.close(); 9 System.out.println(manager.getDeparment().getDepartName()); 10 }
4)测试修改
1 @Test 2 public void testUpdate() { 3 // // 1) session关闭时,修改执行 4 // Manager manager = session.get(Manager.class, 1); 5 // manager.setManagerName("Mgr11111"); 6 // // session.save(manager); 7 // 8 // Deparment deparment = session.get(Deparment.class, 1); 9 // deparment.setDepartName("Depart111111"); 10 // // session.save(deparment); 11 12 // // 2)通过manager 关联修改deparment 13 // Manager manager = session.get(Manager.class, 1); 14 // manager.setManagerName("Mgr222"); 15 // manager.getDeparment().setDepartName("DEPT22"); 16 17 // 3)通过department关联修改manager 18 Deparment deparment = session.get(Deparment.class, 1); 19 deparment.setDepartName("DPT333"); 20 deparment.getManager().setManagerName("Mgr333"); 21 }
5)测试删除
1 @Test 2 public void testDelete() { 3 // 1)在department表中有记录与之关联时,删除失败 4 // Manager manager = session.get(Manager.class, 1); 5 // session.delete(manager); 6 7 // 2)删除成功,只删除了deparment表中的记录,manger表中的记录并没有删除,之后再删除manager就不会出现错误。 8 Deparment deparment = session.get(Deparment.class, 1); 9 session.delete(deparment); 10 }
基础才是编程人员应该深入研究的问题,比如:
1)List/Set/Map内部组成原理|区别
2)mysql索引存储结构&如何调优/b-tree特点、计算复杂度及影响复杂度的因素。。。
3)JVM运行组成与原理及调优
4)Java类加载器运行原理
5)Java中GC过程原理|使用的回收算法原理
6)Redis中hash一致性实现及与hash其他区别
7)Java多线程、线程池开发、管理Lock与Synchroined区别
8)Spring IOC/AOP 原理;加载过程的。。。
【+加关注】。