简体   繁体   中英

Spring and JPA 2.0 - Composite key in many to many relationship with extra column

I have two entities Foo and Bar in many-to-many relationship. The joining entity is FooBar , and since this entity has another property (its own id), I used @ManyToOne on the owner side ( FooBar ) and @OneToMany in dependent entities ( Foo and Bar ). How to create a FooBarRepository extending CrudRepository without the explicit composite key field inside FooBar ? Ideally, I don't want to change the members of my FooBar class.

I tried to use @IdClass , but I don't want to have fields fooId and barId inside FooBar and I am getting this exception:

Caused by: org.hibernate.AnnotationException: Property of @IdClass not found in entity com.nano.testers.test.FooBar: barId

I also tried to follow the documentation of IdClass and reference columns by name explicitly, but I failed (maybe the solution lies somewhere here?)

The names of the fields or properties in the primary key class and the primary key fields or properties of the entity must correspond and their types must be the same.

I tried to change the names of fields inside Foo and Bar to just id , so that they would be referenced as foo_id and bar_id in the joining table, but the exception was the same.

I don't want to use @EmbeddedId , if that means I need to have a field of FooBarPk type inside the FooBar class.

@Entity
public class Foo {
    @Id
    private Long fooId;

    @OneToMany(mappedBy = "foo", cascade = CascadeType.ALL)
    private Set<FooBar> foobars;
}
@Entity
public class Bar {
    @Id
    private Long barId;

    @OneToMany(mappedBy = "bar", cascade = CascadeType.ALL)
    private Set<FooBar> foobars;
}
@Entity
//@IdClass(FooBarPk.class)
public class FooBar implements Serializable {
    @Id
    private Long fooBarId;

    @Id
    @ManyToOne
    @JoinColumn
    private Foo foo;

    @Id
    @ManyToOne
    @JoinColumn
    private Bar bar;

}
public class FooBarPk implements Serializable {
    private Long fooId;
    private Long barId;
    private Long fooBarId;
}
public interface FooBarRepository extends CrudRepository<FooBar, FooBarPk> {
}

It looks like the names of the fields in the composite key class have to be the same as names of the referenced entities. I think these names don't follow the clean code principles, but I will have to live with this solution for now.

public class FooBarPk implements Serializable {
    private Long foo;
    private Long bar;
    private Long fooBarId;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM