【问题标题】:Why Value is not getting assigned in JPA for insert statement为什么没有在 JPA 中为插入语句分配值
【发布时间】:2021-04-24 05:34:16
【问题描述】:

您好,我有几个实体类如下,使用 lombok 作为 getter 和 setter

父实体类有

@Table(name = "PARTY")
@Entity
public class Party {
        
@Id
@Column(name = "PARTY_ID")
private Long partyId;


@OneToMany(targetEntity = DVLoanParticipants.class,cascade = CascadeType.ALL)
@JoinColumn(name = "PARTY_ID")
@MapKey(name="dvpParticipantName")
@LazyCollection(LazyCollectionOption.FALSE)
private Map<String, DVLoanParticipants> dvLoanParticipantsMap;
}

子实体类有

@Table(name = "DV_LOAN_PARTICIPANTS")
@Entity
public class DVLoanParticipants implements Serializable {

@Id
@Column(name = "PARTY_ID")
private Long partyId;

@Id
@Column(name = "DVP_PARTICIPANT_NAME")
private String dvpParticipantName;

@Column(name = "DVP_PARTICIPANT_TYPE")
private String dvpParticipantType;
}

在服务类中,我将保存操作调用为

repository.save(parentEntityObject);

我能够执行更新语句,但是当我尝试为子实体类插入新行时,我收到一个错误提示

cannot insert NULL into ("ABC"."DV_LOAN_PARTICIPANTS"."PARTY_ID")

但如果我在保存操作之前打印 parentEntityObject,我会看到类似的值

(partyId=12345678, dvpParticipantName=XYZ, dvpParticipantType=VKP)

我看到查询格式为

insert 
 into
    DV_LOAN_PARTICIPANTS
    (DVP_PARTICIPANT_TYPE, PARTY_ID, DVP_PARTICIPANT_NAME) 
values
    (?, ?, ?)

就在保存之前,我在对象中看到了值

Builder=DVLoanParticipants(partyId=123456, dvpParticipantName=Builder, 
dvpParticipantType=Individual)

更新

这是值的设置部分

                DVLoanParticipants dvLoanParticipants = new 
           DVLoanParticipants();
                dvLoanParticipants.setPartyId(Long.valueOf(partyId));
                dvLoanParticipants.setDvpParticipantName("Builder");
                dvLoanParticipants.setDvpParticipantType("Individual");
                Party party = new Party();
                Map<String, DVLoanParticipants> dvLoanParticipantsMap = new 
      java.util.HashMap<>();
                dvLoanParticipantsMap.put("Builder", dvLoanParticipants);
                party.setPartyId(Long.valueOf(partyId));
                party.setDvLoanParticipantsMap(dvLoanParticipantsMap);
                repository.save(party);

我做错了什么?

【问题讨论】:

  • 这是单向关联还是双向关联?
  • 这也不清楚您的域模型的哪个类映射到DV_LOAN_PARTICIPANTS 表。
  • 它的单向关联,我更新了问题。
  • 有各种问题。 1)如何设置ID? 2) 你有一个复合主键,但没有 IdClass。
  • (1) 我没有手动设置 ID。但我能够更新参与者表中的值,但只有插入失败。 (2) 我相信即使没有 id 类它也应该可以工作,相反我可以设置两个 id 属性。

标签: spring hibernate spring-mvc jpa


【解决方案1】:

这部分问题的根本原因:

@OneToMany(targetEntity = DVLoanParticipants.class,cascade = CascadeType.ALL)
@JoinColumn(name = "LOAN_ID")
@MapKey(name="dvpParticipantName")
private Map<String, DVLoanParticipants> dvLoanParticipantsMap;

实际上,对于您的情况,@JoinColumn 中的列名意味着:

如果连接是针对使用外键映射策略的单向 OneToMany 映射,外键在目标实体的表中。

因此,为了清楚起见,假设您要映射以下架构:

create table PARTY
(
   PARTY_ID int,
   -- ...

   primary key (PARTY_ID)
);

create table DV_LOAN_PARTICIPANTS
(
   PARTY_ID int,
   DVP_PARTICIPANT_NAME varchar(50),
   DVP_PARTICIPANT_TYPE varchar(10),
   -- ...
   
   primary key (PARTY_ID, DVP_PARTICIPANT_NAME),
   foreign key (PARTY_ID) references PARTY(PARTY_ID)
);

您可以使用以下映射:

@Entity
@Table(name = "PARTY")
public class Party
{
   @Id
   @Column(name = "PARTY_ID")
   private Long partyId;

   // I use fetch = FetchType.EAGER instead of deprecated @LazyCollection(LazyCollectionOption.FALSE)
   // targetEntity = DVLoanParticipants.class is redundant here
   @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
   @JoinColumn(name = "PARTY_ID") // this is DV_LOAN_PARTICIPANTS.PARTY_ID column
   @MapKey(name = "dvpParticipantName")
   private Map<String, DVLoanParticipants> dvLoanParticipantsMap;
   
   public Party()
   {
      dvLoanParticipantsMap = new HashMap<>();
   }

   // getters / setters

   public void addParticipant(DVLoanParticipants p)
   {
      this.dvLoanParticipantsMap.put(p.getDvpParticipantName(), p);
      p.setPartyId(getPartyId());
   }
}

@Entity
@Table(name = "DV_LOAN_PARTICIPANTS")
public class DVLoanParticipants implements Serializable
{
   @Id
   @Column(name = "PARTY_ID")
   private Long partyId;

   @Id
   @Column(name = "DVP_PARTICIPANT_NAME")
   private String dvpParticipantName;

   @Column(name = "DVP_PARTICIPANT_TYPE")
   private String dvpParticipantType;

   // getters / setters
}

以及如何保存的示例:

Party party = new Party();
party.setPartyId(2L);

// ...
DVLoanParticipants part1 = new DVLoanParticipants();
part1.setDvpParticipantName("Name 3");
part1.setDvpParticipantType("T1");
      
DVLoanParticipants part2 = new DVLoanParticipants();
part2.setDvpParticipantName("Name 4");
part2.setDvpParticipantType("T1");

party.addParticipant(part1);
party.addParticipant(part2);

repository.save(party);

还有几个注意事项:

  1. LazyCollectionOption.TRUELazyCollectionOption.FALSE 值是 deprecated,因为您应该使用 @OneToMany 关联的 JPA FetchType 属性。

  2. 您使用特定于休眠的方法来映射复合标识符。正如hibernate documentation 中提到的:

复合标识符必须由主键类(例如@EmbeddedId@IdClass)表示的限制仅适用于 JPA。

Hibernate 确实允许通过多个@Id 属性在没有主键类的情况下定义复合标识符。

但如果您想获得更多的可移植性,您应该更喜欢 jpa 允许的方法之一。

【讨论】:

  • 我修改了你建议的所有内容,但得到了同样的错误。我升级了这个问题。我看到了参与者对象和映射中的值但是在再次插入时它说不能将 NULL 插入 ("ABC"."DV_LOAN_PARTICIPANTS"."PARTY_ID")
  • 再次,我只能更新插入失败。
  • @VKP 请在repository.save(parentEntityObject) 之前分享一个代码,您可以在其中获取/创建和填充父对象和子对象
  • 用值设置部分更新了问题,即使硬编码其说方 ID 为 NULL 的值。
  • @VKP 我看不出有任何原因导致这不起作用。你用的是什么休眠版本?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-07-01
  • 1970-01-01
  • 2021-07-24
  • 2011-03-06
  • 1970-01-01
  • 2017-05-22
  • 2016-01-17
相关资源
最近更新 更多