您的位置:首页 > 其它

hibernate多对一关联配置

2014-09-04 16:43 429 查看
实体是Employee和Department,它们之间是多对一的关系。

Department类:

Java代码


public class Department {

private int id;

private String name;

public Department() {

}

public Department(String name) {

this.name = name;

}

// getters and setters are omitted

}

Employee类:

Java代码


public class Employee {

private int id;

private String name;

private Department department;

public Employee() {

}

public Employee(String name) {

this.name = name;

}

// getters and setters are omitted

Department.hbm.xml:

Xml代码


<hibernate-mapping

package="com.john.myhibernate.domain">

<class name="Department">

<id name="id">

<generator class="native"/>

</id>

<property name="name" length="20" not-null="true"/>

</class>

</hibernate-mapping>

Employee.hbm.xml:

Xml代码


<hibernate-mapping package="com.john.myhibernate.domain">

<class name="Employee">

<id name="id">

<generator class="native"/>

</id>

<property name="name" length="20" not-null="true"/>

<many-to-one name="department" column="department_id" class="Department" fetch="select"/>

</class>

</hibernate-mapping>

many-to-one没有inverse属性,因为关系的维护是many的一方,不可能放弃对关系的维护。

many-to-one的lazy属性有三个取值:false, proxy, no-proxy。

1. 测试cascade属性:

Java代码


public void testSaveCascade() {

Session s = null;

Transaction tx = null;

Department depart = new Department();

depart.setName("FCI");

Employee em1 = new Employee("John");

em1.setDepartment(depart);

Employee em2 = new Employee("Lucy");

em2.setDepartment(depart);

try {

s = HibernateUtil.getSession();

tx = s.beginTransaction();

s.save(em1);

s.save(em2);

tx.commit();

} catch (HibernateException e) {

tx.rollback();

e.printStackTrace();

} finally {

if (s != null)

s.close();

}

}

结果是报org.hibernate.TransientObjectException异常,因为没有保存Department实例。

可以加cascade属性,解决问题:

Xml代码


<many-to-one name="department" column="department_id" class="Department" fetch="select" cascade="save-update"/>

2. 测试fetch

Java代码


Session s = null;

s = HibernateUtil.getSession();

Employee em = (Employee) s.get(Employee.class, 2);

System.out.println(em.getName());

System.out.println(em.getDepartment());

查询语句如下:

Hibernate: select employee0_.id as id1_0_, employee0_.name as name1_0_, employee0_.department as department1_0_, employee0_.skill as skill1_0_, employee0_.sell
as sell1_0_, employee0_.type as type1_0_ from Employee employee0_ where employee0_.id=?

Hibernate: select department0_.id as id0_0_, department0_.name as name0_0_ from Department department0_ where department0_.id=?

因为fetch设置为select,所以对每个实体,都分别用一个SELECT语句

如果把fetch设置为join,也就是连表查询,只使用一个SELECT语句。如下:

Hibernate: select employee0_.id as id1_1_, employee0_.name as name1_1_, employee0_.department as department1_1_, employee0_.skill as skill1_1_, employee0_.sell
as sell1_1_, employee0_.type as type1_1_, department1_.id as id0_0_, department1_.name as name0_0_ from Employee employee0_ left outer join Department department1_ on employee0_.department=department1_.id where employee0_.id=?

3. 测试lazy

当fetch为select时,设置lazy为proxy或者no-proxy。

Xml代码


<many-to-one name="department" column="department_id" class="Department" fetch="select" cascade="save-update" lazy="no-proxy"/>

Java代码


Session s = null;

s = HibernateUtil.getSession();

Employee em = (Employee) s.get(Employee.class, 2);

s.close();

System.out.println(em.getName());

System.out.println(em.getDepartment());

结果是报org.hibernate.LazyInitializationException异常。

因为fetch为select,而且lazy为proxy或者no-proxy,所以开始仅仅查询Employee,当需要用SELECT语句查询Department时,Session已经关闭。

解决办法:

1. 设置lazy为false,hibernate会第一时间把Employee和Department查询出来。

如果fetch为select,使用两个SELECT查询语句。

如果fetch为join,使用一个SELECT连表查询语句。

2. 设置fetch为join,这时不管lazy的取值,hibernate会进行连表查询,把两个实体都查询出来。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: