2009-09-27 13 views
6

Zdefiniowałem relację wiele do wielu między moimi dwoma klasami encji User i Permission. Użytkownik ma podstawowy klucz złożony z nazwy użytkownika i wojewódzkiego identyfikatora użytkownika, a moja tabela uprawnień ma zwykły identyfikator liczby całkowitej. Tabela UserPermission ma trzy klucze obce jako klucz podstawowy: nazwa_użytkownika, identyfikator_domia i ID_odpisu.Hibernate: klucz obcy ma niepoprawną liczbę kolumn

Ponieważ jest to starsza baza danych, nie będę miał okazji wykonać Right Thing (™) i utworzyć klucz podstawowy integer na użytkowniku.

ja zdefiniował wiele do wielu relacji takiego w User.class:

@ManyToMany(targetEntity=Permission.class, cascade={ CascadeType.PERSIST, CascadeType.MERGE }) 
@JoinTable(name="tblUserPermission", 
joinColumns = { @JoinColumn(name="username"), @JoinColumn(name="countyId") }, 
inverseJoinColumns = { @JoinColumn(name="permissionId") }) 
private Collection<Permission> permissions; 

Permission.class mówi tak:

@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, mappedBy = "permissions", targetEntity = User.class) 
private Collection<User> users; 

Myślałem, że to droga , ale gdy uruchomię mój kontekst Wiosna, która używa Hibernacja 3, otrzymuję:

Caused by: org.hibernate.AnnotationException: A Foreign key refering com.mydomain.data.entities.User from com.mydomain.data.entities.Permission has the wrong number of column. should be 1 

Co zrobiłem nie tak w moim Annot acja? Powinno być 2, a nie 1.


Aktualizacja:

Artur zaproponował dodam referencedColumnName, ale dał mi nowy wyjątek:

Caused by: org.hibernate.AnnotationException: referencedColumnNames(username, countyId) of com.mydomain.data.entities.Permission.permissions referencing com.mydomain.data.entities.User not mapped to a single property 

Na jego wniosek, tutaj po kodzie : Permission.Class:

package com.mydomain.data.entities; 

import java.io.Serializable; 
import java.util.Collection; 
import javax.persistence.*; 
import org.hibernate.annotations.ForeignKey; 

@Entity 
@Table(name = "tblPermission") 
public class Permission extends PublishableEntityImpl implements Serializable, Cloneable { 

    private static final long serialVersionUID = 7155322069731920447L; 

    @Id 
    @Column(name = "PermissionId", length = 8, nullable = false) 
    private String PermissionId = ""; 

    @ManyToOne(fetch=FetchType.LAZY) 
    @JoinColumn(name = "CountyId", nullable = false) 
    @ForeignKey(name="FK_CountyID") 
    private County county; 

    @Column(name = "Permission", nullable = true) 
    private Integer permission = 1; 

    @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, 
      mappedBy = "Permissions", 
      targetEntity = Item.class) 
    private Collection<Item> items; 

    @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, 
      mappedBy = "Permissions", 
      targetEntity = User.class) 
    private Collection<User> users; 

    /** Getters and Setters **/ 
} 

i User.class

package com.mydomain.data.entities; 

import java.util.*; 
import java.io.Serializable; 
import javax.persistence.*; 
import org.hibernate.annotations.ForeignKey; 
import org.hibernate.annotations.IndexColumn; 
import org.springframework.security.core.GrantedAuthority; 
import org.springframework.security.core.authority.GrantedAuthorityImpl; 
import org.springframework.security.core.userdetails.UserDetails; 

@Entity 
@Table(name = "tblUser") 
public class User extends PublishableEntityImpl implements Serializable, Cloneable { 

    @Id 
    @Column(name = "CountyId", nullable = false) 
    private Integer countyId; 

    @Id 
    @Column(name = "Username", length = 25, nullable = false) 
    private String username; 

    @ManyToOne(fetch=FetchType.LAZY) 
    @JoinColumn(name = "CountyId", nullable = false, insertable=false, updatable=false) 
    @ForeignKey(name="FK_CountyID") 
    private County county; 

    @Column(name = "Name", length = 50, nullable = true) 
    private String name; 

    @Column(name = "Password", length = 30, nullable = true) 
    private String password; 

    @Column(name = "Role", nullable = false) 
    private Integer role; 

    @ManyToMany(targetEntity=Permission.class, 
      cascade={ CascadeType.PERSIST, CascadeType.MERGE }) 
    @JoinTable(name="tblUserPermission", 
      joinColumns = { @JoinColumn(name="Username", referencedColumnName="Username"), @JoinColumn(name="CountyId", referencedColumnName="CountyId") }, 
      inverseJoinColumns = { @JoinColumn(name="PermissionId", referencedColumnName="PermissionId") }) 
    private Collection<Permission> permissions; 

    @OneToMany(fetch=FetchType.LAZY, mappedBy="county") 
    @IndexColumn(name="version") 
    private List<Version> versions; 

    /** Getters and setters **/ 
} 

Cheers

Nik

+0

Witam, miałem bardzo sam problem, ale po swoim przykładzie, otrzymuję ten błąd: Referencje nieznany podmiot: java.lang.String. W moim przypadku powiat byłby typem String. –

Odpowiedz

5

W celu rozwiązania referencedColumnName wyjątek

W Użytkownika umieścić

@ManyToMany(cascade={CascadeType.PERSIST, cascadeType.MERGE}) 
private Collection<Permission> permissions; 

I Permission

@ManyToMany(mappedBy="permissions") 
@JoinTable(name="tblUserPermission", 
joinColumns={@JoinColumn(name="permissionId", referencedColumnName="permissionId")}, 
inverseJoinColumns={ 
@JoinColumn(name="username", referencedColumnName="username"),       
@JoinColumn(name="countyId", referencedColumnName="countyId")}) 
private Collection<User> users; 

klasa

public class UserId implements Serializable { 

    private String username; 

    private Integer countyId; 

    // getter's and setter's 

    public boolean equals(Object o) { 

     if(o == null) 
      return false; 

     if(!(o instanceof UserId)) 
      return false; 

     UserId id = (UserId) o; 
     if(!(getUsername().equals(id.getUsername())) 
      return false; 

     if(!(getCountyId().equals(id.getCountyId())) 
      return false; 

     return true; 
    } 

    public int hachcode() { 
     // hashcode 
    } 

} 

Następnie UserId w klasie User umieścić

@Entity 
@Table(name="tblUser") 
@IdClass(UserId.class) 
public class User ... { 

    @Id 
    private String username; 

    @Id 
    private Integer countyId; 

} 

Pozdrowienia,

+0

Tak więc, aby było jasne, nazwa jest kolumną tabeli w tabeli sprzężenia, podczas gdy odwołanieColumnName jest kolumną tabeli w tabeli encji? W każdym razie, dodając referencjiColumnName dostaję "Powodowane przez: org.hibernate.AnnotationException: referencedColumnNames (nazwa_użytkownika, countyId) com.mydomain.data.entities.Permission.permissions odwołujące się do com.mydomain.data.entities.Użytkownik nieprzypisany do pojedynczej właściwości "co jest zabawne, ponieważ" uprawnienia "należą do klasy Użytkownik, a nie klasa Pozwolenie – niklassaers

+0

BTW, dlaczego usunięto obiekt targetEntity = Permission.class? – niklassaers

+0

Po chwili zadeklaruj rodzaj kolekcji Collection i Collection targetEntity nie jest konieczne.Będę sprawdzać twoją pierwszą wątpliwość –