hibernate多对一关联映射两种形式的理解
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hibernate多对一关联映射两种形式的理解相关的知识,希望对你有一定的参考价值。
关联是类(类的实例)之间的关系,表示有意义和值得关注的连接。
多对一单向和多对一双向关联:
单向:多对一单向是只用维护多的一方,例如一家厂商(Factory)可以生产多种产品(Product),只用在Product实体类和配置文件中配置即可。
在Product实体属性类中,需要有Factory属性,而不再需要外键这个属性,因为关联外键的配置在配置文件中many-to-one。
双向:多对一双向关联需要双方都维护对方,例如班级(Class)和学生(Student)之间的关系,需要在Class实体类和Class映射文件中配置维护Student,
one-to-many,在Class实体类属性中,需要用Set集合存储Student。
也需要在Student实体类和Student映射文件中配置维护Class,many-to-one,在Product实体属性中,同样需要有Factory属性。
文件结构:
hibernate核心配置文件
Hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- 配置数据库连接驱动类 --> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <!-- 配置数据库连接字符串 --> <property name="connection.url"><![CDATA[jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8]]></property> <!-- 配置数据库连接用户名 --> <property name="connection.username">root</property> <!-- 配置数据库连接密码 --> <property name="connection.password">123456</property> <!-- 配置数据库方言 --> <property name="dialect">org.hibernate.dialect.MySQLDialect</property> <!-- 配置数据库表生成策略 --> <!--<property name="hibernate.hbm2ddl.auto">update</property> --> <!-- 配置是否打印显示SQL语句 --> <property name="show_sql">true</property> <!-- 配置是否格式化显示SQL语句 --> <property name="format_sql">true</property> <!-- 配置hibernate是否自动提交事务 --> <!--<property name="hibernate.connection.autocommit">true</property> --> <!-- 配置实体类对应的映射文件 --> <mapping resource="com/great/entity/Class.hbm.xml"></mapping> <mapping resource="com/great/entity/Student.hbm.xml"></mapping> <mapping resource="com/great/entity1/Product.hbm.xml"></mapping> <mapping resource="com/great/entity1/Factory.hbm.xml"></mapping> </session-factory> </hibernate-configuration>
多对一单向关联:
Factory.java
package com.great.entity1; public class Factory { // 厂商类 // 厂商id private int fId; // 厂商名字 private String fName; public int getfId() { return fId; } public void setfId(int fId) { this.fId = fId; } public String getfName() { return fName; } public void setfName(String fName) { this.fName = fName; } }
Product.java
package com.great.entity1; public class Product { // 多对一单向关联 // 产品类 // 产品id private int pId; // 产品名字 private String pName; // 厂商 private Factory factory; public int getpId() { return pId; } public void setpId(int pId) { this.pId = pId; } public String getpName() { return pName; } public void setpName(String pName) { this.pName = pName; } public Factory getFactory() { return factory; } public void setFactory(Factory factory) { this.factory = factory; } }
Factory.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"> <hibernate-mapping package="com.great.entity1"> <class name="Factory" table="factory"> <!-- 配置主键映射关系 --> <id name="fId" column="fId" type="int"> <!-- 配置主键生成策略 --> <generator class="identity"> </generator> </id> <!-- 配置属性和表字段映射关系 --> <property name="fName" column="fName" type="string"></property> </class> </hibernate-mapping>
Product.hbm.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" > <hibernate-mapping package="com.great.entity1"> <!-- 配置实体类与数据库表的映射关系 --> <class name="Product" table="Product"> <!-- 配置主键映射关系 --> <id name="pId" column="pId" type="int"> <!-- 配置主键生成策略 --> <generator class="identity"> </generator> </id> <!-- 配置属性和表字段映射关系 --> <property name="pName" column="pName" type="string"></property> <!-- 多对一关联关系配置 --> <!-- many-to-one标签声明多对一关联关系,name指定多方所维护的一方的实例名 --> <many-to-one name="factory" class="com.great.entity1.Factory" cascade="save-update"> <!-- column标签指定关联外键,还是子表的外键列名 --> <column name="fId"></column> </many-to-one> </class> </hibernate-mapping>
TestManyToOneUnidirectional.java
package com.great.test; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; import com.great.entity1.Product; public class TestManyToOneUnidirectional { static Session session; // 多对一单向关联 @BeforeClass public static void setUpBeforeClass() throws Exception { // 加载hibernate主配置文件 Configuration cfg = new Configuration().configure(); // 构建session工厂 SessionFactory sf = cfg.buildSessionFactory(); // 打开session session = sf.openSession(); } @AfterClass public static void tearDownAfterClass() throws Exception { // 关闭session,释放资源 session.close(); } // 查询产品名字和厂家 @Test public void testManyToOneSelect() { Product p = (Product) session.get(Product.class, 1); System.out.println("产品名字为:" + p.getpName()); System.out.println("产品厂家为:" + p.getFactory().getfName()); } }
数据库:
factory:
product:
多对一双向关联:
Class.java
package com.great.entity; import java.util.HashSet; import java.util.Set; import com.great.entity.Student; public class Class { // 班级id private int cId; // 班级名字 private String cName; // 注意点:必须new一个Set的实现类的实例 // 原因:子表不一定有主表的关联数据,所以可能取出空集合,引发空指针异常 private Set<Student> students = new HashSet<Student>(); public int getcId() { return cId; } public void setcId(int cId) { this.cId = cId; } public String getcName() { return cName; } public void setcName(String cName) { this.cName = cName; } public Set<Student> getStudents() { return students; } public void setStudents(Set<Student> students) { this.students = students; } @Override public String toString() { return "Class [cId=" + cId + ", cName=" + cName + ", students=" + students + "]"; } }
Student.java
package com.great.entity; import com.great.entity.Class; public class Student { private int id; private String sName; // 多对一映射时,因为要维护一的一方的实例,所以外键不需要映射 // private int cId; private Class classes; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getsName() { return sName; } public void setsName(String sName) { this.sName = sName; } public Class getClasses() { return classes; } public void setClasses(Class classes) { this.classes = classes; } }
Class.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"> <hibernate-mapping package="com.great.entity"> <class name="Class" table="class"> <!-- 配置主键映射关系 --> <id name="cId" column="cId" type="int"> <!-- 配置主键生成策略 --> <generator class="identity"> </generator> </id> <!-- 配置属性和表字段映射关系 --> <property name="cName" column="cName" type="string"></property> <!-- 一对多关联关系配置 --> <!-- inverse属性设置为true代表一的一方不在拥有关联关系的控制权,而把控制权交给多的一方 --> <!-- fetch属性用来指定子表数据的抓取策略,默认值为"select",代表对主表子表进行单独查询 ,对主表子表单独发select语句--> <!-- fetch属性用来指定子表数据的抓取策略,设置为"join"时,代表对主表子表进行关联查询,对主表子表发出关联查询语句 --> <!-- lazy属性用来指定子表数据是否延迟加载,fetch="select"时起作用,fetch="join"时不起作用 --> <!-- fetch="select" lazy="true" --> <set name="students" cascade="all" inverse="true" > <!-- key配置的是子表的外键列名 --> <key column="cId"></key> <!-- one-to-many标签声明关联关系是一对多,class指定多方的实体类类型 --> <one-to-many class="com.great.entity.Student"/> </set> </class> </hibernate-mapping>
Student.hbm.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" > <hibernate-mapping package="com.great.entity"> <!-- 配置实体类与数据库表的映射关系 --> <class name="Student" table="student"> <!-- 配置主键映射关系 --> <id name="id" column="sId" type="int"> <!-- 配置主键生成策略 --> <generator class="identity"> </generator> </id> <!-- 配置属性和表字段映射关系 --> <property name="sName" column="sName" type="string"></property> <!-- 多对一关联关系配置 --> <!-- many-to-one标签声明多对一关联关系,name指定多方所维护的一方的实例名 --> <many-to-one name="classes" class="com.great.entity.Class" cascade="save-update"> <!-- column标签指定关联外键,还是子表的外键列名 --> <column name="cId"></column> </many-to-one> </class> </hibernate-mapping>
数据库:
class:
student:
以上是关于hibernate多对一关联映射两种形式的理解的主要内容,如果未能解决你的问题,请参考以下文章