hibernate jpa的一对多级联删除配置

自己的代码修正,记着避免忘记

先贴上代码

一方:User.java

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
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;
import javax.persistence.Transient;
@Entity
@Table
public class User implements Serializable {
	private static final long serialVersionUID = 1L;
	private Integer uid;
	private String email;
	private String password;
	private String signature;
	private String image;
	private Integer sex;
	private String username;
	private String verifyCode;
	private List<Log> logList = new ArrayList<Log>();
	
	/**
	 * @return the logList
	 */
	@OneToMany(targetEntity=Log.class, orphanRemoval=true)
	@JoinColumn(name = "ulid")
	public List<Log> getLogList() {
		return logList;
	}

	/**
	 * @param logList
	 *            the logList to set
	 */
	public void setLogList(List<Log> logList) {
		this.logList = logList;
	}

	/**
	 * @return the verifyCode
	 */
	@Transient
	public String getVerifyCode() {
		return verifyCode;
	}

	/**
	 * @param verifyCode
	 *            the verifyCode to set
	 */
	public void setVerifyCode(String verifyCode) {
		this.verifyCode = verifyCode;
	}

	/**
	 * @return the uid
	 */
	@Id
	@Column(name = "uid")
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	public Integer getUid() {
		return uid;
	}

	/**
	 * @param uid
	 *            the uid to set
	 */
	public void setUid(Integer uid) {
		this.uid = uid;
	}

	/**
	 * @return the email
	 */
	@Column(name = "email")
	public String getEmail() {
		return email;
	}

	/**
	 * @param email
	 *            the email to set
	 */
	public void setEmail(String email) {
		this.email = email;
	}

	/**
	 * @return the password
	 */
	@Column(name = "password")
	public String getPassword() {
		return password;
	}

	/**
	 * @param password
	 *            the password to set
	 */
	public void setPassword(String password) {
		this.password = password;
	}

	/**
	 * @return the signature
	 */
	@Column(name = "signature")
	public String getSignature() {
		return signature;
	}

	/**
	 * @param signature
	 *            the signature to set
	 */
	public void setSignature(String signature) {
		this.signature = signature;
	}

	/**
	 * @return the image
	 */
	@Column(name = "image")
	public String getImage() {
		return image;
	}

	/**
	 * @param image
	 *            the image to set
	 */
	public void setImage(String image) {
		this.image = image;
	}

	/**
	 * @return the sex
	 */
	@Column(name = "sex")
	public Integer getSex() {
		return sex;
	}

	/**
	 * @param sex
	 *            the sex to set
	 */
	public void setSex(Integer sex) {
		this.sex = sex;
	}

	/**
	 * @return the username
	 */
	@Column(name = "username")
	public String getUsername() {
		return username;
	}

	/**
	 * @param username
	 *            the username to set
	 */
	public void setUsername(String username) {
		this.username = username;
	}

	@Override
	public String toString() {
		return "User [uid=" + uid + ", email=" + email + ", password=" + password + ", signature=" + signature
				+ ", image=" + image + ", sex=" + sex + ", username=" + username + ", verifyCode=" + verifyCode
				+ ", logList=" + logList + "]";
	}
}

多方: Log.java

import java.io.Serializable;
import java.util.Date;
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.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.apache.struts2.json.annotations.JSON;
@Table
@Entity
public class Log implements Serializable{
	private static final long serialVersionUID = 1L;
	private Integer lid;
	private String ip;
	private String device;
	private Date loginTime;
	private User user;
	
	@ManyToOne
	@JoinColumn(name="ulid")
	public User getUser() {
		return user;
	}
	/**
	 * @param user the user to set
	 */
	public void setUser(User user) {
		this.user = user;
	}
	/**
	 * @return the lid
	 */
	@Id
	@Column(name="lid")
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	public Integer getLid() {
		return lid;
	}
	/**
	 * @param lid the lid to set
	 */
	public void setLid(Integer lid) {
		this.lid = lid;
	}
	/**
	 * @return the ip
	 */
	@Column(name="ip")
	public String getIp() {
		return ip;
	}
	/**
	 * @param ip the ip to set
	 */
	public void setIp(String ip) {
		this.ip = ip;
	}
	/**
	 * @return the device
	 */
	@Column(name="device")
	public String getDevice() {
		return device;
	}
	/**
	 * @param device the device to set
	 */
	public void setDevice(String device) {
		this.device = device;
	}
	/**
	 * 	设置日期类类型为timestamp
	 * @return the loginTime
	 */
	@Column(name="loginTime")
	@Temporal(TemporalType.TIMESTAMP)
	@JSON(format="yyyy-MM-dd HH:mm:ss")
	public Date getLoginTime() {
		return loginTime;
	}
	/**
	 * @param loginTime the loginTime to set
	 */
	public void setLoginTime(Date loginTime) {
		this.loginTime = loginTime;
	}

	@Override
	public String toString() {
		return "Log [lid=" + lid + ", ip=" + ip + ", device=" + device + ", loginTime=" + loginTime + "]";
	} 
}

底层dao文件:UserDaoImpl.java

	public void deleteUserByUid(User user) {
		// 此时的user2为持久态,如果是托管态或瞬时态,不能进行级联删除
		User user2 = hibernateTemplate.get(User.class, user.getUid());
		
		hibernateTemplate.delete(user2);
		// 同步数据库与session缓存
		hibernateTemplate.flush();
	}

测试结果:

1. 去掉一的一方的@JoinColumn注解,报错Cannot delete or update a parent row: a foreign key constraint fails (`test/log`, CONSTRAINT `FK1clr7t8a6pnwpwjndqr5d12ce` FOREIGN KEY (`ulid`) REFERENCES `user` (`uid`))
2. 去掉一的一方的@OneToMany(targetEntity=Log.class, orphanRemoval=true)中的orphanRemoval=true,数据库不级联删除,多的一方中的外键会被置空
	
	2.1 ***********orphanRemoval在一对多关系中,可以看做是是否级联删除***********

3. 如果底层删除的实体类的对象的状态不是持久态,会报错
	3.1. 如果底层删除的实体类对象的状态是托管态,报错A different object with the same identifier value was already associated with the session : [pdsu.xps.ssh.pojo.User#2]
	3.2. 如果底层删除的实体类对象的状态是顺势态,报错java.lang.IllegalArgumentException: id to load is required for loading

参考:

  1. 三种持久化对象的状态
    Transient瞬时态
    特点:持久化对象没有唯一标识OID.没有纳入Session的管理.
    Persistent持久态:
    特点:持久化对象有唯一标识OID.已经纳入到Session的管理.
    结论:持久化持久态对象有自动更新数据库的能力.
    Detached脱管态:
    特点:持久化对象有唯一标识OID,没有纳入到Session管理.
  2. Hibernate中的级联取值
    none :不使用级联
    dave-update :保存或更新的时候级联
    delete :删除的时候级联
    all :除了孤儿删除以外的所有级联.
    delete-orphan :孤儿删除(孤子删除).
    仅限于一对多.只有一对多时候,才有父子存在.认为一的一方是父亲,多的一方是子方.
    当一个客户与某个订单解除了关系.将外键置为null.订单没有了所属客户,相当于一个孩子没有了父亲.将这种记录就删除了.
    all-delete-orphan:包含了孤儿删除的所有的级联.

参考链接:https://www.jianshu.com/p/95f597050ab4

你可能感兴趣的:(hibernate jpa的一对多级联删除配置)