您的位置:首页 > 其它

Hibernate学习-7-关联映射(一对多,多对一)

2016-12-08 18:03 344 查看
关联映射
需求分析

eg 1-

部门与员工的例子

一个部门有多个员工[一对多]

多个员工,属于一个部门[多对一]

eg 2-

一个项目多个开发人员

一个开发人员参与多个项目 [多对多]

一对多与多对一映射

一.需求分析

二.数据库

t_dept

字段:deptId deptName

t_employee

字段:empId empName salary dept_id

三.javabean

设计关键:通过一方维护到另一方

class Dept{

private int deptId;

private String deptName;

//部门对应多个员工
private Set<Employee> emps;

}

class Employee{

private int empId;

private String empName;

private double salary;

//多个员工对应一个部门
private Dept dept;
}


四.映射

Dept映射关键点

1.映射的集合属性:"emps"

2.指定集合属性对应的集合表:"t_employee"

3.指定集合表的外键字段

4.指定集合元素的类型

Employee映射的关键点

1.映射的部门属性: dept

2.映射的部门对象,对应的外键字段:dept_id

3.部门的类型

实例-保存数据-查询数据

总配置文件

<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
<session-factory>
<!--1.数据库连接配置-->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql:///learnHibernate</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">33269456.cx</property>
<!--
数据库方言配置,hibernate会根据不同的方言生成符合当前数据库语法的sql
-->
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>

<!--2.其他相关配置-->
<!--2.1显示运行时的sql语句-->
<property name="hibernate.show_sql">true</property>

<!--2.2格式化sql-->

<property name="hibernate.format_sql">true</property>

<!--2.3自动建表,写好映射就可以-->

<property name="hibernate.hbm2ddl.auto">update</property>

<!--3.加载所有映射-->

</session-factory>

</hibernate-configuration>


Dept.java

package com.cx.entity;

import java.util.HashSet;
import java.util.Set;

/**
* Created by cxspace on 16-8-2.
*/
public class Dept {

private int deptId;

private String deptName;

//一对多(一个部门对应多个员工)
private Set<Employee> employees = new HashSet<>();

public int getDeptId() {
return deptId;
}

public void setDeptId(int deptId) {
this.deptId = deptId;
}

public String getDeptName() {
return deptName;
}

public void setDeptName(String deptName) {
this.deptName = deptName;
}

public Set<Employee> getEmployees() {
return employees;
}

public void setEmployees(Set<Employee> employees) {
this.employees = employees;
}
}


相关映射配置

<?xml version="1.0"?>
<!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.cx.entity">

<class name="Dept" table="t_dept">

<id name="deptId">
<generator class="native"></generator>
</id>

<property name="deptName" length="20"></property>

<!--
1.映射的集合属性:"emps"

2.指定集合属性对应的集合表:"t_employee"

3.指定集合表的外键字段

4.指定集合元素的类型
-->

<!--table="t_employee",可以省略-->

<set name="employees" table="t_employee">
<key column="dept_id"></key>
<one-to-many class="Employee"></one-to-many>
</set>

</class>

</hibernate-mapping>


Employee.java

package com.cx.entity;

/**
* Created by cxspace on 16-8-2.
*/
public class Employee {

private int empId;

private String empName;

private double salary;

private Dept dept;

public Dept getDept() {
return dept;
}

public void setDept(Dept dept) {
this.dept = dept;
}

public int getEmpId() {
return empId;
}

public void setEmpId(int empId) {
this.empId = empId;
}

public String getEmpName() {
return empName;
}

public void setEmpName(String empName) {
this.empName = empName;
}

public double getSalary() {
return salary;
}

public void setSalary(double salary) {
this.salary = salary;
}
}


相关映射配置

<?xml version="1.0"?>
<!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.cx.entity">

<class name="Employee" table="t_employee">
<id name="empId">
<generator class="native"></generator>
</id>

<property name="empName" length="20"></property>

<property name="salary" type="double"></property>

<!--
多对一映射配置
Employee 映射关键点:
1.  映射的部门属性  :  dept
2.  映射的部门属性,对应的外键字段: dept_id
3.  部门的类型
-->

<many-to-one name="dept" column="dept_id" class="Dept"></many-to-one>

</class>

</hibernate-mapping>


测试类

package com.cx.test;

import com.cx.entity.Dept;
import com.cx.entity.Employee;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.Test;

