【问题标题】:How do I dynamically generate JPA Id column based on parent?如何根据父级动态生成 JPA Id 列?
【发布时间】:2021-03-23 17:44:22
【问题描述】:

我有一个如下所示的 JSON 文件...

{
  "accountId": "123",
  "parties":[
    {
      "name": "John Doe"
    }
  ]
}

我可以使用类似的东西解析这个很好

public class Account{
  private String id;
  @JsonProperty("parties")
  private List<Party> parties;
}

public class Party{
  private String name;
}

但是,SQL 表 PARTY 包含一个复合键作为 ID。这是名称和父帐户 ID 的复合键。有没有办法在没有单独课程的情况下做到这一点?我试过这个...

@JsonBackReference
private Account parent;

public class GetIdConverter implements AttributeConverter<String, String> {
    @Override
    public String convertToDatabaseColumn(String b) {
        if(parent == null){
            logger.error("couldn't find the parent");
        }
        return parent.getId();
    }

    @Override
    public String convertToEntityAttribute(String s) {
        return s;
    }
}

但是当我尝试插入时,我得到...

IdentifierGenerationException: 这个类的 ids 必须在调用 save() 之前手动分配

【问题讨论】:

    标签: java jpa jackson jackson-dataformat-xml


    【解决方案1】:

    不幸的是,在 JPA 中定义复合键只有两个选项:@IdClass@EmbeddedId 注释,在这两种情况下我们都必须创建一个单独的类。为复合类创建类背后的基本思想是了解我们的键包含多个主键字段并将此对象视为原子对象。将复合键作为一个类的想法使得在任何实现 JPA 的结构中使用实体键变得很容易。

    像选项一样,您可以将两个类合并为一个实体:

    @Entity
    @Table
    @IdClass(PartyEntity.PartyId.class)
    public class PartyEntity {
    
        public static class PartyId implements Serializable {
            private String accountId;
    
            private String name;
    
            public PartyId() {
            }
    
            public PartyId(String accountId, String name) {
                this.accountId = accountId;
                this.name = name;
            }
    
            @Override
            public boolean equals(Object o) {
                if (this == o) return true;
                if (!(o instanceof PartyId)) return false;
                PartyId partyId = (PartyId) o;
                return Objects.equals(accountId, partyId.accountId) &&
                        Objects.equals(name, partyId.name);
            }
    
            @Override
            public int hashCode() {
                return Objects.hash(accountId, name);
            }
        }
    
        @Id
        private String accountId;
    
        @Id
        private String name;
    
        //getters and setters
    }
    

    【讨论】:

      【解决方案2】:

      对 saver 的回答略有改进 - 您可以尝试以下映射:

      public class Account{
        private String id;
      
        @JsonProperty("parties")
        @JsonManagedReference
        private List<Party> parties;
      }
      
      @IdClass(PartyEntity.PartyId.class)
      public class Party {
      
          @JsonBackReference
          @Id
          @ManyToOne
          private Account account;
      
      
          @Id
          private String name;
      }
      
      

      请参阅spec 的“派生标识符示例”部分中的第一个示例

      【讨论】:

      • 抱歉还没来得及尝试,希望今天谢谢!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-02-24
      • 1970-01-01
      • 1970-01-01
      • 2012-09-12
      • 1970-01-01
      • 2016-06-05
      相关资源
      最近更新 更多