@OneToMany and composite primary keys?

前端 未结 9 1698
温柔的废话
温柔的废话 2020-12-01 03:31

I\'m using Hibernate with annotations (in spring), and I have an object which has an ordered, many-to-one relationship which a child object which has a composite primary key

相关标签:
9条回答
  • 2020-12-01 04:18

    Found this question searching for the answer to it's problem, but it's answers didn't solve my problem, because I was looking for @OneToMany which isn't as good of a fit for the table structure I was going after. @ElementCollection is the right fit in my case. One of the gotchas of it I believe though is that it looks at the entire row of relations as being unique, not just the rows id.

    @Entity
    public class ParentObject {
    @Column(nullable=false, updatable=false)
    @Id @GeneratedValue(generator="...")
    private String id;
    
    @ElementCollection
    @CollectionTable( name = "chidren", joinColumns = @JoinColumn( name = "parent_id" ) )
    private List<ObjectChild> attrs;
    
    ...
    }
    
    @Embeddable
    public static class ObjectChild implements Serializable {
        @Column(nullable=false, updatable=false)
        private String parentId;
    
        @Column(nullable=false, updatable=false)
        private String name;
    
        @Column(nullable=false, updatable=false)
        private int pos;
    
        @Override
        public String toString() {
            return new Formatter().format("%s.%s[%d]", parentId, name, pos).toString();
        }
    
        ... getters and setters REQUIRED (at least they were for me)
    }
    
    0 讨论(0)
  • 2020-12-01 04:21

    After saving the Parent object, you have to explicitly set the parentId in the Child objects for the inserts on the Child objects to work.

    0 讨论(0)
  • 2020-12-01 04:30

    Firstly, in the ParentObject, "fix" the mappedBy attribute that should be set to "parent". Also (but this is maybe a typo) add an @Id annotation:

    @Entity
    public class ParentObject {
        @Id
        @GeneratedValue
        private String id;
    
        @OneToMany(mappedBy="parent", fetch=FetchType.EAGER)
        @IndexColumn(name = "pos", base=0)
        private List<ObjectChild> attrs;
    
        // getters/setters
    }
    

    Then, in ObjectChild, add a name attribute to the objectId in the composite key:

    @Entity
    public class ObjectChild {
        @Embeddable
        public static class Pk implements Serializable {
            @Column(name = "parentId", nullable = false, updatable = false)
            private String objectId;
    
            @Column(nullable = false, updatable = false)
            private String name;
    
            @Column(nullable = false, updatable = false)
            private int pos;
        }
    
        @EmbeddedId
        private Pk pk;
    
        @ManyToOne
        @JoinColumn(name = "parentId", insertable = false, updatable = false)
        private ParentObject parent;
    
        // getters/setters
    
    }
    

    AND also add insertable = false, updatable = false to the @JoinColumn because we are repeating the parentId column in the mapping of this entity.

    With these changes, persisting and reading the entities is working fine for me (tested with Derby).

    0 讨论(0)
提交回复
热议问题