/**
* Created by cxspace on 16-8-2.
*/
public class Save {

private static SessionFactory sf;
static {
sf = new Configuration()
.configure()
.addClass(Dept.class)
.addClass(Employee.class)   // 测试时候使用
.buildSessionFactory();
}

//保存,部门方 一对一方法操作

public void save(){

Session session = sf.openSession();
session.beginTransaction();

//部门对象
Dept dept = new Dept();
dept.setDeptName("应用开发部");

//员工对象
Employee emp_zs = new Employee();

emp_zs.setEmpName("张三");

Employee emp_ls = new Employee();

emp_ls.setEmpName("李四");

//关系
dept.getEmployees().add(emp_zs);
dept.getEmployees().add(emp_ls);

//保存

session.save(emp_zs);
session.save(emp_ls);

session.save(dept);

session.getTransaction().commit();
session.close();

/*
*

Hibernate:
insert
into
t_employee
(empName, salary, dept_id)
values
(?, ?, ?)
Hibernate:
insert
into
t_employee
(empName, salary, dept_id)
values
(?, ?, ?)
Hibernate:
insert
into
t_dept
(deptName)
values
(?)
Hibernate:
update
t_employee
set
dept_id=?
where
empId=?
Hibernate:
update
t_employee
set
dept_id=?
where
empId=?

* */

}

//保存,员工方[多对一保存],效率更高
@Test

public void save2(){

Session session = sf.openSession();
session.beginTransaction();

Dept dept = new Dept();
dept.setDeptName("综合部");

Employee emp_zs = new Employee();
emp_zs.setEmpName("张三");

Employee emp_ls = new Employee();
emp_ls.setEmpName("李四");

emp_zs.setDept(dept);
emp_ls.setDept(dept);

session.save(dept);
session.save(emp_ls);
session.save(emp_zs);

session.getTransaction().commit();
session.close();

/*
*
* 结果
*
*   Hibernate:
insert
into
t_dept
(deptName)
values
(?)
Hibernate:
insert
into
t_employee
(empName, salary, dept_id)
values
(?, ?, ?)
Hibernate:
insert
into
t_employee
(empName, salary, dept_id)
values
(?, ?, ?)
*
*
* */

}

}


结果





package com.cx.test;

import com.cx.entity.Dept;
import com.cx.entity.Employee;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.Test;

/**
* Created by cxspace on 16-8-2.
*/
public class Get {

private static SessionFactory sf;
static {
sf = new Configuration()
.configure()
.addClass(Dept.class)
.addClass(Employee.class)   // 测试时候使用
.buildSessionFactory();
}

@Test
public void get(){

Session session = sf.openSession();
session.beginTransaction();

//通过部门方获取另一方
//        Dept dept = (Dept) session.get(Dept.class , 1);
//        System.out.println(dept.getDeptName());
//        System.out.println(dept.getEmployees());

结果

Hibernate:
select
dept0_.deptId as deptId0_0_,
dept0_.deptName as deptName0_0_
from
t_dept dept0_
where
dept0_.deptId=?
应用开发部
Hibernate:
select
employees0_.dept_id as dept4_0_1_,
employees0_.empId as empId1_,
employees0_.empId as empId1_0_,
employees0_.empName as empName1_0_,
employees0_.salary as salary1_0_,
employees0_.dept_id as dept4_1_0_
from
t_employee employees0_
where
employees0_.dept_id=?
[com.cx.entity.Employee@d35dea7, com.cx.entity.Employee@24313fcc]

//通过员工获取部门
Employee emp = (Employee)session.get(Employee.class,1);
System.out.println(emp.getEmpName());
System.out.println(emp.getDept().getDeptName());

session.getTransaction().commit();
session.close();

结果

Hibernate:
select
employee0_.empId as empId1_0_,
employee0_.empName as empName1_0_,
employee0_.salary as salary1_0_,
employee0_.dept_id as dept4_1_0_
from
t_employee employee0_
where
employee0_.empId=?
张三
Hibernate:
select
dept0_.deptId as deptId0_0_,
dept0_.deptName as deptName0_0_
from
t_dept dept0_
where
dept0_.deptId=?
应用开发部

}

}


Inverse属性

在维护关联关系的时候起作用。表示控制权是否转移。(在一的一方起作用)

inverse 控制反转

inverse = false不反转 有控制权

= true 控制反转 没有控制权 (不能主动维护另一方)

维护关联关系

1.保存数据

设计关联

