您现在的位置是:亿华云 > IT科技

躲不过JPA的坑之级联保存

亿华云2025-10-03 06:38:54【IT科技】3人已围观

简介​哈喽,大家好,我是指北君。又是全新的一周,同时也是踩坑的开始,那就先洗涤下自己的心灵吧。失败者的一大弱点在于放弃,成功的必然之路就是不断地重来一次。——托马斯·爱迪生。现在是不是热血沸腾了,马上开启

​哈喽,躲不的坑大家好,联保我是躲不的坑指北君。又是联保全新的一周,同时也是躲不的坑踩坑的开始,那就先洗涤下自己的联保心灵吧。

失败者的躲不的坑一大弱点在于放弃,成功的必然之路就是不断地重来一次。——托马斯·爱迪生。联保

现在是躲不的坑不是热血沸腾了,马上开启今天的联保分享~

前言

相信大部分java小伙伴在日常开发过程中,在存储操作层都会选择更容易上手的躲不的坑jpa,各种封装,联保通过注解等方式,躲不的坑简化了大量的云服务器联保代码内容,同时提升了开发效率,躲不的坑但是(敲黑板,永远都躲不开的但是...)相应也将一些问题隐藏,需要更多的时间去理解、分析才能找到病根。

​JPA简介

JPA全称(Java Persistence API),通常叫持久层API。它提供面向对象的编程模型,让使用者更容易理解与上手;底层也提供了通用接口,可以实现与其它框架快速集成。下面整理一些基础概念,不了解的可以参考下:

JPA是一种ORM规范。Hibernate是JPA的一个子集。Spring Data JPA,是JPA的代码实现,同时底层为Hibernate技术实现。​JPA实战-级联操作

目前小编所开发项目的数据持久层大部分采用的是Spring Data JPA,服务器托管经过长时间的使用验证,发现出了级联保存问题,即调用repository的save方法后,发现数据结果却是“丢三落四”,这就很让人脑袋疼,下面结合代码一起分析下。

代码场景:用户与住址是多对多的关系,JPA中描述这种关系通常使用@ManyToMany注解,首先是创建对象;//维护端

public class User{

//属性代码省略

@ManyToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY)

@JoinTable(name = "user_addresses",

joinColumns = { @JoinColumn(name = "user_id",referencedColumnName = "user_id")},

inverseJoinColumns = { @JoinColumn(name = "address_id",referencedColumnName = "address_id")})

private Set

addresses = new HashSet<>();

}//被维护方

public class Address{

//属性代码省略

@ManyToMany(mappedBy = "addresses")

@JsonIgnore

private Setusers = new HashSet<>();

}最初我只在维护端设置的级联属性(Cascade.ALL),然后通过维护端进行保存,很顺利,User表、Address表、user_addresses关联表都能保存,代码如下,没毛病。// 维护端操作

public User save(){

Address address = new Address();

address.setAddressName("北京海淀");

User user1 = new User();

user1.setName("阿韦");

user1.getAddresses().add(address);

return UserService.save(User1);

}然后我换了个思路,从被维护端能不能进行保存,然后就立即进行尝试。代码如下:// 被维护端操作

public Address save(){

Address address = new Address();

address.setAddressName("北京海淀");

User user1 = new User();

user1.setName("阿韦");

address.getUsers().add(user1);

return addressService.save(address);

}结果,我以为能够成功的时候,发现只保存了Address一张表,还没报错,就是User表和关联表死活没有数据。亿华云此时,问题已经复现,查阅各种文档说明,大概是需要添加级联属性,改造内容如下:@ManyToMany(cascade = CascadeType.ALL,fetch = FetchType.EAGER,mappedBy = "addresses")

private Set<User> users = new HashSet<>();修改之后再一次进行保存,两个实体类的表确实都生成了数据,但是关联表还是没有,这时已经快要抓狂,但问题还是没解决,继续耐心分析,很快就在控制台打印sql处发现了一些猫腻:

果然是没有对关联表的数据操作,接下来又是一顿探索,终于找到根源了,由被维护端发起操作的时候,需要为关联类属性添加彼此,感觉真是关联到“恩爱”的地步了,羡煞旁人啊!!!// 被维护端操作

public Address save(){

Address address = new Address();

address.setAddressName("中央花园");

User user1 = new User();

user1.setName("阿韦");

user1.setHeight("170");

user1.setSex("1");

//在彼此定义对方类集合中添加

user1.getAddresses().add(address);

address.getUsers().add(user1);

return addressService.save(address);

}

最终彻底解决掉了问题,数据持久化到相应的表中。自己也确实松了一口气,过程虽然充满曲折,但结果还是非常鼓舞自己的。心得

希望本文能够帮你避开jpa的坑,这就是小编最骄傲的事情。每一条道路上都是坑洼不平的,有些时候可能会掉入坑里,希望每个人都能重新站起来,跳过阻挡你的“坑”,最终会收获到很多,让自己变得更强。

很赞哦!(873)