Search code examples
javamysqlspringhibernatehibernate-mapping

Hibernate One-To-Many Mapping issue using @JoinTable


I have two tables: User And Team

User

  • UserId
  • 4 digit Password/pin

Team

  • Team_id
  • TeamName

Constraints 1 user can only belong to one team whereas 1 team can have many users. I have already normalized the database and the third table()Join Table) named user_team will be as follows:

User_Team[JOIN TABLE]

  • User_id(This is a Foreign Key from User Table)
  • Team_Id(This is a Foreign Key from Team Table)

While implementing this in Hibernate using @JoinColumn Attribute and @OneToMany annotations its throwing following error:

A Foreign key refering com.project.hibernate.Team from com.project.hibernate.User has the wrong number of column. should be 2

Exception in thread "main" org.hibernate.AnnotationException: A Foreign key refering com.project.hibernate.Team from com.project.hibernate.User has the wrong number of column. should be 2 at org.hibernate.cfg.annotations.TableBinder.bindFk(TableBinder.java:657) at org.hibernate.cfg.annotations.CollectionBinder.bindCollectionSecondPass(CollectionBinder.java:1610) at org.hibernate.cfg.annotations.CollectionBinder.bindManyToManySecondPass(CollectionBinder.java:1335) at org.hibernate.cfg.annotations.CollectionBinder.bindStarToManySecondPass(CollectionBinder.java:800) at org.hibernate.cfg.annotations.CollectionBinder$1.secondPass(CollectionBinder.java:725) at org.hibernate.cfg.CollectionSecondPass.doSecondPass(CollectionSecondPass.java:54) at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1621) at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1589) at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:278) at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.build(MetadataBuildingProcess.java:83) at org.hibernate.boot.internal.MetadataBuilderImpl.build(MetadataBuilderImpl.java:418) at org.hibernate.boot.internal.MetadataBuilderImpl.build(MetadataBuilderImpl.java:87) at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:691) at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:726) at com.project.hibernate.User_TeamDAO.main(User_TeamDAO.java:26)


Solution

  • You have a composed key containing two fields:

    @Id
    @Column(name="team_id")
    private String team_id;
    
    @Id
    @Column(name="team_name")
    private String team_name;
    

    Whereas your join table has only one key per table:

    @OneToMany(cascade=CascadeType.ALL)
    @JoinTable(name="user_team",
            joinColumns=@JoinColumn(name="team_id"),
            inverseJoinColumns=@JoinColumn(name="user_id"))
    private List<User> user;
    

    You need to use all keys that make the relationship, something like that (of course table also need to have the right columns):

    @OneToMany(cascade=CascadeType.ALL)
    @JoinTable(name="user_team",
            joinColumns=@JoinColumn({@JoinColumn(name="team_id"), @JoinColumn(name="team_name")}),
            inverseJoinColumns=@JoinColumn(name="user_id"))
    private List<User> user;