如果设置控制反转,然后通过部门方维护关联关系。在保存部门的时候,同时保存员工,数据会保存,但关联关系不会维护,外键字段为NULL。

2.获取数据

无影响

3.解除关联关系

有影响

没有控制权无法接触关联关系,无法生成update语句,也不会报错

4.删除数据对关联关系的影响

有控制权,可以删除,先清空外键引用,再删除。

没控制权报错,无法删除。

测试代码

package com.cx.test;

import com.cx.entity.Dept;
import com.cx.entity.Employee;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.Test;

/**
* Created by cxspace on 16-8-2.
*/
public class Inverse {

private static SessionFactory sf;
static {
sf = new Configuration()
.configure()
.addClass(Dept.class)
.addClass(Employee.class) // 测试时候使用
.buildSessionFactory();
}

//inverse对保存数据的影响
public void save(){

Session session = sf.openSession();
session.beginTransaction();

//部门对象
Dept dept = new Dept();
dept.setDeptName("运维部");

//员工对象
Employee emp_zs = new Employee();

emp_zs.setEmpName("张三");

Employee emp_ls = new Employee();

emp_ls.setEmpName("李四");

//关系
dept.getEmployees().add(emp_zs);
dept.getEmployees().add(emp_ls);

//inverse = true ,不会设置关联,此时的关联应该通过员工方来维护

//保存

session.save(emp_zs);
session.save(emp_ls);

session.save(dept);

session.getTransaction().commit();
session.close();

/*
*
*
*
Hibernate:
insert
into
t_employee
(empName, salary, dept_id)
values
(?, ?, ?)
Hibernate:
insert
into
t_employee
(empName, salary, dept_id)
values
(?, ?, ?)
Hibernate:
insert
into
t_dept
(deptName)
values
(?)
*
*
* */

}

//inverse属性,对获取数据的影响---无影响

public void get(){
Session session = sf.openSession();
session.beginTransaction();

Dept dept = (Dept) session.get(Dept.class,2);

System.out.println(dept.getDeptName());
System.out.println(dept.getEmployees());

session.getTransaction().commit();
session.close();

/*
*
*
*
* Hibernate:
select
dept0_.deptId as deptId0_0_,
dept0_.deptName as deptName0_0_
from
t_dept dept0_
where
dept0_.deptId=?
综合部
Hibernate:
select
employees0_.dept_id as dept4_0_1_,
employees0_.empId as empId1_,
employees0_.empId as empId1_0_,
employees0_.empName as empName1_0_,
employees0_.salary as salary1_0_,
employees0_.dept_id as dept4_1_0_
from
t_employee employees0_
where
employees0_.dept_id=?
[com.cx.entity.Employee@d35dea7, com.cx.entity.Employee@24313fcc]
*
*
*
*
*
*
*
* */

}

public void removeRelation(){

Session session = sf.openSession();
session.beginTransaction();

Dept dept = (Dept)session.get(Dept.class,2);

dept.getEmployees().clear();

session.getTransaction().commit();
session.close();

/*
* inverse=true 没有控制权
*
*
Hibernate:
select
dept0_.deptId as deptId0_0_,
dept0_.deptName as deptName0_0_
from
t_dept dept0_
where
dept0_.deptId=?
*
*
*
inverse = false

Hibernate:
select
dept0_.deptId as deptId0_0_,
dept0_.deptName as deptName0_0_
from
t_dept dept0_
where
dept0_.deptId=?
Hibernate:
select
employees0_.dept_id as dept4_0_1_,
employees0_.empId as empId1_,
employees0_.empId as empId1_0_,
employees0_.empName as empName1_0_,
employees0_.salary as salary1_0_,
employees0_.dept_id as dept4_1_0_
from
t_employee employees0_
where
employees0_.dept_id=?
Hibernate:
update
t_employee
set
dept_id=null
where
dept_id=?

*
* */

}

@Test
public void deleteData(){
Session session = sf.openSession();
session.beginTransaction();

Dept dept = (Dept) session.get(Dept.class,1);
session.delete(dept);

session.getTransaction().commit();
session.close();

/*
inverse = true
Hibernate:

select
dept0_.deptId as deptId0_0_,
dept0_.deptName as deptName0_0_
from
t_dept dept0_
where
dept0_.deptId=?
Hibernate:
delete
from
t_dept
where
deptId=?

报错
org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update

at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:96)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:268)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:189)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:383)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:133)
at com.cx.test.Inverse.deleteData(Inverse.java:217)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.internal.runners.TestMethodRunner.executeMethodBody(TestMethodRunner.java:99)
at org.junit.internal.runners.TestMethodRunner.runUnprotected(TestMethodRunner.java:81)
at org.junit.internal.runners.BeforeAndAfterRunner.runProtected(BeforeAndAfterRunner.java:34)
at org.junit.internal.runners.TestMethodRunner.runMethod(TestMethodRunner.java:75)
at org.junit.internal.runners.TestMethodRunner.run(TestMethodRunner.java:45)
at org.junit.internal.runners.TestClassMethodsRunner.invokeTestMethod(TestClassMethodsRunner.java:66)
at org.junit.internal.runners.TestClassMethodsRunner.run(TestClassMethodsRunner.java:35)
at org.junit.internal.runners.TestClassRunner$1.runUnprotected(TestClassRunner.java:42)
at org.junit.internal.runners.BeforeAndAfterRunner.runProtected(BeforeAndAfterRunner.java:34)
at org.junit.internal.runners.TestClassRunner.run(TestClassRunner.java:52)
at org.junit.runner.JUnitCore.run(JUnitCore.java:130)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:119)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Caused by: java.sql.BatchUpdateException: Cannot delete or update a parent row: a foreign key constraint fails (`learnHibernate`.`t_employee`, CONSTRAINT `FKFDCF5A195CFBCEF9` FOREIGN KEY (`dept_id`) REFERENCES `t_dept` (`deptId`))
at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:2054)
at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:1467)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268)
... 32 more

inverse = false

正常删除

Hibernate:
select
dept0_.deptId as deptId0_0_,
dept0_.deptName as deptName0_0_
from
t_dept dept0_
where
dept0_.deptId=?
Hibernate:
update
t_employee
set
dept_id=null
where
dept_id=?
Hibernate:
delete
from
t_dept
where
deptId=?

*/} }


