Андрей Б
Андрей Б

Reputation: 65

Many-to-Many self-reference hibernate annotation(with two entity)

I need help with my application.

I'm using Hibernate+Postgresql + Maven.

And I want to create relation many to many in database without @ManyToMany annotation, but with two @OneToMany annotations, but I have some trouble with it. I have User entity and Friendship entity.

@Entity
@Table(name="USER")
@SuppressWarnings("unused")
public class User {
    @Id
    @GeneratedValue
    @Column(name="USER_ID")
    private Long user_id;
    @Column(name="NAME")
    private String name;
    @Column(name="SOURNAME")
    private String sourname;
    @Column(name="BIRTHDAY")
    private String birthday;
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.user1", cascade= CascadeType.ALL)
    private Set<Friendship> friendship = new HashSet<Friendship>(0);
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.user2")

    private Set<Friendship> friendships = new HashSet<Friendship>(0);
//getters and setters
}
@Entity
@Table(name="FRIENDSHIP")
@AssociationOverrides({
        @AssociationOverride(name = "pk.user1", joinColumns = @JoinColumn(name = "user_id")),
        @AssociationOverride(name = "pk.user2", joinColumns = @JoinColumn(name = "user_id")) })
@SuppressWarnings("unused")
public class Friendship {
    @EmbeddedId
    private FriendshipId pk = new FriendshipId();
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "CREATED_DATE", nullable = false, length = 10)
    private Date createdDate;


    public FriendshipId getPk() {
        return pk;
    }

    public void setPk(FriendshipId pk) {
        this.pk = pk;
    }

    public Date getCreatedDate() {
        return createdDate;
    }

    public void setCreatedDate(Date createdDate) {
        this.createdDate = createdDate;
    }

    @Transient
    public User getUser1(){return getPk().getUser1();}

    @Transient
    public User getUser2(){
        return getPk().getUser2();
    }

    public void setUser1(User user1){ getPk().setUser1(user1); }

    public void setUser2(User user2){getPk().setUser2(user2);}

}
@Embeddable
public class FriendshipId implements Serializable{
    @ManyToOne
    private User user1;
    @ManyToOne
    private User user2;

    public User getUser1() {
        return user1;
    }

    public void setUser1(User user1) {
        this.user1 = user1;
    }

    public User getUser2() {
        return user2;
    }

    public void setUser2(User user2) {
        this.user2 = user2;
    }


    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        FriendshipId that = (FriendshipId) o;

        if (user1 != null ? !user1.equals(that.user1) : that.user2 != null) return false;
        if (user2 != null ? !user2.equals(that.user2) : that.user2 != null) return false;

        return true;
    }

    public int hashCode() {
        int result;
        result = (user1 != null ? user1.hashCode() : 0);
        result = 31 * result + (user2 != null ? user2.hashCode() : 0);
        return result;
    }

}

and I have this stacktrace:

Caused by: org.hibernate.MappingException: Repeated column in mapping for entity: model.Friendship column: user_id (should be mapped with insert="false" update="false")
    at org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:696)
    at org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:737)
    at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:493)
    at org.hibernate.mapping.RootClass.validate(RootClass.java:270)
    at org.hibernate.cfg.Configuration.validate(Configuration.java:1324)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1782)

help me!

UPD:

@Entity
@Table(name="FRIENDSHIP")
@AssociationOverrides({
        @AssociationOverride(name = "pk.user1", joinColumns = @JoinColumn(name = "user_id_1")),
        @AssociationOverride(name = "pk.user2", joinColumns = @JoinColumn(name = "user_id_2")) })
@SuppressWarnings("unused")
public class Friendship

and stacktrace now:

