hibernate inverse

本文深入探讨了Hibernate配置文件中inverse属性在一对多关联中的作用,通过实例解析了其对关联关系建立过程及性能的影响,并提供了设置inverse属性的建议。

 

   inverse 英文意思为反向,倒转的。

  Hibernate配置文件中的inverse正是这一意思的真实反映,inverse属性只在Hibernate配置文件的集合元素上存在,如bag,list,map,set等。inverse有两个值,分别为true和false,如果inverse=false,表明控制权在一对多关联关系的一方;如果inverse=true,表明控制权在一对多关联关系的多方。
 

  下面以公司与分公司为例来说明inverse的作用。一个公司有多个分支,一个分支又只属于一个公司。


 

package com.template.model.company;

import java.util.ArrayList;
import java.util.List;

public class Company {
    private Integer id;
    private String name;

    private List<Branch> branches;

    public Company() {
    }
    
    public Company(String name) {
        this.name = name;
    }

    public void addBranch(Branch branch) {
        if (branches == null) {
            branches = new ArrayList<Branch>();
        }
        branches.add(branch);
    }
}

<?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 default-access="field">

    <class name="com.template.model.company.Company" table="company" dynamic-insert="true" dynamic-update="true">
        <id name="id" column="id" type="java.lang.Integer">
            <generator class="native"/>
        </id>
        <property name="name" column="name" type="java.lang.String"/>

        <bag name="branches" table="branch" inverse="false" cascade="all">
            <key column="companyid"/>
            <one-to-many class="com.template.model.company.Branch"/>
        </bag>
    </class>

</hibernate-mapping>

package com.template.model.company;

public class Branch {
    private Integer id;
    private String name;

    private Company company;

    public Branch() {
    }

    public Branch(String name) {
        this.name = name;
    }

    public Branch(String name, Company company) {
        this.name = name;
        this.company = company;
    }
}

<?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 default-access="field">

    <class name="com.template.model.company.Branch" table="branch" dynamic-insert="true" dynamic-update="true">
        <id name="id" column="id" type="java.lang.Integer">
            <generator class="native"/>
        </id>
        <property name="name" column="name" type="java.lang.String"/>

        <many-to-one name="company" class="com.template.model.company.Company" column="companyid"/>
    </class>

</hibernate-mapping>

import com.template.model.company.Branch;
import com.template.model.company.Company;
import junit.framework.TestCase;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.classic.Session;

import java.util.Properties;

public class HibernateInverseTest extends TestCase {
    private SessionFactory sessionFactory = null;

    @Override
    public void setUp() throws Exception {
        Properties properties = new Properties();
        properties.setProperty("hibernate.connection.driver_class", "com.mysql.jdbc.Driver");
        properties.setProperty("hibernate.connection.url", "jdbc:mysql://localhost:3306/demo");
        properties.setProperty("hibernate.connection.username", "root");
        properties.setProperty("hibernate.connection.password", "qq123456");
        properties.setProperty("hibernate.show_sql", "true");
        properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
        properties.setProperty("hibernate.hbm2ddl.auto", "update");

        Configuration configuration = new Configuration();
        configuration.addResource("hibernate_mappings/Company.hbm.xml");
        configuration.addResource("hibernate_mappings/Branch.hbm.xml");
        configuration.setProperties(properties);
        sessionFactory = configuration.buildSessionFactory();
    }

    public void testInverse() throws Exception {
        Session session = sessionFactory.openSession();

        Company company = new Company("company");

        Branch branch1 = new Branch("branch one", company);
        Branch branch2 = new Branch("branch two", company);

        company.addBranch(branch1);
        company.addBranch(branch2);

        Transaction transaction = session.getTransaction();
        transaction.begin();

        session.saveOrUpdate(company);

        transaction.commit();
    }
}

注意:在Company的持久化配置文件Company.hbm.xml中,bag元素的inverse属性为false

 

  六。inverse=false时,测试运行结果

  inverse_false

 

  七。将Company.hbm.xml配置文件中的inverse值改为true。inverse=true时,测试运行结果

  inverse_true

 

  从上面两张截图上发现,当inverse=false时,也就是说控制权在Company对象上时,Hibernate多操作了两条update语句。关于inverse的true和false的值的区别。可以这样来理解,当inverse=false时,Hibernate首先会逐条插入company,branch1,branch2,这个时候Hibernate并不会维护Company与Branch之间的一对多的关联关系,也就是说当插入branch1,branch2时,companyid的值是null,然后Hibernate会再多发出两条update语句,用于建立Company与Branch之间的一对多的关联关系。而当inverse=true时,Hibernate就只需要操作三条语句就可以建立起Company与Branch之间的一对多的关联关系,因为插入branch1和branch2的时候也为它们赋予了companyid的值。所以可以看出inverse为true或false,达到的结果一样,实现的过程却截然不同。出于执行效率的考虑,建议将inverse设置为true,即由多方来维护一对多的关联关系。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值