Associated with the cascade hibernate

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:

Here Insert Picture Description

A brief summary of "party" parties saved:

Here Insert Picture Description

Save a brief summary of the cascade:

Here Insert Picture Description

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
Here Insert Picture Description
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;
    }

Here Insert Picture Description我们发现在查询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); 

}

Guess you like

Origin blog.csdn.net/qq_37651267/article/details/94058364
Recommended