JPA关系映射之one-to-many和many-to-one(另inverse=“true”解析)

one-to-many(一对多)和many-to-one(多对一)双向关联

假设部门与员工是一对多关系,反过来员工与部门就是多对一关系。

Dept.java类

public class Dept implements java.io.Serializable {

    private Integer deptId;
    private String deptName;
    private Set<Emp> emps=new HashSet<Emp>();

}

Emp.java类

public class Emp implements java.io.Serializable {

    private Integer empNo;
    private String empName;
    private Date empBrithday;
    private Dept dept;

}

Dept.hbm.xml

<hibernate-mapping>
    <class name="com.db.entity.Dept" table="dept" catalog="mydb">
        <id name="deptId" type="java.lang.Integer">
            <column name="deptId" />
            <generator class="native" />
        </id>
        <property name="deptName" type="java.lang.String">
            <column name="deptName" length="32" />
        </property>
        <set name="emps" inverse="true" cascade="all">
            <key column="deptId" not-null="true" />
            <one-to-many class="com.db.entity.Emp" />
        </set>
    </class>
</hibernate-mapping>

Emp.hbm.xml

<hibernate-mapping>
    <class name="com.db.entity.Emp" table="emp" catalog="mydb">
        <id name="empNo" type="java.lang.Integer">
            <column name="empNo" />
            <generator class="native" />
        </id>
        <property name="empName" type="java.lang.String">
            <column name="empName" length="20" />
        </property>
        <property name="empBrithday" type="java.util.Date">
            <column name="empBrithday"/>
        </property>
        <many-to-one name="dept" column="deptId" class="com.db.entity.Dept" not-null="true"  fetch="select" cascade="save-update,delete"/>
    </class>
</hibernate-mapping>

hibernate.cfg.xml

<hibernate-configuration>

    <session-factory>
        <property name="dialect">
            org.hibernate.dialect.MySQLDialect
        </property>
        <property name="connection.url">
            jdbc:mysql://localhost:3306/mydb
        </property>
        <property name="connection.username">root</property>
        <property name="connection.password">123456</property>
        <property name="connection.driver_class">
            com.mysql.jdbc.Driver
        </property>
        <property name="myeclipse.connection.profile">
            MyDBAccount
        </property>
        <mapping resource="com/db/entity/Dept.hbm.xml" />
        <mapping resource="com/db/entity/Emp.hbm.xml" />
    </session-factory>

</hibernate-configuration>

测试用例

public class TestOneMany {

    public static void main(String[] args) throws ParseException {
        // TODO Auto-generated method stub

        Session session=HibernateSessionFactory.getSession();
        Dept dept1=new Dept();
        dept1.setDeptName("开发部");
        Emp emp1=new Emp();
        emp1.setEmpName("王洋");
        String brithString="1999-03-05";
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
        Date brithday=sdf.parse(brithString);
        emp1.setEmpBrithday(brithday);
        Emp emp2=new Emp();
        emp2.setEmpName("李林");
        brithString="2005-02-07";
        brithday=sdf.parse(brithString);
        emp2.setEmpBrithday(brithday);
        //把emp和dpt分别添加到对方的实力对象中
        dept1.getEmps().add(emp1);
        dept1.getEmps().add(emp2);
        emp1.setDept(dept1);
        emp2.setDept(dept1);
        session.beginTransaction();
        session.save(dept1);
        session.getTransaction().commit();
    }

}

注意:

在一的set配置中声明inverse=“true”,意味着Dept不在作为主控方,将关联关系的维护工作交给关联对象Emp来完成。

在保存dept1对象的时不在关心Emp类中dept属性对应的deptId列,必须由Emp自己去维护,即设置emp.setDept(dept)  

上述操作完成的sql语句是:

Hibernate: insert into mydb.dept (deptName) values (?)
Hibernate: insert into mydb.emp (empName, empBrithday, deptId) values (?, ?, ?)
Hibernate: insert into mydb.emp (empName, empBrithday, deptId) values (?, ?, ?)

扫描二维码关注公众号,回复: 3799402 查看本文章

inverse=“true”解析

在一对多关联中,在一的一方设置inverse="true",有助于性能的改善

Inverse是hibernate双向关系中的基本概念。
inverse的真正作用就是指定由哪一方来维护之间的关联关系。
当一方中指定了“inverse=false”(默认),那么那一方就有责任负责之间的关联关系,说白了就是hibernate如何生成Sql来维护关联的记录。

Inverse:负责控制关系,默认为false,也就是关系的两端都能控制,但这样会造成一些问题,更新的时候会因为两端都控制关系,于是重复更新一般来说有一端要设为true。

Cascade:负责控制关联对象的级联操作,包括更新、删除等,也就是说对一个对象进行更新、删除时,其它对象也受影响,比如我删除一个对象,那么跟它是多对一关系的对象也全部被删除。

举例说明区别:

删除“一”那一端一个对象O的时候,如果“多”的那一端的Inverse设为true,则把“多”的那一端所有与O相关联的对象外键清空;如果“多”的那一端的Cascade设为Delete,则把“多”的那一端所有与O相关联的对象全部删除。


还有些需要注意:

不要在有序集合如list,array中使用inverse, 

<!-- <list name="emps">
<key column="depart_id"/>
<list-index column="order_col"/>
<one-to-many class="Employee"/>
</list> -->

你想,他都不去维护他们的映射关系了,又怎会关心他们添加的顺序


来源于:

https://www.cnblogs.com/SaraMoring/p/5631429.html

https://wenda.so.com/q/1450912342729693

http://www.cnblogs.com/qingmaple/p/4116641.html

猜你喜欢

转载自blog.csdn.net/weixin_41888813/article/details/83013139