[hibernate-issues] [Hibernate-JIRA] Commented: (HHH-3410) @OneToMany forces unique key in @JoinTable when inverseJoinColumns = @JoinColumn(unique=false)

Marc Nufer (JIRA) noreply at atlassian.com
Wed Nov 5 05:24:05 EST 2008


    [ http://opensource.atlassian.com/projects/hibernate/browse/HHH-3410?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=31600#action_31600 ] 

Marc Nufer commented on HHH-3410:
---------------------------------

I agree with you guys that the unique=false won't take effect.

But please keep in mind that on a oneToMany the inverseColumn HAS to be unique because else it wouldn't be an oneToMany relation!! I've run into this more than once. the correct mapping would be ManyToMany. 

I'll try to explain this with the User and Role. The best is, if you imagine a bidirectional association to understand what's going on.

OneToMany:

- User has a collection of Roles.
- Role has one association to User. 
=> therefore it is not allowed that a role has more than one User

ManyToMany:
- User has a collection of Roles.
- Role has a collection of Users.

now it should be clear why hibernate adds a unique constraint. as i mentioned before: this is a likely error if your using unidirectional mappings and start from the java-point-of-view.

Hope this helps.

Greez
Marc


> @OneToMany forces unique key in @JoinTable when inverseJoinColumns = @JoinColumn(unique=false)
> ----------------------------------------------------------------------------------------------
>
>                 Key: HHH-3410
>                 URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-3410
>             Project: Hibernate Core
>          Issue Type: Bug
>    Affects Versions: 3.2.6
>         Environment: MySQL 5.0.51b, Hibernate Core 3.2.6 GA, Hibernate Annotations 3.3.1 GA
>            Reporter: Kamil Morong
>
> Hi,
> I need to have this class composition with one to many relation:
> @Entity
> @Table(name="USER")
> public class User implements java.io.Serializable {
>     private Long id;
>     private String username;
>     private String password;
>     private Set<Role> roles = new LinkedHashSet<Role>();
>     public User() {
>     }       
>     @Id
>     @GeneratedValue(strategy = GenerationType.AUTO)
>     @Column(name = "USER_ID")
>     public Long getId() {
>         return id;
>     }
>     public void setId(Long id) {
>         this.id = id;
>     }
>     @Column(name="USERNAME", nullable=false, unique=true)
>     public String getUsername() {
>         return username;
>     }
>     public void setUsername(String userName) {
>         this.username = userName;
>     }
>     @Column(name="PASSWORD", nullable=false)
>     public String getPassword() {
>         return password;
>     }
>     public void setPassword(String password) {
>         this.password = password;
>     }
>     @CollectionOfElements
>     @OneToMany(cascade={CascadeType.PERSIST, CascadeType.MERGE})
>     @JoinTable(name = "USER_ROLE",
>                joinColumns = @JoinColumn(name = "USER_ID", unique=false),
>                inverseJoinColumns = @JoinColumn(name = "ROLE_ID", unique=false))
>     @Cascade(org.hibernate.annotations.CascadeType.SAVE_UPDATE)
>     @LazyCollection(LazyCollectionOption.FALSE)
>     public Set<Role> getRoles() {
>         return roles;
>     }
>     public void setRoles(Set<Role> roles) {
>         this.roles = roles;
>     }
> }
> @Entity
> @Table(name="ROLE")
> public class Role implements java.io.Serializable {
>     private Long id;
>     private String name;
>     public Role() {
>     }
>     @Id
>     @GeneratedValue(strategy = GenerationType.AUTO)
>     @Column(name = "ROLE_ID")
>     public Long getId() {
>         return id;
>     }
>     public void setId(Long id) {
>         this.id = id;
>     }
>     @Column(name="NAME", nullable=false, unique=true)
>     public String getName() {
>         return name;
>     }
>     public void setName(String name) {
>         this.name = name;
>     }
> }
> This will create db tables like SQL script
> CREATE TABLE `user` (
>   `USER_ID` BIGINT(20) NOT NULL AUTO_INCREMENT,
>   `PASSWORD` VARCHAR(255) NOT NULL DEFAULT '',
>   `USERNAME` VARCHAR(255) NOT NULL DEFAULT '',
>   PRIMARY KEY (`USER_ID`),
>   UNIQUE KEY `USERNAME` (`USERNAME`)
> );
> CREATE TABLE `role` (
>   `ROLE_ID` BIGINT(20) NOT NULL AUTO_INCREMENT,
>   `NAME` VARCHAR(255) NOT NULL DEFAULT '',
>   PRIMARY KEY (`ROLE_ID`),
>   UNIQUE KEY `NAME` (`NAME`)
> );
> CREATE TABLE `user_role` (
>   `USER_ID` BIGINT(20) NOT NULL,
>   `ROLE_ID` BIGINT(20) NOT NULL,
>   PRIMARY KEY (`USER_ID`, `ROLE_ID`),
>   UNIQUE KEY `ROLE_ID` (`ROLE_ID`),
>   KEY `FKBC16F46A1174FFAB` (`ROLE_ID`),
>   KEY `FKBC16F46AB69FC38B` (`USER_ID`),
>   CONSTRAINT `FKBC16F46AB69FC38B` FOREIGN KEY (`USER_ID`) REFERENCES `user` (`USER_ID`),
>   CONSTRAINT `FKBC16F46A1174FFAB` FOREIGN KEY (`ROLE_ID`) REFERENCES `role` (`ROLE_ID`)
> );
> Tables USER and ROLE are right, but the join table USER_ROLE still have defined UNIQUE KEY `ROLE_ID` (`ROLE_ID`).
> This causes there cannot be one user with many roles.
> There must be some bug while generating database scheme. I am not able to remove unique key.

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://opensource.atlassian.com/projects/hibernate/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

        



More information about the hibernate-issues mailing list