为什么在 JPA 中没有为插入语句分配值
Why Value is not getting assigned in JPA for insert statement
您好,我有几个实体 class,如下所示,使用 lombok 作为 getter 和 setter
父实体Class有
@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;
}
子实体Class有
@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;
}
服务中class我正在调用保存操作
repository.save(parentEntityObject);
我能够执行更新语句,但是当我尝试为子实体插入新行时 class 我收到一条错误消息
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);
我做错了什么?
你这部分问题的根本原因:
@OneToMany(targetEntity = DVLoanParticipants.class,cascade = CascadeType.ALL)
@JoinColumn(name = "LOAN_ID")
@MapKey(name="dvpParticipantName")
private Map<String, DVLoanParticipants> dvLoanParticipantsMap;
实际上对于您的情况,@JoinColumn 中的列名称表示:
If the join is for a unidirectional OneToMany mapping using a foreign key mapping strategy, the foreign key is in the table of the target entity.
因此,为了清晰起见,假设您要映射以下架构:
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);
和几个注释:
LazyCollectionOption.TRUE
和 LazyCollectionOption.FALSE
值是 deprecated 因为您应该使用 @OneToMany
关联的 JPA FetchType
属性.
您使用休眠特定的方法来映射复合标识符。正如 hibernate documentation:
中提到的
The restriction that a composite identifier has to be represented by a primary key class (e.g. @EmbeddedId
or @IdClass
) is only JPA-specific.
Hibernate does allow composite identifiers to be defined without a primary key class via multiple @Id
attributes.
但是如果你想获得更多的可移植性,你应该更喜欢 jpa 允许的方法之一。
您好,我有几个实体 class,如下所示,使用 lombok 作为 getter 和 setter
父实体Class有
@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;
}
子实体Class有
@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;
}
服务中class我正在调用保存操作
repository.save(parentEntityObject);
我能够执行更新语句,但是当我尝试为子实体插入新行时 class 我收到一条错误消息
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);
我做错了什么?
你这部分问题的根本原因:
@OneToMany(targetEntity = DVLoanParticipants.class,cascade = CascadeType.ALL)
@JoinColumn(name = "LOAN_ID")
@MapKey(name="dvpParticipantName")
private Map<String, DVLoanParticipants> dvLoanParticipantsMap;
实际上对于您的情况,@JoinColumn 中的列名称表示:
If the join is for a unidirectional OneToMany mapping using a foreign key mapping strategy, the foreign key is in the table of the target entity.
因此,为了清晰起见,假设您要映射以下架构:
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);
和几个注释:
LazyCollectionOption.TRUE
和LazyCollectionOption.FALSE
值是 deprecated 因为您应该使用@OneToMany
关联的 JPAFetchType
属性.您使用休眠特定的方法来映射复合标识符。正如 hibernate documentation:
中提到的
The restriction that a composite identifier has to be represented by a primary key class (e.g.
@EmbeddedId
or@IdClass
) is only JPA-specific.Hibernate does allow composite identifiers to be defined without a primary key class via multiple
@Id
attributes.
但是如果你想获得更多的可移植性,你应该更喜欢 jpa 允许的方法之一。