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,即由多方来维护一对多的关联关系。