问题描述
我正在尝试在 Spring 数据 JDBC 中使用 PartyId(一个值对象)作为 Id。我正在设置 PartyId 中的值(您可以在下面的第一个屏幕截图中看到),但在插入时出现以下错误。
调试原因的屏幕截图
堆栈跟踪
Caused by: org.springframework.dao.DataIntegrityViolationException: PreparedStatementCallback; sql
[INSERT INTO "party" ("currency_uom_id","description","party_id","party_type_id","status_id","version") VALUES (?,?,?)]; ERROR: null value in column "party_id" violates not-null constraint
Detail: Failing row contains (null,null,Organisation,USD,Enable,1).; nested exception is org.postgresql.util.PsqlException: ERROR: null value in column "party_id" violates not-null constraint
Detail: Failing row contains (null,1).
at org.springframework.jdbc.support.sqlErrorCodesqlExceptionTranslator.doTranslate(sqlErrorCodesqlExceptionTranslator.java:251) ~[spring-jdbc-5.3.5.jar:5.3.5]
at org.springframework.jdbc.support.AbstractFallbacksqlExceptionTranslator.translate(AbstractFallbacksqlExceptionTranslator.java:70) ~[spring-jdbc-5.3.5.jar:5.3.5]
at org.springframework.jdbc.core.JdbcTemplate.translateException(JdbcTemplate.java:1541) ~[spring-jdbc-5.3.5.jar:5.3.5]
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:667) ~[spring-jdbc-5.3.5.jar:5.3.5]
at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:991) ~[spring-jdbc-5.3.5.jar:5.3.5]
at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.update(NamedParameterJdbcTemplate.java:356) ~[spring-jdbc-5.3.5.jar:5.3.5]
at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.update(NamedParameterJdbcTemplate.java:340) ~[spring-jdbc-5.3.5.jar:5.3.5]
at org.springframework.data.jdbc.core.convert.DefaultDataAccessstrategy.insert(DefaultDataAccessstrategy.java:138) ~[spring-data-jdbc-2.1.6.jar:2.1.6]
at org.springframework.data.jdbc.core.JdbcAggregateChangeExecutionContext.executeInsertRoot(JdbcAggregateChangeExecutionContext.java:90) ~[spring-data-jdbc-2.1.6.jar:2.1.6]
at org.springframework.data.jdbc.core.AggregateChangeExecutor.execute(AggregateChangeExecutor.java:66) ~[spring-data-jdbc-2.1.6.jar:2.1.6]
... 96 common frames omitted
错误说, PartyId 为 null ,这消除了数据库约束。
党类作为聚合根
@Accesstype(Accesstype.Type.PROPERTY)
public class Party implements AggregateRoot {
//Business key Id;
@Id//Use by spring data jdbc
@Embedded(onEmpty = USE_NULL)
private PartyId partyId; // private String partyId - this is working (removing @Embedded also)
private String description;
@Embedded(onEmpty = USE_NULL)
private PartyTypeId partyTypeId;
@Embedded(onEmpty = USE_NULL)
private CurrencyUomId currencyUomId;
@Embedded(onEmpty = USE_NULL)
private StatusId statusId;
@Version
private long version;
/*private List<PartyAttributes> partyAttributes = new ArrayList<>();
private List<PartyCarrierAccount> partyCarrierAccounts = new ArrayList<>();*/
//Only package level access
public Party(PartyId partyId,String description,PartyTypeId partyTypeId,CurrencyUomId currencyUomId,StatusId statusId,List<PartyAttributes> partyAttributes,List<PartyCarrierAccount> partyCarrierAccounts){
this.partyId = partyId;
this.partyTypeId = partyTypeId;
this.currencyUomId = currencyUomId;
this.statusId = statusId;
}
如果我将partyId设为String(Party类中的私有StringpartyId,显然从partyId中删除@Embeded注释),插入将起作用
解决方法
-
@EmbeddedId //have not found onEmpty parameter in any documentation private PartyId partyId;
-
@Embeddable public class PartyId
-
覆盖
equals
上的hashcode
和Party class
方法以考虑partyId
字段。 -
转到
PartyId class
并覆盖equals
和hashcode
方法以考虑类PartyId
的所有 id 字段
Spring Data JDBC 尚不支持嵌入式 ID。但由于您的 PartyId
似乎只包含一个值,您可以为其注册自定义转换并获得您想要的结果。
Here is an example for registering conversions.
你创建一个如下的配置类
@Configuration
static class ConversionConfigurationApplication extends AbstractJdbcConfiguration {
@Override
@Bean
public JdbcCustomConversions jdbcCustomConversions() {
return new JdbcCustomConversions(asList(PartyIdToString.INSTANCE,StringToPartyId.INSTANCE));
}
@WritingConverter
enum PartyIdToString implements Converter<PartyId,String> {
INSTANCE;
@Override
public String convert(PartyId source) {
return source.partyId;
}
}
@ReadingConverter
enum StringToPartyId implements Converter<String,PartyId> {
INSTANCE;
@Override
public PartyId convert(String source) {
return new PartyId(source);
}
}
}