Hibernate(九):基于主键映射的1-1关联关系
- 背景:
在实际开发中我们会遇到新建一个用户表,但这个表字段过长,而且有写字段常用(主要),有些字段比较不常用(次要)。此时,我们会考虑到把用户信息拆分到两张表中:member(存储用户主要信息),memberdetail(存储用户次要信息)。
那么,这两个表就是很明显是一对一的关系,一个用户的基本信息只需要存储一份。
上一章节我们介绍了在hibernate中一对一的关联关系通过外键来实现,本章节我们将会介绍,在hibernate中使用主键来实现一对一的关联关系。
- hibernate实现过程中,需要注意事项:
1)基于主键的映射策略:指一端的主键生成器使用foreign策略,表明根据“对方”的主键来生成自己的主键,自己并不能独立生成主键。<param>子元素指定使用当前持久化类的哪个属性作为“对方”。
2)采用foriegn主键生成器策略的一端增加one-to-one元素映射关联属性,其one-to-one属性还应该增加constranied="true"属性;另一端增加one-to-one元素映射关联属性。
3)constrained(约束):指定为当前持久化类对应的数据库表的主键添加一个外间约束,引用被关联的对象(“对方”)所对应的数据表主键。
- 测试:
新建工程hibernate6,在src下新建包com.dx.hibernate005.onetoonebyprimary,
在包下新建Member.java
1 package com.dx.hibernate005.onetoonebyprimary; 2 3 import java.util.Date; 4 5 public class Member { 6 private Integer id; 7 private String username; 8 private String password; 9 private Date createTime; 10 private MemberDetail memberDetail; 11 12 public Member() { 13 super(); 14 } 15 16 public Member(String username, String password, Date createTime) { 17 super(); 18 this.username = username; 19 this.password = password; 20 this.createTime = createTime; 21 } 22 23 public Integer getId() { 24 return id; 25 } 26 27 public void setId(Integer id) { 28 this.id = id; 29 } 30 31 public String getUsername() { 32 return username; 33 } 34 35 public void setUsername(String username) { 36 this.username = username; 37 } 38 39 public String getPassword() { 40 return password; 41 } 42 43 public void setPassword(String password) { 44 this.password = password; 45 } 46 47 public Date getCreateTime() { 48 return createTime; 49 } 50 51 public void setCreateTime(Date createTime) { 52 this.createTime = createTime; 53 } 54 55 public MemberDetail getMemberDetail() { 56 return memberDetail; 57 } 58 59 public void setMemberDetail(MemberDetail memberDetail) { 60 this.memberDetail = memberDetail; 61 } 62 63 }
Member.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-5 15:39:57 by Hibernate Tools 3.5.0.Final --> 5 <hibernate-mapping package="com.dx.hibernate005.onetoonebyprimary"> 6 <class name="Member" table="MEMBER"> 7 <id name="id" type="java.lang.Integer"> 8 <column name="ID" /> 9 <generator class="native" /> 10 </id> 11 <property name="username" type="java.lang.String"> 12 <column name="USERNAME" /> 13 </property> 14 <property name="password" type="java.lang.String"> 15 <column name="PASSWORD" /> 16 </property> 17 <property name="createTime" type="java.util.Date"> 18 <column name="CREATETIME" /> 19 </property> 20 <one-to-one name="memberDetail" class="com.dx.hibernate005.onetoonebyprimary.MemberDetail"></one-to-one> 21 </class> 22 </hibernate-mapping>
MemberDetail.java
1 package com.dx.hibernate005.onetoonebyprimary; 2 3 import java.util.Date; 4 5 public class MemberDetail { 6 private Integer memberId; 7 private Date birthDay; 8 private String address; 9 private Member member; 10 11 public MemberDetail() { 12 super(); 13 } 14 15 public MemberDetail(Date birthDay, String address) { 16 super(); 17 this.birthDay = birthDay; 18 this.address = address; 19 } 20 21 public Integer getMemberId() { 22 return memberId; 23 } 24 25 public void setMemberId(Integer memberId) { 26 this.memberId = memberId; 27 } 28 29 public Date getBirthDay() { 30 return birthDay; 31 } 32 33 public void setBirthDay(Date birthDay) { 34 this.birthDay = birthDay; 35 } 36 37 public String getAddress() { 38 return address; 39 } 40 41 public void setAddress(String address) { 42 this.address = address; 43 } 44 45 public Member getMember() { 46 return member; 47 } 48 49 public void setMember(Member member) { 50 this.member = member; 51 } 52 }
MemberDetail.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-5 15:39:57 by Hibernate Tools 3.5.0.Final --> 5 <hibernate-mapping package="com.dx.hibernate005.onetoonebyprimary"> 6 <class name="MemberDetail" table="MEMBERDETAIL"> 7 <id name="memberId" type="java.lang.Integer"> 8 <column name="MEMBERID" /> 9 <generator class="foreign"> 10 <param name="property">member</param> 11 </generator> 12 </id> 13 <property name="birthDay" type="java.util.Date"> 14 <column name="BIRTHDAY" /> 15 </property> 16 <property name="address" type="java.lang.String"> 17 <column name="ADDRESS" /> 18 </property> 19 <one-to-one name="member" class="com.dx.hibernate005.onetoonebyprimary.Member" constrained="true"></one-to-one> 20 </class> 21 </hibernate-mapping>
在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/onetoonebyprimary/Member.hbm.xml" /> 32 <mapping resource="com/dx/hibernate005/onetoonebyprimary/MemberDetail.hbm.xml" /> 33 34 <!-- 35 <mapping class="com.dx.hibernate005.onetoonebyprimary.Member" /> 36 <mapping class="com.dx.hibernate005.onetoonebyprimary.MemberDetail" /> 37 --> 38 </session-factory> 39 </hibernate-configuration>
添加测试类TestMain.java
1 package com.dx.hibernate005.onetoonebyprimary; 2 3 import java.util.Date; 4 5 import org.hibernate.Session; 6 import org.hibernate.SessionFactory; 7 import org.hibernate.Transaction; 8 import org.hibernate.boot.Metadata; 9 import org.hibernate.boot.MetadataSources; 10 import org.hibernate.boot.model.naming.ImplicitNamingStrategyComponentPathImpl; 11 import org.hibernate.boot.registry.StandardServiceRegistry; 12 import org.hibernate.boot.registry.StandardServiceRegistryBuilder; 13 import org.junit.After; 14 import org.junit.Before; 15 import org.junit.Test; 16 17 public class TestMain { 18 private SessionFactory sessionFactory = null; 19 private Session session = null; 20 private Transaction transaction = null; 21 22 @Before 23 public void init() { 24 StandardServiceRegistry standardRegistry = new StandardServiceRegistryBuilder().configure().build(); 25 Metadata metadata = new MetadataSources(standardRegistry).getMetadataBuilder().applyImplicitNamingStrategy(ImplicitNamingStrategyComponentPathImpl.INSTANCE).build(); 26 27 sessionFactory = metadata.getSessionFactoryBuilder().build(); 28 session = sessionFactory.getCurrentSession(); 29 transaction = session.beginTransaction(); 30 } 31 32 @After 33 public void destory() { 34 transaction.commit(); 35 session.close(); 36 sessionFactory.close(); 37 } 38 }
添加测试函数,执行测试1:
1 @Test 2 public void testInsert() { 3 Member member = new Member("user1","123456",new Date()); 4 MemberDetail memberDetail = new MemberDetail(new Date(),"address1"); 5 6 member.setMemberDetail(memberDetail); 7 memberDetail.setMember(member); 8 9 session.save(memberDetail); 10 session.save(member); 11 }
输出sql:
1 Hibernate: 2 3 create table MEMBER ( 4 ID integer not null auto_increment, 5 USERNAME varchar(255), 6 PASSWORD varchar(255), 7 CREATETIME datetime, 8 primary key (ID) 9 ) engine=InnoDB 10 Hibernate: 11 12 create table MEMBERDETAIL ( 13 MEMBERID integer not null, 14 BIRTHDAY datetime, 15 ADDRESS varchar(255), 16 primary key (MEMBERID) 17 ) engine=InnoDB 18 Hibernate: 19 20 alter table MEMBERDETAIL 21 add constraint FKsfbbuql27qw1ym706tof0nwcf 22 foreign key (MEMBERID) 23 references MEMBER (ID) 24 Hibernate: 25 insert 26 into 27 MEMBER 28 (USERNAME, PASSWORD, CREATETIME) 29 values 30 (?, ?, ?) 31 Hibernate: 32 insert 33 into 34 MEMBERDETAIL 35 (BIRTHDAY, ADDRESS, MEMBERID) 36 values 37 (?, ?, ?)
添加测试函数,执行测试2:
1 @Test 2 public void testSelect() { 3 // 1.查询时,没采用懒加载。 4 Member member = (Member) session.get(Member.class, 1); 5 System.out.println(member.getUsername()); 6 7 // 2.不会出现懒加载异常问题 8 session.close(); 9 MemberDetail memberDetail = member.getMemberDetail(); 10 System.out.println(memberDetail.getClass()); 11 System.out.println(memberDetail.getAddress()); 12 }
添加测试函数,执行测试3:
1 @Test 2 public void testSelectMemberDetail() { 3 // 1.查询时,采用懒加载。 4 MemberDetail memberDetail = session.get(MemberDetail.class, 1); 5 System.out.println(memberDetail.getAddress()); 6 7 // 2.会出现懒加载异常问题 8 session.close(); 9 System.out.println(memberDetail.getMember().getUsername()); 10 }
添加测试函数,执行测试4:
1 @Test 2 public void testUpdate() { 3 // // 1) session关闭时,修改执行 4 // Member member = session.get(Member.class, 1); 5 // member.setUsername("Mgr11112"); 6 // // 或 session.update(member); 7 // // 或 session.save(member); 8 // // 或 不需要任何操作,关闭session自动保存 9 // 10 // MemberDetail memberDetail = session.get(MemberDetail.class, 1); 11 // memberDetail.setAddress("address111112"); 12 // // 或 session.update(memberDetail); 13 // // 或 session.save(memberDetail); 14 // // 或 不需要任何操作,关闭session自动保存 15 16 // // 2)通过Member 关联修改MemberDetai 17 // Member member = session.get(Member.class, 1); 18 // member.setUsername("Mgr"); 19 // member.getMemberDetail().setAddress("Address"); 20 21 // 3)通过MemberDetai 关联修改Member 22 MemberDetail memberDetail = session.get(MemberDetail.class, 1); 23 memberDetail.setAddress("Address333"); 24 memberDetail.getMember().setUsername("Mgr333"); 25 }
添加测试函数,执行测试5:
1 @Test 2 public void testDelete() { 3 // // 1)Member表中有记录与之关联时,删除失败 4 // Member member = session.get(Member.class, 1); 5 // session.delete(member); 6 7 // 2)删除成功,只删除了MemberDetail表中的记录,Member表中的记录并没有删除,之后再删除Member就不会出现错误。 8 MemberDetail memberDetail = session.get(MemberDetail.class, 1); 9 session.delete(memberDetail); 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 原理;加载过程的。。。
【+加关注】。