INFO: HHH000227: Running hbm2ddl schema export
Hibernate: alter table FRIENDSHIP drop constraint FK_82a932pmyph72ritrnbumysli
апр 08, 2016 10:21:26 AM org.hibernate.tool.hbm2ddl.SchemaExport perform
ERROR: HHH000389: Unsuccessful: alter table FRIENDSHIP drop constraint FK_82a932pmyph72ritrnbumysli
апр 08, 2016 10:21:26 AM org.hibernate.tool.hbm2ddl.SchemaExport perform
ERROR: constraint "fk_82a932pmyph72ritrnbumysli" in table "friendship" not exist
Hibernate: alter table FRIENDSHIP drop constraint FK_nlu74mncjyeaokaaj0c5eomrp
Hibernate: drop table if exists FRIENDSHIP cascade
апр 08, 2016 10:21:26 AM org.hibernate.tool.hbm2ddl.SchemaExport perform
ERROR: HHH000389: Unsuccessful: alter table FRIENDSHIP drop constraint FK_nlu74mncjyeaokaaj0c5eomrp
апр 08, 2016 10:21:26 AM org.hibernate.tool.hbm2ddl.SchemaExport perform
ERROR:  constraint "fk_nlu74mncjyeaokaaj0c5eomrp" in table "friendship" not exist
апр 08, 2016 10:21:26 AM org.hibernate.tool.hbm2ddl.SchemaExport perform
ERROR: HHH000389: Unsuccessful: drop table if exists USER cascade
апр 08, 2016 10:21:26 AM org.hibernate.tool.hbm2ddl.SchemaExport perform
Hibernate: drop table if exists USER cascade
ERROR: syntax error (approximate location: "USER")
  Position: 22
Hibernate: drop sequence hibernate_sequence
Hibernate: create table FRIENDSHIP (CREATED_DATE timestamp not null, user_id_2 int8, user_id_1 int8, primary key (user_id_1, user_id_2))
апр 08, 2016 10:21:26 AM org.hibernate.tool.hbm2ddl.SchemaExport perform
ERROR: HHH000389: Unsuccessful: create table USER (USER_ID int8 not null, BIRTHDAY varchar(255), NAME varchar(255), SOURNAME varchar(255), primary key (USER_ID))
Hibernate: create table USER (USER_ID int8 not null, BIRTHDAY varchar(255), NAME varchar(255), SOURNAME varchar(255), primary key (USER_ID))
апр 08, 2016 10:21:26 AM org.hibernate.tool.hbm2ddl.SchemaExport perform
Hibernate: alter table FRIENDSHIP add constraint FK_82a932pmyph72ritrnbumysli foreign key (user_id_2) references USER
ERROR:syntax error (approximate location: "USER")
  Position: 14
апр 08, 2016 10:21:26 AM org.hibernate.tool.hbm2ddl.SchemaExport perform
ERROR: HHH000389: Unsuccessful: alter table FRIENDSHIP add constraint FK_82a932pmyph72ritrnbumysli foreign key (user_id_2) references USER
апр 08, 2016 10:21:26 AM org.hibernate.tool.hbm2ddl.SchemaExport perform
ERROR: syntax error (approximate location: "USER")
  Position: 103
Hibernate: alter table FRIENDSHIP add constraint FK_nlu74mncjyeaokaaj0c5eomrp foreign key (user_id_1) references USER
апр 08, 2016 10:21:26 AM org.hibernate.tool.hbm2ddl.SchemaExport perform
ERROR: HHH000389: Unsuccessful: alter table FRIENDSHIP add constraint FK_nlu74mncjyeaokaaj0c5eomrp foreign key (user_id_1) references USER
апр 08, 2016 10:21:26 AM org.hibernate.tool.hbm2ddl.SchemaExport perform
ERROR:  syntax error (approximate location: "USER")
  Position: 103
Hibernate: create sequence hibernate_sequence
апр 08, 2016 10:21:26 AM org.hibernate.tool.hbm2ddl.SchemaExport execute
INFO: HHH000230: Schema export complete

Upvotes: 1

Views: 567

Answers (1)

v.ladynev
v.ladynev

Reputation: 19956

I think the problem with this

@AssociationOverrides({
        @AssociationOverride(name = "pk.user1", joinColumns = @JoinColumn(name = "user_id")),
        @AssociationOverride(name = "pk.user2", joinColumns = @JoinColumn(name = "user_id")) })

You need to use different names for the foreign key columns user_id_1, user_id_2

@AssociationOverrides({
        @AssociationOverride(name = "pk.user1", joinColumns = @JoinColumn(name = "user_id_1")),
        @AssociationOverride(name = "pk.user2", joinColumns = @JoinColumn(name = "user_id_2")) })

Do not give names to tables like User. User is a reserved keyword in PostgreSQL. Please, use lower case plural names with prefix like xxx_users.

You can take a look on other useful prefixes and naming approaches: StrategyOptions, Hibernate5NamingStrategy.

Upvotes: 1

Related Questions