Json 将@ManyToMany关系持久化到引用表中时出现问题

Json 将@ManyToMany关系持久化到引用表中时出现问题,json,hibernate,jpa,spring-roo,spring-data-jpa,Json,Hibernate,Jpa,Spring Roo,Spring Data Jpa,我有一个课程实体,如下所示: @Entity public class Curriculum { @ManyToMany private Set<Language> languages; ... {"curriculum":{"languages":[{"id":46,"description":"Français"},{"id":30,"description":"Chinois"}],"firstName":"Julianito","dateOfBir

我有一个课程实体,如下所示:

@Entity
public class Curriculum {

    @ManyToMany
    private Set<Language> languages;
    ...
{"curriculum":{"languages":[{"id":46,"description":"Français"},{"id":30,"description":"Chinois"}],"firstName":"Julianito","dateOfBirth":"1975-01-06","telephoneNumber":"0608965874","workExperienceInYears":3,"maxNumberChildren":1,"drivingLicense":true}}
-如果我确实指定了
级联.ALL
,则带有新ID的新行将被插入
语言表中,这显然不是我想要的

编辑2:注意,我使用Spring数据JPA来持久化我的实例,来自浏览器的数据是一个JSON对象,如下所示:

@Entity
public class Curriculum {

    @ManyToMany
    private Set<Language> languages;
    ...
{"curriculum":{"languages":[{"id":46,"description":"Français"},{"id":30,"description":"Chinois"}],"firstName":"Julianito","dateOfBirth":"1975-01-06","telephoneNumber":"0608965874","workExperienceInYears":3,"maxNumberChildren":1,"drivingLicense":true}}

可能最简单的实现方法是从数据库加载所需的语言,并在persist操作之前将它们分配到课程中

这背后的逻辑如下:

  • 当一个语言对象进入应用程序并从JSON反序列化时,它已经被分配了一个ID字段
  • 当您尝试持久化课程(使用从JSON反序列化的语言)时,JPA会对这些ID感到困惑,因为一方面它“应该”知道这些对象(设置了ID),但另一方面,活动的JPA会话对它们一无所知(它们来自JSON的外部世界)
  • 所以通过ID获取语言会告诉JPA谁是谁

当不存在的
语言
附带了
课程
实例时,会发生什么?是应该忽略
语言
实例,还是应该抛出
异常


如果应该引发异常,只需将持久化实体的代码包装在try-catch块中,并引发您自己的异常。如果该语言应该被忽略,那么在持久化之前,只需将其从
列表中删除即可,例如
语言的ID为空。

我忘了提到我使用了乐观锁定。在JSon中包含版本字段将问题排序为:

"languages":[{"id":46,"description":"Français","version":0}],...
这将是伟大的,如果有人能提供一个解释,虽然

编辑:版本字段:

@Version
@Column(name = "version")
private Integer Curriculum.version;

谢谢你是说用身份证?另外:为什么JSon而不是普通html表单会有这个问题?是的,只需从DB中按id获取语言。我会更新答案,我明白你的意思。嗯。。。我相信可能有另一种方法可以在不诉诸此解决方案的情况下实现所需的结果…根据您的JPA提供程序,您可能有一个方法saveOrUpdate(),它将尊重语言对象的ID。我使用Hibernate+Spring数据JPA。还有一件事:saveOrUpdate真的适用于我的情况吗:我只想在映射表中添加行,即
课程语言
(请参见@ManyToMany)?嗨,安德烈,谢谢你的回复。我关心的是必须从数据库中获取语言实例,以便将行持久化到课程语言映射表中。在我看来,这就像是一个解决方法/黑客……为什么要从DB获取它们?Hibernate将负责在映射表中插入
columination\u languages
行,而不插入该行。如果用户将传递一些不存在的语言ID,那么数据库应该进行检查并抛出一个
ForeignKeyConstraintException
,但一切都发生在后台。我明白了。问题是,在我当前的设置中,你的建议不起作用(除非我遗漏了什么…)。看一看我的编辑1你是说你得到了一个
org.hibernate.transientObject异常
Alt尽管所有
语言
ID都已经在DB中了吗?非常有趣。这是另一个问题,因为我真的很想知道为什么会出现这种异常,而我没有:)你能展示一下@Version字段的样子吗?它是什么类型的(
int
Integer
)?据我所知,@Version字段可能不是空的(如果实体已被持久化,请参见此)。现在只是一个假设:因为在没有该字段的情况下解码JSON字符串时它被设置为null,hibernate认为它可以为null的唯一情况是它处于托管状态(但我不知道为什么)。