jpa onetomany 使用级连表删除被维护表数据时的坑

目录
  • jpa onetomany 使用级连表删除被维护表数据时的坑
    • 一、异常产生的场景
    • 二、存在异常的问题
    • 三、异常原因分析
    • 四、解决方案
  • jpa onetomany的用法
    • one部分
    • many部分
    • 注意

jpa onetomany 使用级连表删除被维护表数据时的坑

一、异常产生的场景

两个实体类,为一对多的关系

主表 ,字段维护表,1个用户可能有多个角色

实体类User,代码如下:

package ywcai.ls.entity;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.Table;
@Entity
@Table(name="user")
public class User implements Serializable{
/**
*
*/
private static final long serialVersionUID = -7383132326629943397L;
@Id
    @GeneratedValue(strategy= GenerationType.AUTO)
    @Column(name="id")
    private Long id;
    @Column(name="username")
    private String username;
    @Column(name="password")
    private String password;
    @OneToMany(cascade={CascadeType.ALL},fetch=FetchType.EAGER,mappedBy="user")
   //特别注意:onetomany标识这是级联1对多的关系。cascade={CascadeType.ALL}表示主表的增查删改都会直接通过关联字段对从表进行相应操作。
   //例如删除主表的一个user实例,从表与user相关联roles将被删除。
   //而fetch=FetchType.EAGER表示急加载,即指一旦主表进行了相应操作,则从表也将立即进行相应的级联操作。
   //例如,一旦读取了user表的某一个实例,则user会立即加载Roles;而fetch=FetchType.LAZY为懒加载,当需要使用到getRolelist()方法时,才会读取相关联的级联表数据
    @OrderBy(value= "id ASC")//获取的角色信息根据角色表的id进行升序排序
    private Set<Roles> rolelist;

public Set<Roles> getRolelist() {
return rolelist;
}
public void setRolelist(Set<Roles> rolelist) {
this.rolelist = rolelist;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
}

被维护的级联表,多个Roles角色可能对应1个用户

实体类Roles,代码如下:

package ywcai.ls.entity;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@Entity
@Table(name="roles")
public class Roles {
    @Id
    @GeneratedValue(strategy= GenerationType.AUTO)
    @Column(name="id")
    private Long id;
    @Column(name="username")
    private String username;
    @Column(name="rolename")
    private String rolename;
    @ManyToOne(cascade={CascadeType.REFRESH},fetch=FetchType.LAZY)
    @JoinColumn(name="userid")//加入一列作为外键
    private User user;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getRolename() {
return rolename;
}
public void setRolename(String rolename) {
this.rolename = rolename;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}

二、存在异常的问题

当Roles类级联操作属性使用(cascade={CascadeType.REFRESH},这样主要为达到对从表的某一个用户的权限进行操作,而不影响主表User。

这时候Roles的注解

@ManyToOne(cascade={CascadeType.REFRESH},fetch=FetchType.EAGER)

通过user对Roles进行增加操作时,无任何问题。但单独对Roles表中的一项进行删除,例如单独删除A用户的管理员橘色,则无法删除。

@Repository
@Table(name="roles")
@Qualifier("rolesRepository")
public interface RolesRepository extends JpaRepository<Roles, Long > {
@Transactional
int deleteByUsernameAndRolename(String username,String rolename);
}

首先通过JpaRepository约束接口删除数据,必须开启事务,否则报错。

而开启事务后,该删除代码可以执行,执行返回的结果也正常返回1,但实际的数据中却没有反应,数据无法被删除。

三、异常原因分析

出现该问题的原因是Roles使用了CascadeType.REFRESH注解,Roles删除了该表中的相应数据后,会自动试图去删除主表中该USER实体数据。但由于注解中仅赋予了CascadeType.REFRESH,读取刷新数据的权限,因此删除主表中该USER实体数据的语句是无法执行的,最终造成了整个deleteByUsernameAndRolename()事务的失败回滚,结果就是要删的数据没删掉。

若在Roles实体类增加CascadeType.REMOVE权限,虽deleteByUsernameAndRolename()的事务可以正常执行,但会造成主表USER用户也被整体删除,进而反过来造成Roles表中所有该USER的角色也都被删除。显然,这和业务需求也不符合。

四、解决方案

上诉的问题看起来已经是一个逻辑相悖的矛盾,无法解决。实际上只需要将Roles中加载模式改为懒加载即可,User实体类的加载模式不需改变。

当删除roles中记录时不会立即触发到对User实体类数据的删除,也就不会报错和造成失误的回滚。

jpa onetomany的用法

one部分

时机项目中使用到的。

@OneToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY,mappedBy="dcpDataServiceManage")
    private List<DcpDataServiceTableFieldEntity> dataServiceTableFieldList;

注意这个mappBy 要和many部分字段对应上

many部分

/**
     * 关联的
     */
    @ManyToOne
    @JoinColumn(referencedColumnName = "gid")
    private DcpDataServiceManageEntity dcpDataServiceManage;

这块注意的是数据库保存的是实体类的gid.。one部分mappBy就是这个字段名。

注意

这块就可以省去中间的一张关联表。由于项目的原因。不能采用jpa 自动建表的功能。这里使用的是sql。 特别注意的是这个字段名在数据库创建的时候要加GID的

像上面代码块的字段 根据表映射规则 数据库存的字段应该是DCP_DATA_SERVICE_MANAGE_GID 这个要注意一下

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • 解决JPA @OneToMany及懒加载无效的问题