cascade属性

表示级联操作

none不级联操作 ,默认值

save-update级联保存或者更新

delete级联删除

save-update,delete 级联保存、更新、删除

all 同上

实例

package com.cx.test;

import com.cx.entity.Dept;
import com.cx.entity.Employee;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.Test;

/**
* Created by cxspace on 16-8-2.
*/
public class Cascade {

private static SessionFactory sf;
static {
sf = new Configuration()
.configure()
.addClass(Dept.class)
.addClass(Employee.class) // 测试时候使用
.buildSessionFactory();
}

//级联保存

@Test
public void save(){

Session session = sf.openSession();
session.beginTransaction();

Dept dept = new Dept();
dept.setDeptName("人事部");

Employee emp_zs = new Employee();
emp_zs.setEmpName("张三");
Employee emp_ls = new Employee();
emp_ls.setEmpName("李四");
// 关系
dept.getEmployees().add(emp_zs);
dept.getEmployees().add(emp_ls);

//设置了级联只要保存部门
session.save(dept);

session.getTransaction().commit();
session.close();

/*
*
* Hibernate:
insert
into
t_dept
(deptName)
values
(?)
Hibernate:
insert
into
t_employee
(empName, salary, dept_id)
values
(?, ?, ?)
Hibernate:
insert
into
t_employee
(empName, salary, dept_id)
values
(?, ?, ?)
Hibernate:
update
t_employee
set
dept_id=?
where
empId=?
Hibernate:
update
t_employee
set
dept_id=?
where
empId=?
* */

}

public void delete(){
Session session = sf.openSession();
session.beginTransaction();

Dept dept = (Dept) session.get(Dept.class,5);

session.delete(dept);

session.getTransaction().commit();
session.close();

/*
*
* Hibernate:
select
dept0_.deptId as deptId0_0_,
dept0_.deptName as deptName0_0_
from
t_dept dept0_
where
dept0_.deptId=?
Hibernate:
select
employees0_.dept_id as dept4_0_1_,
employees0_.empId as empId1_,
employees0_.empId as empId1_0_,
employees0_.empName as empName1_0_,
employees0_.salary as salary1_0_,
employees0_.dept_id as dept4_1_0_
from
t_employee employees0_
where
employees0_.dept_id=?
Hibernate:
update
t_employee
set
dept_id=null
where
dept_id=?
Hibernate:
delete
from
t_employee
where
empId=?
Hibernate:
delete
from
t_employee
where
empId=?
Hibernate:
delete
from
t_dept
where
deptId=?
*
* */} }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: