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时,测试运行结果
七。将Company.hbm.xml配置文件中的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,即由多方来维护一对多的关联关系。