    目录 JPA @OneToMany及懒加载无效 @OneToMany 小结一下吧 实现JPA的懒加载和无外键 例如 转换时使用 JPA @OneToMany及懒加载无效 @OneToOne @ManyToMany使用不做过多解释,重点解决"懒加载无效问题". 示例: @OneToMany teacher 和 student是一对多关系 只需要在studentList上使用@OneToMany注解,对应的参数为 懒加载.级联操作.子表外键 我为了验证懒加载是否生效,在debug模式下发现

  • jpa使用manyToOne(opntional=true)踩过的坑及解决

    目录 jpa使用manyToOne(opntional=true)踩坑 @ManyToOne用于一对多的情况 @manytoone设置为optional=true不起作用 @manytoone 原因 jpa使用manyToOne(opntional=true)踩坑 @ManyToOne用于一对多的情况 (默认情况下是懒加载的,没必要去配置哦)如:一个account可以对应多个accountPrivilege @Entity @Table(name = ACCOUNT_PRIVILEGE) pub

  • SpringData JPA中@OneToMany和@ManyToOne的用法详解

    目录 一. 假设需求场景 二. 代码实现 2.1 级联存储操作 2.2 查询操作和toSting问题 2.3 级联删除 2.4 pom.xml 一. 假设需求场景 在我们开发的过程中,经常出现两个对象存在一对多或多对一的关系.如何在程序在表明这两个对象的关系,以及如何利用这种关系优雅地使用它们. 其实,在javax.persistence包下有这样两个注解--@OneTomany和@ManyToOne,可以为我们所用. 现在,我们假设需要开发一个校园管理系统,管理各大高校的学生.这是一种典型的一

  • jpa onetomany 使用级连表删除被维护表数据时的坑

    目录 jpa onetomany 使用级连表删除被维护表数据时的坑 一.异常产生的场景 二.存在异常的问题 三.异常原因分析 四.解决方案 jpa onetomany的用法 one部分 many部分 注意 jpa onetomany 使用级连表删除被维护表数据时的坑 一.异常产生的场景 两个实体类,为一对多的关系 主表 ,字段维护表,1个用户可能有多个角色 实体类User,代码如下: package ywcai.ls.entity; import java.io.Serializable; im

  • Linux下Oracle删除用户和表空间的方法

    本文实例讲述了Linux下Oracle删除用户和表空间的方法.分享给大家供大家参考,具体如下: 1.删除某个用户 SQL> conn /as sysdba Connected. SQL> drop user userName cascade; 用户已删除 如果用户无法删除,并报错: ERROR at line 1: ORA-01940: cannot drop a user that is currently connected 通过查看用户的进行,并kill用户进程,然后删除用户. SQL&

  • mysql中多表删除其中ID相同记录的方法

      问题源自一个5年前的百度知道回答,刚看到这个问题时我刚上班21天,遂根据自己的那一丁点经验和临时操作检验做出了当时认为正确的回答:  但很快就被人否定,我猜主要原因就是我说的最后一句话过于绝对,但由于自己太相信自己了,而且有一大堆理由支撑着,所以没有深入研究. 最近又有网友评论了我的这个回答,我才开始查了一下百度,发现Mysql4.0以上版本已经可以通过一条delete删除多个表的数据了.看来我确实在误人子弟了,只能说声抱歉,好在楼主没有选我的答案,要不然罪过大了. 最后总结一下: MySq

  • Oracle 删除用户和表空间详细介绍

    Oracle 删除用户和表空间 Oracle 使用时间长了, 新增了许多user 和tablespace. 需要清理一下 对于单个user和tablespace 来说, 可以使用如下命令来完成.  步骤一:  删除user drop user ×× cascade 说明: 删除了user,只是删除了该user下的schema objects,是不会删除相应的tablespace的. 步骤二: 删除tablespace DROP TABLESPACE tablespace_name INCLUDI

  • Yii使用DeleteAll连表删除出现报错问题的解决方法

    本文实例讲述了Yii使用DeleteAll连表删除出现报错问题的解决方法.分享给大家供大家参考,具体如下: 删除数据的时候,经常会遇到连联判断删除数据的条件,今天用Yii 的CDbCriteria生成关连条件.批量删除的时候数据库报错. 页面代码为: $criteria=new CDbCriteria; $criteria->join = ' LEFT JOIN {{positions}} p ON p.zpo_id=t.zpo_id '; $criteria->addCondition(&q

  • MySQL学习笔记之创建、删除、修改表的方法

    本文实例讲述了MySQL学习笔记之创建.删除.修改表的方法.分享给大家供大家参考,具体如下: 创建表: create table users( id int, name varchar(64), sex bit(1), birthday date, Entry_date date, job varchar(32), salary float, resume text ); 1 添加列: alter table 表名 add 列名 数据类型 alter table users add image

  • Django 解决新建表删除后无法重新创建等问题

    起因 同步表的过程中,我手动将数据库中的一个表删除了,此时再去执行命令,发现不能再数据库中新建表了 修改了表结构以后执行python3 manage.py migrate 报错: No changes detected 所以进数据库把对应的表删除了,想着重新生成这张表. 删除表以后执行: python3 manage.py makemigrations python3 manage.py migrate 还是不能生成表,提示:No changes detected 处理过程 一.首先删除了app

  • 浅谈MySQL如何优雅的做大表删除

    随着时间的推移或者业务量的增长,数据库空间使用率也不断的呈稳定上升状态,当数据库空间将要达到瓶颈的时候,可能我们才会发现数据库有那么一两张的超级大表!他们堆积了从业务开始到现在的全部数据,但是90%的数据都是没有业务价值的,这时候该如何处理这些大表? 既然是没有价值的数据,我们通常一般会选择直接删除或者归档后删除两种,对于数据删除的操作方式来说又可分为两大类: 通过truncate直接删除表中全部数据 通过delete删除表中满足条件记录 一.Truncate操作 从逻辑意义上来讲,trunca

  • MongoDB实现创建删除数据库、创建删除表(集合 )、数据增删改查

    一. 数据库使用 开启 mongodb 服务:要管理数据库,必须先开启服务,开启服务使用 mongod --dbpath c:\mongodb 管理 mongodb 数据库:(一定要在新的 cmd 中输入) mongo 清屏: cls 查看所有数据库列表 show dbs 二. 创建数据库 使用数据库.创建数据库 use student 如果真的想把这个数据库创建成功,那么必须插入一个数据.数据库中不能直接插入数据,只能往集合(collections)中插入数据.不需要专门创建集合,只需要写点语

随机推荐