为什么没有在JPA中为insert语句分配Value



Hi我有两个实体类,如下所示,使用lombok进行getter和setters

父实体类具有

@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
(?, ?, ?)

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

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);

我做错了什么?

这部分问题的根本原因:

@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值已弃用,因为您应该使用@OneToMany关联的JPAFetchType属性。

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

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

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

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

最新更新