【问题标题】:JPA force insert related entities (as opposed to update)JPA 强制插入相关实体(而不是更新)
【发布时间】:2020-01-09 14:28:59
【问题描述】:

我想要的行为:

Make 
ID   |   City   |   Vers
1        Jose        S_5

MakeConfiguration
MakeID | Something | Vers
1         nada       S_5

当我得到这个实体(使用带有一些自定义 @Query 的 spring data jpa)时,一切正常。

当我尝试发布(完全相同的实体)时,我想要以下内容:

Make 
ID   |   City   |   Vers
1        Jose        S_5
1        Jose        S_6

MakeConfiguration
MakeID | Something | Vers
1         nada       S_5
1         nada       S_6

但我得到的是这样的:

Make 
ID   |   City   |   Vers
1        Jose        S_5
1        Jose        S_6

MakeConfiguration
MakeID | Something | Vers
1         nada       S_6

(请注意在 MakeConfiguration 中没有创建新记录) 正在显示的 SQL 正在将新记录插入 Make,并使用新版本更新 MakeConfiguration 中的记录。如果我更改任何其他 @Id 注释值(在这种情况下是某物),那么它会正确插入一条新记录。似乎hibernate不尊重版本上的@Id注解。

我有以下(JPA/Hibernate 实体)

@Entity
@IdClass(MakeId.class)
public class Make {
    @Id
    @Column(name="MAKE_ID")
    private String makeUuid;

    @Id
    private String city

    @Id @Column(name = "MAKE_ID_VERSION")
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "version_seq")
    @GenericGenerator(
            name = "version_seq", strategy = "com.me.VersionIdGenerator"
    )
    private String makeIdVersion;

    @OneToMany(fetch = FetchType.EAGER)
    @JoinColumns( {
            @JoinColumn(name = "clientProgramUuid", referencedColumnName = "MAKE_ID"),
            @JoinColumn(name = "clientUuidVersion", referencedColumnName = "MAKE_ID_VERSION")
    })
    private List<MakeConfiguration> makeConfigurations;
}

@Entity
@IdClass(MakeConfigurationId.class)
public class MakeConfiguration {
    @Id
    private String makeConfigurationUuid

    @Id
    private String something

    @Id
    private String makeIdVersion;
}

为便于阅读,省略了 IdClass、getter、setter。 VersionIdGenerator 按顺序生成下一个版本(假设为 S_1、S_2...S_N)。

我也总是在 Make entity 上调用 entitymanager.persist。

我已经尝试了几件事来让它工作(双向等)但没有运气。我认为我需要强制从 Make 生成的内容中检索版本。

【问题讨论】:

  • 看起来您的交易有问题...您是否获取版本5_5 的MakeConfiguration 并对其进行修改?如果是这样:这一切都发生在一笔交易中吗?如果是:实体仍被附加并因此得到更新。如果您使用@Transactional(propagation = Propagation.REQUIRES_NEW) 注释获取MakeConfiguration 的方法,这可能是可以避免的
  • 不,我唯一的交互是通过rest API(get + post),所以什么都不应该附加
  • 这里似乎有一个误解...在您的应用程序中,您需要有一些代码(可能是Repository)与数据库交互。一定会涉及到一些交易。没有事务 = 没有数据库交互。

标签: java hibernate jpa


【解决方案1】:

首先,永远不要使用Eager)使用FetchType.LAZY。
Check this question

其次,不要经常使用@id。每个实体仅使用一次。 @Id:这个注解指定了实体的主键。即使您放置在某个对象的列 id 中 - 只需使用 @Column
Check this question

顺便说一句,download ProjectLombok 库(用于 Maven):

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>

我修复了你的程序。它应该是这样的:

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Table
@Entity
public class Make {

    @Id
    @Column(name = "ID")
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "version_generator")
    @SequenceGenerator(name = "version_generator", sequenceName = "seq_version", allocationSize = 1)
    private Long id;

    @Column
    private String makeUuid;

    @Column
    private String city;

    @OneToMany(
            cascade = {
                    CascadeType.MERGE,
                    CascadeType.PERSIST
            }, fetch = FetchType.LAZY
    )
    private List<MakeConfiguration> makeConfigurations = new ArrayList<>();

    public void addMakeConfigurations(MakeConfiguration makeConfiguration) {
        makeConfigurations.add(makeConfiguration);
    }

    public void removeMakeConfigurations(MakeConfiguration makeConfiguration) {
        makeConfigurations.remove(makeConfiguration);
    }

}

@Data
@AllArgsConstructor
@NoArgsConstructor
@Table
@Entity
public class MakeConfiguration {

    @Id
    @Column(name = "ID")
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "makeConfig_generator")
    @SequenceGenerator(name = "makeConfig_generator", sequenceName = "seq_makeConfig", allocationSize = 1)
    private Long id;

    @Column
    private String makeConfigurationUuid;

    @Column
    private String something;

    @Column
    private String version;
}

【讨论】:

    猜你喜欢
    • 2016-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多