我正在从事一个基于SpringJPA的微服务项目,其中我有两个实体,userentity和regionentity,通过多对多关系关联。以下是两个实体的(简化)代码:
@EqualsAndHashCode(of = {"id"})
@Data
@Entity
@Table(name = "users")
@Audited
public class UserEntity implements Serializable {
@Id
@Column(name = "userId", columnDefinition = "int", unique = true, nullable = false)
private Long id;
@NotAudited
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "users_regions",
joinColumns = @JoinColumn(name = "userId", columnDefinition = "int", nullable = false, updatable = false),
inverseJoinColumns = @JoinColumn(name = "regionId", columnDefinition = "varchar(50)", nullable = false, updatable = false))
private Set<RegionEntity> regions = new HashSet<>();
}
@EqualsAndHashCode(exclude = {"users"})
@Entity
@Table(name = "regions")
@Data
@Audited
public class RegionEntity {
@Id
@Column(name = "name", columnDefinition = "varchar(50)", unique = true, nullable = false)
private String name;
@ManyToMany(mappedBy = "regions", fetch = FetchType.EAGER)
private Set<UserEntity> users = new HashSet<>();
}
现在,我有了一个用于持久化第三个实体(callentity)示例的路由,该实体利用了前面两个实体。了解callentity还与regionentity有多对多关联,与user有多对一关联可能很有用。简而言之,这里是路由调用的方法。
public CallDTO myMethod(String userName, /* ... more stuff */) {
UserProjection userProj = userConsumer.findByUserName(userName, UserBasicProjection.class); // from another repository, retrieve a user projection
UserEntity user = userRepository.findById(user.getId()).orElse(null); // use that projection to initialise the user
Set<RegionEntity> userRegions = user != null ? user.getRegions() : null;
CallEntity newCall = new CallEntity();
/ * some actions, mainly setting values for newCall using userRegions and user... */
CallEntity call = callRepository.save(newCall);
return callMapper.toDTO(call);
}
问题是hibernate在保存callentity对象时会自动删除关联表中与用户区域对相关的行。例如,如果用户的id为1234,并且区域a、b和c关联,
user | region
-------------
1234 | A
-------------
1234 | B
-------------
1234 | C
-------------
然后,表中此代码行之后的所有三行都将被删除:
callentity call=callrepository.save(newcall);
被执行。
这是当前使用的hibernate版本:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-jpamodelgen</artifactId>
<version>5.3.12.Final</version>
</dependency>
这是执行后的控制台打印输出:
Hibernate:
/* get current state package-name.UserEntity */ select
userent_.userId
from
user userent_
where
userent_.userId=?
Hibernate:
/* get current state package-name.RegionEntity */ select
regione_.name
from
region regione_
where
regione_.name=?
Hibernate:
/* insert package-name.CallEntity
*/ insert
into
call
(id, userid, regionid)
values
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate:
select
last_insert_id()
Hibernate:
/* delete collection package-name.UserEntity.regions */ delete
from
users_regions
where
userId=?
Hibernate:
/* insert collection
row package-name.CallEntity.userRegions */ insert
into
call_region
(id, name)
values
(?, ?)
我发现,如果我改变关系的方向(在本例中,拥有的实体是regionentity),问题就会消失。然而,这绝不是一个可行的解决方案,因为它会影响项目的其他部分。此外,我发现以前在这个网站上也有人问过类似的问题(许多人都会删除连接表条目),但不幸的是,答案并不令人满意。我尝试添加和使用方便的方法来正确地建立关联(如链接问题的答案所示),但这根本不起作用。
任何帮助都将不胜感激。
非常感谢。
1条答案
按热度按时间o4tp2gmn1#
最后,通过将区域集 Package 在副本中解决了该问题。
也就是说,通过替换此行:
设置userregions=user!=无效的user.getregions():null;
与:
设置userregions=userxpc!=无效的set.copyof(userxpc.getregions()):null;