What is the correlation (association)
1, a reference refers to the association relationships between classes. If the class associated with the class A B, then the referenced class B to class A are defined as attributes of.
2, classification association: association can be divided into one-to-many / many-to-many association,
There is a correlation direction
The key points are associated with the foreign key
How to build a two-way-to-many association
Orders and line items to make the case
a multiple line items for orders, multiple line items on an order
you need to add two properties in order entity class:Set<OrderItem> orderItems
initOrderItems = 0;//0代表懒加载 1代表立即加载
In the line item in the entity classes you need to add a property:Order order
定义一对多的关系时需要采用接口方式
1, in Order.hbm.xml need to add (to build relationships orders for many of the line items)
<!--
cascade:用来配置维护实体类之间的关系所用
inverse:关系交由反方控制(由OrderItem控制)
-->
<set name="orderItems" cascade="save-update" inverse="true">
<!-- 填外键 -->
<key column="oid"></key>
<one-to-many class="com.zking.four.entity.OrderItem"/>
</set>
2, in OrderItem.hbm.xml need to add (many to one relationship to the order line item)
<property name="oid" type="java.lang.Integer" column="oid" insert="false" update="false"></property>
<!-- 会报错 -->
<many-to-one name="order" class="com.zking.four.entity.Order" column="oid"></many-to-one>
Third, the new cascade, cascading query, ordinary delete
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>2.1.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.3.7.Final</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.querydsl/querydsl-jpa -->
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
<version>4.1.4</version>
</dependency>
</dependencies>
method:
package com.four.dao;
import java.util.List;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.four.entity.Order;
import com.four.entity.OrderItem;
import com.two.util.SessionFactoryUtil;
public class OrderDao {
//订单项新增
public Integer addOrderItem(OrderItem orderItem) {
Session session = SessionFactoryUtil.getSession();
Transaction transaction = session.beginTransaction();
Integer otid = (Integer) session.save(orderItem);
transaction.commit();
session.close();
return otid;
}
//订单新增
public Integer addOrder(Order order) {
Session session = SessionFactoryUtil.getSession();
Transaction transaction = session.beginTransaction();
Integer otid = (Integer) session.save(order);
transaction.commit();
session.close();
return otid;
}
//查单个
public Order getOrder(Order order) {
Session session = SessionFactoryUtil.getSession();
Transaction transaction = session.beginTransaction();
Order o = session.get(Order.class, order.getOrderId());
if(o != null && new Integer(1).equals(order.getInitOrderItems())) {
Hibernate.initialize(o.getOrderItems());
}
transaction.commit();
session.close();
return o;
}
//查所有
public List<Order> getOrderList(){
Session session = SessionFactoryUtil.getSession();
Transaction transaction = session.beginTransaction();
List list = session.createQuery("from Order").list();
transaction.commit();
session.close();
return list;
}
//删除(hibernate需要先删从表(订单项)再删主表(订单))
public void delOrder(Order order) {
Session session = SessionFactoryUtil.getSession();
Transaction transaction = session.beginTransaction();
Order o = session.get(Order.class, order.getOrderId());
for (OrderItem ot : o.getOrderItems()) {
session.delete(ot);
}
session.delete(o);
transaction.commit();
session.close();
}
}
JUnit test
package com.four.dao;
import java.util.Iterator;
import java.util.List;
import org.junit.Test;
import com.four.entity.Order;
import com.four.entity.OrderItem;
public class OrderDaoTest {
private OrderDao orderDao = new OrderDao();
/**
* Repeated column in mapping for entity:
* com.zking.four.entity.OrderItem column: oid
* (should be mapped with insert="false" update="false")
* 同一个字段被映射了两次
*/
@Test
public void testAddOrderItem() {//订单项新增
OrderItem orderItem = new OrderItem();
// orderItem.setOid(7);//普通新增
orderItem.setProductId(89);
orderItem.setQuantity(78);
Order order = new Order();
order.setOrderId(5);
orderItem.setOrder(order);
this.orderDao.addOrderItem(orderItem);
}
//提交一个具有6个订单项的订单
// addOrder 1
// addOrderItem 6
@Test
public void testAddOrder() {//订单新增
Order order = new Order();
order.setOrderNo("P8");
OrderItem orderItem;
for (int i = 1; i < 7; i++) {
orderItem = new OrderItem();
orderItem.setProductId(i);
orderItem.setQuantity(i);
order.getOrderItems().add(orderItem);
orderItem.setOrder(order);
}
this.orderDao.addOrder(order);
}
@Test
public void testGetOrder() {//查单个
Order order = new Order();
order.setOrderId(8);
order.setInitOrderItems(1);
Order o = this.orderDao.getOrder(order);
System.out.println(o.getOrderNo());
System.out.println(o.getOrderItems().size());
for (OrderItem ot : o.getOrderItems()) {
System.out.println(ot.getProductId());
}
}
@Test
public void testGetOrderList() {//查所有
List<Order> list = this.orderDao.getOrderList();
for (Order o : list) {
System.out.println(o.getOrderNo());
System.out.println(o.getOrderItems().size());
for (OrderItem ot : o.getOrderItems()) {
System.out.println(ot.getProductId());
}
}
}
@Test
public void testDelOrder() {//删除
Order order = new Order();
order.setOrderId(8);
this.orderDao.delOrder(order);
}
}
"Party" Save diagram:
A brief summary of "party" parties saved:
Save a brief summary of the cascade:
Case
Many
First, let's understand what it means to many of the data in a database table A, B can be mapped multiple database tables, that is, the angle A standing table, it was all dance data reference table B,
Hiberante on a table that has a set of table B, the following configuration
package com.xingxue.entity;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;
//关联我们的表
@Entity //该类被hibernate当做实体给管理
@Table(name="xx_plat_role") //对应数据库的表
public class Role {
@Id //配置主键
@GeneratedValue(strategy=GenerationType.IDENTITY) //自增策略
@Column(name="role_id") //关联字段名和数据类型
private int id;
@Column(name="role_name") //关联字段名和数据类型
private String name;
@Column(name="role_status") //关联字段名和数据类型
private String status;
@Column(name="createdate", columnDefinition="DATETIME") //关联字段名和数据类型
private Date createdate;
@OneToMany //一对多配置,
@JoinColumn(name="admin_role") // 外键的名字
private Set<Admin> admins = new HashSet<Admin>();
}
Here many configuration, only the configuration end, multiport do not manage, so Admin does not require any configuration
test code:
public boolean add(Admin param, int roleId) {
Session session = this.sessionFactory.openSession();
//开启事务
Transaction t = session.beginTransaction();
//get我们的role对象,让hibernate管理起来
Role role = (Role) session.get(Role.class, roleId);
//关联role和admin的关系
role.getAdmins().add(param);
int result = (Integer) session.save(param);
//提交事务
t.commit();
//关闭回话
session.close();
return result > 0;
}
The results are as follows
according to the test results, we found that if we want to association of two tables,:
1, hibernate configure the relationship
2, when operating data, two associated objects are to manage hibernate,
3, the two objects We must establish a relationship between
Query data test
@Override
public List<Role> list() {
Session session = this.sessionFactory.openSession();
String SQL = "select * from xx_plat_role";
List<Role> list = session.createSQLQuery(SQL).addEntity(Role.class).list();
return list;
}
我们发现在查询role的时候,实际上hibernate自动帮我们查询了当前role下面的所有admin信息,并且封装到了set里面,也就是数据已经包装好了。省去了我们以前的链接查询的操作。
但是通过测试我们发现,在查admin的时候没有把admin相关的role给查询出来,那是因为admin没有配置映射关系,多对一,所以admin无效果,
懒加载设置
其实有的时候我们不需要查询admin信息,所以关联数据hiberante默认使用懒加载机制,所谓的懒加载就是我们需要使用这个数据他 才去查询,你不使用,H就不查询,但是必须建立在session不关闭的情况下,
@OneToMany(fetch=FetchType.EAGER) //没有懒加载,
@OneToMany(fetch=FetchType.LAZY) //使用懒加载,
由于不使用懒加载效率很低,所以我们默认都使用懒加载,如果在dao有需要进行关联数据加载,建议手动用代码访问一下关联数据
多对一
多对一实际上就是和一对多站的角度不一样,表之间的关系,如果是一对多,我们换个角度就是多对一,所以一般一对多和多对一都是双向关联配置,还是Admin和role为例
站在admin的角度多对一:
@Table(name="xx_plat_admin")
public class Admin {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="admin_id")
private int id;
@Column(name="admin_username",length=20)
private String userName;
@Column(name="admin_pwd",length=20)
private String pwd;
@ManyToOne
@JoinColumn(name="admin_role")
private Role role;
双向关联是如上配置, 同时需要注意的是,此种配置,我们的关系管理就交给了多端来进行管理了。
所以代码如下:
@Override
public boolean add(Admin param, int roleId) {
Session session = this.sessionFactory.openSession();
//开启事务
Transaction t = session.beginTransaction();
//get我们的role对象,让hibernate管理起来
Role role = (Role) session.get(Role.class, roleId);
//关联role和admin的关系
// role.getAdmins().add(param);
param.setRole(role);
int result = (Integer) session.save(param);
//提交事务
t.commit();
//关闭回话
session.close();
return result > 0;
}
多对一默认不是用懒加载,如果需要使用。需要手动开启
@ManyToOne(fetch=FetchType.LAZY)
多对多
hibernate多对多当中,我们常常希望只删除一方已及对应的关系,但不想删除另一方
表user和表role多对多,中间表user_role(userId,roleId),user是主控方,role是从方,
在spring+hibernate的环境下,使用的是Annotation配置
User.java
@ManyToMany(cascade = {CascadeType.MERGE,CascadeType.PERSIST}, fetch = FetchType.EAGER)
@JoinTable(name = "user_role",joinColumns = { @JoinColumn(name = "userId",referencedColumnName="userId")},inverseJoinColumns = { @JoinColumn(name = "roleId",referencedColumnName="roleId") })
public Set<Role> getRoles() {
return this.roles;
}
Role.java
@ManyToMany(cascade = {CascadeType.MERGE,CascadeType.PERSIST}, fetch = FetchType.EAGER,
mappedBy = "roles")
public Set<User> getUsers() {
return this.users;
}
Test: master User deletion, user will be deleted, user_role relationship will also be deleted, but the corresponding role will not be deleted
@Test
public void testDelete() {
User user = userDao.findById(8);
userDao.delete(user);
}
Test: If there is no corresponding user_role roleId, role can be deleted from the deletion of the square Role, user will not be deleted
@Test
public void testDelete() {
Role role = roleDao.findById(26);
roleDao.delete(role);
}
Test: Role removed from the party, if there are user_role corresponding association roleId and other userId, role can not be deleted
@Test
public void testDelete() {
Role role = roleDao.findById(26);
roleDao.delete(role);
}
We will complain:
org.springframework.dao.DataIntegrityViolationException: Could not execute JDBC batch update; nested exception is org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
Caused by: org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
Caused by: java.sql.BatchUpdateException: Cannot delete or update a parent row: a foreign key constraint fails (`hrms`.`user_role`, CONSTRAINT `roleId` FOREIGN KEY (`roleId`) REFERENCES `role` (`roleId`) ON DELETE NO ACTION ON UPDATE NO ACTION)
Cascade operation user_role change table structure in the database, it is to add the constraint, add delete roleId Solution:
ALTER TABLE `hrms`.`user_role`
ADD CONSTRAINT `roleId`
FOREIGN KEY (`roleId` )
REFERENCES `hrms`.`role` (`roleId` )
ON DELETE CASCADE;
Test: If there are user_role corresponding roleId, now can remove the party role Role deleted from the corresponding relationship user_role inside will be deleted, but the corresponding user will not be deleted, to the effect that we want
@Test
public void testDelete() {
Role role = roleDao.findById(26);
roleDao.delete(role);
}