您的位置:首页 > 其它

Hibernate 多对一关联查询

2016-06-19 16:25 246 查看

版权声明:本文为博主原创文章,[b]如需转载请标注转载地址。[/b]

博客地址:http://www.cnblogs.com/caoyc/p/5598269.html

一、单向多对一和双向多对一的区别

  如果只需要从一方获取另一方数据,就用单向多对一;如果需要从双方都获取对方数据,就用双向多对一。

  如果有两个对象,一个为User对象,一个为Department对象,一个用户只能属于一个部门,而一个部门可以包含多个用户。这样就是多对一关系。如下图

  


    假设:我们需要通过用户找到所对应的部门,不需要通过部门查询该部门有哪些用户,就采用单向多对一关系

    如果:我们不仅需要通过用户获取所对应的部门,还需要通过部门对象获取该部门下的用户,那么就采用双向多对一

二、单向多对一关系

  Department.java

package com.proc.pojo;

import java.io.Serializable;

public class Department implements Serializable {

private Integer id;
private String deptname;

//提供构造方法
public Department() {
}

public Department(String deptname) {
this.deptname = deptname;
}

//getter和setter实现
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getDeptname() {
return deptname;
}
public void setDeptname(String deptname) {
this.deptname = deptname;
}
}


  User.java

package com.proc.pojo;

import java.io.Serializable;

public class User implements Serializable {

private Integer id;
private String name;
private Department dept;

//提供构造方法
public User() {
}
public User(String name) {
this.name = name;
}
//getter和setter实现
public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Department getDept() {
return dept;
}
public void setDept(Department dept) {
this.dept = dept;
}
}


  Department.hbm.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.proc.pojo">
<class name="Department" table="department">
<id name="id" type="int">
<generator class="native"></generator>
</id>
<property name="deptname" length="20" not-null="true"></property>
</class>
</hibernate-mapping>


  User.hbm.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.proc.pojo">
<class name="User">
<id name="id" type="int">
<generator class="native"></generator>
</id>
<property name="name" length="20" not-null="true"></property>
<many-to-one name="dept" column="deptid" class="Department" ></many-to-one>
</class>
</hibernate-mapping>


  代码讲解:在配置User(多)->Department(一)时,采用外键映射,其中

  name="dept":User对象dept属性

  class="Department":表示该dept属性的类型是Department类型,因为User和Department在同一个包中,所以直接使用了类名称

  column="deptid":指定在用user表中,对应department表的中主键的列为deptid

  这里并没有指出user表中deptid对应的值department表中哪一列,默认为主键,这里也会自动给deptid列添加一个外键约束

  foreign-key="none":不创建外键约束,如果将none改成其他的,即为指定外键名称

  测试代码:

package com.proc.test;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.Test;

import com.proc.pojo.Department;
import com.proc.pojo.User;

public class TestOneToMany {

private static SessionFactory factory=new Configuration()
.configure()
.addClass(User.class)
.addClass(Department.class)
.buildSessionFactory();
@Test
public void set(){

Session session=factory.openSession();
Transaction tran=session.beginTransaction();
Department dept1=new Department("IT部");

User user1=new User("caoyc");
User user2=new User("zhh");

user1.setDept(dept1);
user2.setDept(dept1);

session.save(dept1);
session.save(user1);
session.save(user2);

tran.commit();
session.close();
}
}


   在控制台输出SQL语句:

Hibernate: create table department (id integer not null auto_increment, deptname varchar(20) not null, primary key (id))
Hibernate: create table User (id integer not null auto_increment, name varchar(20) not null, deptid integer, primary key (id))
Hibernate: alter table User add constraint FK66lqw6kl2gcxhs44gamc91fbd foreign key (deptid) references department (id)

Hibernate: insert into department (deptname) values (?)
Hibernate: insert into User (name, deptid) values (?, ?)
Hibernate: insert into User (name, deptid) values (?, ?)

测试:如果将测试代码中32-34行代码改成

session.save(user1);
session.save(user2);
session.save(dept1);


  在控制台输出SQL语句:

Hibernate: create table department (id integer not null auto_increment, deptname varchar(20) not null, primary key (id))
Hibernate: create table User (id integer not null auto_increment, name varchar(20) not null, deptid integer, primary key (id))
Hibernate: alter table User add constraint FK66lqw6kl2gcxhs44gamc91fbd foreign key (deptid) references department (id)

Hibernate: insert into User (name, deptid) values (?, ?)
Hibernate: insert into User (name, deptid) values (?, ?)
Hibernate: insert into department (deptname) values (?)
Hibernate: update User set name=?, deptid=? where id=?
Hibernate: update User set name=?, deptid=? where id=?

  这里多出了两行update User代码,也就是在我们先添加向user表中插入数据时,而还在department总还没有数据,当插入department数据后,在通过update的方式来修改user表

  总结:在我们插入多对一关系时,需要先保存(一)的一方,然后在保存(多)的一方,这样可以减少SQL执行语句,如果是单向多对一关系,在添加多对一关系,只需要在(多)的一方的映射文件(.hbm.xml)中添加many-to-one就可以了

单向多对一删除操作:

  a、删除(多)的一方(User),删除成功

  b、删除(一)的一方(Department),如果user表中没有该部门的用户,则删除成功

  c、删除(一)的一方(Department),如果user表中还有改部门的用户,则删除失败,因为有外键约束

三、双向多对一操作

  第一步:在Department.java中添加一个users属性,并提供get和set方法

private Set<User> users;
public Set<User> getUsers() {
return users;
}
public void setUsers(Set<User> users) {
this.users = users;
}


  第二步:在Department.hbm.xml中添加关联映射



既可以通过User的到Department,也可以通过Department得到Set<User>

双向多对一删除:

  a、删除(多)的一方,总是成功

  b、删除(少)的一方,如果inverse=“false”,成功

  c、删除(少)的一方,如果inverse=“true”,失败
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: