【问题标题】:JPA Many-to-Many Join table entity with compound key "null id generated "具有复合键“生成空 id”的 JPA 多对多连接表实体
【发布时间】:2013-02-08 00:03:35
【问题描述】:

这是我的实体:

public class Account extends AbstractEntity<Long> {

    @Id
    @SequenceGenerator(name = "accountSequence", sequenceName = "SQ_ACCOUNTS", allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "accountSequence")
    @Column(name = "ACC_ID", nullable = false)
    private Long id;
...
}

public class Integration extends AbstractEntity<Long> {

    @Id
    @SequenceGenerator(name = "integrationSequence", sequenceName="SQ_INTEGRATIONS", allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "integrationSequence")
    @Column(name = "INT_ID", nullable = false)
    private Long id;
...
public void addIntegration(Integration integration) {
        IntegrationAccount association = new IntegrationAccount();
            // This does not help
        //association.setIntAccountsPK(new IntAccountsPK(integration.getId(), this.getId()));
        association.setAccount(this);
        association.setIntegration(integration);
        this.integrationAccounts.add(association);
        integration.getIntAccountsCollection().add(association);
    }
}

这是连接表的实体

@Entity
@Table(name = "INT_ACCOUNTS")
public class IntegrationAccount  {

    @EmbeddedId
    protected IntAccountsPK intAccountsPK;

    @JoinColumn(name = "ACC_ID", referencedColumnName = "ACC_ID", insertable = false, updatable = false)
    @ManyToOne
    private Account account;

    @JoinColumn(name = "INT_ID", referencedColumnName = "INT_ID", insertable = false, updatable = false)
    @ManyToOne
    private Integration integration;
...
}
@Embeddable
public class IntAccountsPK  implements Serializable {

    @Column(name = "INT_ID", nullable = false)
    private Long intId;

    @Column(name = "ACC_ID", nullable = false)
    private Long accId;
...
}

当我这样做时:

account.addIntegrations(integrations.getTarget());
account.setCustomer(customer);
accountService.save(account);

我的日志里有这个 引起:org.hibernate.id.IdentifierGenerationException:为:类 com.dhl.dcc.domain.IntegrationAccount 生成 null id

我对这种映射了解不多,请告诉我如何改进这种映射(必须保留连接表的实体)以及如何保存相关集成的帐户?谢谢。

【问题讨论】:

    标签: java hibernate jpa many-to-many jointable


    【解决方案1】:

    我知道这个问题已被标记为已解决,但我不同意接受的答案。这个答案通过在表INT_ACCOUNTS 中添加一个无用的列(新的 id)来修改数据模型。在 Hibernate 中还有另一种方法可以在不修改数据模型的情况下解决这个问题:

    @Entity
    @Table(name = "INT_ACCOUNTS")
    public class IntegrationAccount implements Serializable {
    
        @Id
        @ManyToOne
        @JoinColumn(name = "INT_ID_FK")
        private Integration integration;
    
        @Id
        @ManyToOne
        @JoinColumn(name = "ACC_ID_FK")
        private Account account;
    }
    
    @Entity
    @Table(name = "INTEGRATIONS")
    public class Integration {
    
        @Id
        @SequenceGenerator(name = "integrationSequence", sequenceName = "SQ_INTEGRATIONS", allocationSize = 1)
        @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "integrationSequence")
        @Column(name = "INT_ID")
        private Long id;
    }
    
    @Entity
    @Table(name = "ACCOUNTS")
    public class Account {
    
        @Id
        @SequenceGenerator(name = "accountSequence", sequenceName = "SQ_ACCOUNTS", allocationSize = 1)
        @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "accountSequence")
        @Column(name = "ACC_ID")
        private Long id;
    }
    

    【讨论】:

    • 不修改数据模型的解决方案会好很多。当我按照你的方式做时,我会得到Hibernate: insert into integration (name) values (?) Hibernate: insert into account (name) values (?) Exception in thread "main" java.lang.NullPointerException at org.hibernate.type.descriptor.java.AbstractTypeDescriptor.extractHashCode(AbstractTypeDescriptor.java:88) at org.hibernate.type.AbstractStandardBasicType.getHashCode(AbstractStandardBasicType.java:201) at org.hibernate.type.AbstractStandardBasicType.getHashCode(AbstractStandardBasicType.java:205)
    • 奇怪。它对我来说非常有效。我添加了用于重新创建测试用例的其余映射。你能给我更多关于你现在遇到的错误的信息吗?
    【解决方案2】:

    您可以为您的 IntegrationAccount 创建一个 ID 字段,然后为您的两个字段创建一个唯一约束。

    @Entity
    @Table(name = "INT_ACCOUNTS",
           uniqueConstraints=@UniqueConstraint(columnNames={"ACC_ID", "INT_ID"}))
    public class IntegrationAccount  {
    
        @Id
        private Long id;
    
        @JoinColumn(name = "ACC_ID", referencedColumnName = "ACC_ID", insertable = false, updatable = false)
        @ManyToOne
        private Account account;
    
        @JoinColumn(name = "INT_ID", referencedColumnName = "INT_ID", insertable = false, updatable = false)
        @ManyToOne
        private Integration integration;
    ...
    }
    

    像魅力一样工作!

    【讨论】:

    • 就像你说的那样,谢谢。我还必须删除“insertable = false,updateable false”。
    猜你喜欢
    • 2014-08-16
    • 2015-09-30
    • 1970-01-01
    • 2020-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多