Hibernate inverse 深度解析

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

 

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

 

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

 

  一。Company.java

 

package com.template.model.company;

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

/**
 * Created by IntelliJ IDEA.
 * User: Zhong Gang
 * Date: 11-8-9
 * Time: 下午9:02
 */
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);
    }
}

 

  二。Company.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 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>

 

  三。Branch.java

 

package com.template.model.company;

/**
 * Created by IntelliJ IDEA.
 * User: Zhong Gang
 * Date: 11-8-9
 * Time: 下午9:02
 */
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;
    }
}

 

  四。Branch.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 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>

 

  五。测试类HibernateInverseTest.java

 

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;

/**
 * Created by IntelliJ IDEA.
 * User: Zhong Gang
 * Date: 11-8-8
 * Time: 下午10:03
 */
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", "root");
        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=false时,Hibernate就只需要操作三条语句就可以建立起Company与Branch之间的一对多的关联关系,因为插入branch1和branch2的时候也为它们赋予了companyid的值。所以可以看出inverse为true或false,达到的结果一样,实现的过程却截然不同。出于执行效率的考虑,建议将inverse设置为true,即由多方来维护一对多的关联关系。

 

 

你可能感兴趣的:(Hibernate,inverse)