如何让Hibernate JPA自动管理列表索引?

问题描述 投票:0回答:3

如何使用列表设置基本的一对多关系并让 Hibernate JPA 自动管理列表的序列索引号?这可以吗?

这是我的测试用例(或多或少);

@Table(name="Policy_Root")
public class PolicyRoot extends BaseDomainModel {

    private List<Policy> policyList = new ArrayList<Policy>();

    @OneToMany(targetEntity=Policy.class, mappedBy="policyRoot", cascade=CascadeType.ALL)
    @IndexColumn(name="policy_sequence", base=0, nullable=false)
    public List<Policy> getPolicyList() {
        return policyList;
    }

    public void setPolicyList(List<Policy> policyList) {
        this.policyList = policyList;
    }

    public void addPolicy(Policy policy) {
        policyList.add(policy);
        policy.setPolicyRoot(this);
    }

    public void addPolicy(int sequence, Policy policy) {
        policyList.add(sequence, policy);
        policy.setPolicyRoot(this);
    }
}

@Entity()
@Table(name="Policy")
public class Policy extends BaseDomainModel {

    /** The position of this policy record within the list of policy's belong to the parent PolicyRoot    */
    private int policySequence;

    /** Birectional pointer to parent */
    private PolicyRoot policyRoot;

    @Column(name="policy_sequence")
    public int getPolicySequence() {
        return policySequence;
    }

    public void setPolicySequence(int policySequence) {
        this.policySequence = policySequence;
    }

    @ManyToOne
    @JoinColumn(name="policy_root_oid", nullable=false)
    public PolicyRoot getPolicyRoot() {
        return policyRoot;
    }

    public void setPolicyRoot(PolicyRoot policyRoot) {
        this.policyRoot = policyRoot;
    }
}


    @Test
    public void testCreation() {
        Policy policy1 = new Policy();
        Policy policy2 = new Policy();

        // Uncomment the following and the test case works - but I don't want to manage the sequence numbers
        //policy2.setPolicySequence(1);

        PolicyRoot policyRoot = new PolicyRoot();
        policyRoot.addPolicy(policy1);
        policyRoot.addPolicy(policy2);

        ServiceImplFacade.getPersistenceFacade().persistSingleItem(policyRoot);
        Long oid = policyRoot.getOid();
        PolicyRoot policyRootFromDB = ServiceImplFacade.getPersistenceFacade().getEntityManager().find(PolicyRoot.class, oid);

        assertEquals(2, policyRootFromDB.getPolicyList().size());
    }

如果我取消注释policy2.setPolicySequence(1);行然后测试用例通过,但我认为我不需要这样做。我希望 Hibernate 为我做这件事。我的理解是它可以,但如果它不能,那么知道它不能也是一个很好的答案。

我尝试过设置可空、可插入和可更新的各种组合,但我可能错过了一个。

这可能吗? - 如果是的话怎么办?

java hibernate jpa one-to-many
3个回答
2
投票

找到了答案——它是围绕获得可空和可插入的正确组合。还必须在 Integer 处创建“子索引”,以便它可以为空,并且下面还有一个“可选”标志。

public class PolicyRoot extends BordereauxBaseDomainModel {

     private List<Policy> policyList = new ArrayList<Policy>();

    @OneToMany(cascade=CascadeType.ALL)
    @IndexColumn(name="policy_sequence", nullable=false, base=0)
    @JoinColumn(name="policy_root_oid", nullable=false)
    public List<Policy> getPolicyList() {
        return policyList;
    }

    public void setPolicyList(List<Policy> policyList) {
        this.policyList = policyList;
    }
}


public class Policy extends BordereauxBaseDomainModel {

    /** The position of this policy record within the list of policy's belong to the parent PolicyRoot    */
    private Integer policySequence;

    /** Birectional pointer to parent */
    private PolicyRoot policyRoot;

    @Column(name="policy_sequence", insertable=false, updatable=false)
    public Integer getPolicySequence() {
        return policySequence;
    }

    public void setPolicySequence(Integer policySequence) {
        this.policySequence = policySequence;
    }

    @ManyToOne(optional=false)
    @JoinColumn(name="policy_root_oid", insertable=false, updatable=false, nullable=false)
    public PolicyRoot getPolicyRoot() {
        return policyRoot;
    }

    public void setPolicyRoot(PolicyRoot policyRoot) {
        this.policyRoot = policyRoot;
    }
}

Google 搜索了一段时间后,在下一页找到了答案。

http://opensource.atlassian.com/projects/hibernate/browse/HHH-4390


0
投票

做这样的事情:

@Entity
class Parent {

    @OneToMany
    @IndexColumn(name = "index_column")
    List<Child> children;
}

@Entity
class Child {

    @ManyToOne
    Parent parent;
    @Column(name = "index_column")
    Integer index;

    @PrePersist
    @PreUpdate
    private void prepareIndex() {
        if (parent != null) {
            index = parent.children.indexOf(this);
        }
    }
}

0
投票

我要发布这个答案,因为我最近遇到了同样的问题,这个问题虽然已经过时,但在研究中不断出现。

@IndexColumn 注释很久以前就已被弃用。事实上,实际上建议使用 @OrderColumn 注释来代替。第二个注释不仅简化了语法而无需指定

base
属性,而且还避免了在详细信息类中声明额外的字段。在本例中,是
policySequence
类中的
Policy
字段。

这是上一个片段的更新版本:

@Table(name="Policy_Root")
public class PolicyRoot extends BaseDomainModel {

    private List<Policy> policyList = new ArrayList<Policy>();

    @OneToMany(targetEntity=Policy.class, mappedBy="policyRoot", cascade=CascadeType.ALL)
    @OrderColumn(name="policy_sequence", nullable=false)
    public List<Policy> getPolicyList() {
        return policyList;
    }

    public void setPolicyList(List<Policy> policyList) {
        this.policyList = policyList;
    }

    public void addPolicy(Policy policy) {
        policyList.add(policy);
        policy.setPolicyRoot(this);
    }

    public void addPolicy(int sequence, Policy policy) {
        policyList.add(sequence, policy);
        policy.setPolicyRoot(this);
    }
}

@Entity()
@Table(name="Policy")
public class Policy extends BaseDomainModel {

    //No need to declare the policySequence field

    /** Birectional pointer to parent */
    private PolicyRoot policyRoot;

    @Column(name="policy_sequence")
    public int getPolicySequence() {
        return policySequence;
    }

    public void setPolicySequence(int policySequence) {
        this.policySequence = policySequence;
    }

    @ManyToOne
    @JoinColumn(name="policy_root_oid", nullable=false)
    public PolicyRoot getPolicyRoot() {
        return policyRoot;
    }

    public void setPolicyRoot(PolicyRoot policyRoot) {
        this.policyRoot = policyRoot;
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.