1.有一张表是有外键的(指向另外一张表的主键),而且外键是唯一性的约束.另外一张表是没有外键的,只是他会有个one-to-one来关联有外键的那个表的外键字段.这样就可以通过本端主键和另外一端的外键相等来通过本端(无外键)来查找有外键的那一段(hibernate)默认会发送联合查询的sql语句
//3. 查询 Manager 对象的连接条件应该是 dept.manager_id = mgr.manager_id //而不应该是on manager0_.MA_ID=department1_.DEPT_ID // 正确的:on manager0_.MA_ID=department1_.MA_ID <!-- 映射 1-1 的关联关系: 在对应的数据表中已经有外键了, 当前持久化类使用 one-to-one 进行映射 --> <!-- 没有外键的一端需要使用one-to-one元素,该元素使用 property-ref 属性指定使用被关联实体主键以外的字段作为关联字段 也就是说,它会去找:Department表,property-ref="managerId"属性对应的列名(column="MA_ID")称来作为联合查询的条件 不然联合查询会出现错误.:默认会去关联另外一个表的主键 这样不会在该表中产生外键或者索引 property-ref="managerId" --> <one-to-one name="dpatId" class="com.hgh.hibernate.oto.foreign.Department" property-ref="managerId"></one-to-one> <many-to-one name="managerId" class="com.hgh.hibernate.oto.foreign.Manager" column="MA_ID" unique="true"></many-to-one>Department
package com.hgh.hibernate.oto.foreign; public class Department { private Integer deptId; private String deptName; private Manager managerId; public Integer getDeptId() { return deptId; } public void setDeptId(Integer deptId) { this.deptId = deptId; } public String getDeptName() { return deptName; } public void setDeptName(String deptName) { this.deptName = deptName; } public Manager getManagerId() { return managerId; } public void setManagerId(Manager managerId) { this.managerId = managerId; } }Manager
package com.hgh.hibernate.oto.foreign; public class Manager { private Integer maId; private String maName; private Department dpatId; public Integer getMaId() { return maId; } public void setMaId(Integer maId) { this.maId = maId; } public String getMaName() { return maName; } public void setMaName(String maName) { this.maName = maName; } public Department getDpatId() { return dpatId; } public void setDpatId(Department dpatId) { this.dpatId = dpatId; } } <?xml version="1.0"?> <!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.hgh.hibernate.oto.foreign.Department" table="DEPARTMENT"> <id name="deptId" type="java.lang.Integer"> <column name="DEPT_ID" /> <generator class="native" /> </id> <property name="deptName" type="java.lang.String"> <column name="DEPT_NAME" /> </property> <many-to-one name="managerId" class="com.hgh.hibernate.oto.foreign.Manager" column="MA_ID" unique="true"></many-to-one> </class> </hibernate-mapping> <?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 2017-4-14 15:26:19 by Hibernate Tools 3.4.0.CR1 --> <hibernate-mapping> <class name="com.hgh.hibernate.oto.foreign.Manager" table="MANAGER"> <id name="maId" type="java.lang.Integer"> <column name="MA_ID" /> <generator class="native" /> </id> <property name="maName" type="java.lang.String"> <column name="MA_NAME" /> </property> <!-- 映射 1-1 的关联关系: 在对应的数据表中已经有外键了, 当前持久化类使用 one-to-one 进行映射 --> <!-- 没有外键的一端需要使用one-to-one元素,该元素使用 property-ref 属性指定使用被关联实体主键以外的字段作为关联字段 也就是说,它会去找:Department表,property-ref="managerId"属性对应的列名(column="MA_ID")称来作为联合查询的条件 不然联合查询会出现错误.:默认会去关联另外一个表的主键 这样不会在该表中产生外键或者索引 property-ref="managerId" --> <one-to-one name="dpatId" class="com.hgh.hibernate.oto.foreign.Department" property-ref="managerId"></one-to-one> </class> </hibernate-mapping> package com.hgh.hibernate.oto.foreign; import static org.junit.Assert.*; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.sql.Blob; import java.sql.Connection; import java.sql.SQLException; import java.util.Date; import org.hibernate.Hibernate; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.hibernate.jdbc.Work; import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistryBuilder; import org.junit.After; import org.junit.Before; import org.junit.Test; public class HibernateTest { private SessionFactory SessionFactory; private ServiceRegistry ServiceRegistry; private Transaction transaction; private Session session; @Before public void init(){ System.out.println("init"); Configuration configuration = new Configuration().configure(); ServiceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()) .buildServiceRegistry(); SessionFactory = configuration.buildSessionFactory(ServiceRegistry); session = SessionFactory.openSession(); transaction = session.beginTransaction(); } @After public void destroy(){ System.out.println("destroy"); transaction.commit(); session.close(); SessionFactory.close(); } @Test public void test2(){ /* * select manager0_.MA_ID as MA_ID1_1_1_, manager0_.MA_NAME as MA_NAME2_1_1_, department1_.DEPT_ID as DEPT_ID1_0_0_, department1_.DEPT_NAME as DEPT_NAM2_0_0_, department1_.MA_ID as MA_ID3_0_0_ from MANAGER manager0_ left outer join DEPARTMENT department1_ on manager0_.MA_ID=department1_.MA_ID where manager0_.MA_ID=? */ //用无外键,有one to one的表查询,会吧关联的也查询出来 //在查询没有外键的实体对象时, 使用的左外连接查询, 一并查询出其关联的对象 //并已经进行初始化. Manager manager = (Manager) session.get(Manager.class, 1); System.out.println(manager.getMaName()); System.out.println(manager.getDpatId().getDeptName()); } @Test public void testGet(){ //1. 默认情况下对关联属性使用懒加载 Department department = (Department) session.get(Department.class, 1); System.out.println(department.getDeptName()); //2. 所以会出现懒加载异常的问题. // session.close(); // Manager manager = department.getManagerId(); // System.out.println(manager.getClass().getName()); // System.out.println(manager.getMaName()); //3. 查询 Manager 对象的连接条件应该是 dept.manager_id = mgr.manager_id //而不应该是on manager0_.MA_ID=department1_.DEPT_ID // 正确的:on manager0_.MA_ID=department1_.MA_ID Manager manager = department.getManagerId(); System.out.println(manager.getMaName()); } @Test public void testSave(){ Department department = new Department(); Manager manager = new Manager(); department.setDeptName("d1"); department.setManagerId(manager); manager.setMaName("m1"); manager.setDpatId(department); session.save(department); session.save(manager); } }