在 Spring 数据 jdbc 中使用值对象作为 ID - 无法插入

问题描述

我正在尝试在 Spring 数据 JDBC 中使用 PartyId(一个值对象)作为 Id。我正在设置 PartyId 中的值(您可以在下面的第一个屏幕截图中看到),但在插入时出现以下错误

PartyId debug image

调试原因的屏幕截图

enter image description here

堆栈跟踪

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注释),插入将起作用

解决方法

  1.   @EmbeddedId   //have not found onEmpty parameter in any documentation 
      private PartyId partyId;
    
  2.  @Embeddable
     public class PartyId
    
  3. 覆盖 equals 上的 hashcodeParty class 方法以考虑 partyId 字段。

  4. 转到 PartyId class 并覆盖 equalshashcode 方法以考虑类 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);
        }
    }

}