2015-04-10 3 views
27

Ich habe 3 Modelle User, House, UserHouseMap. Und ich muss über die Karte auf das Haus eines Benutzers zugreifen. Das einzige Problem ist, das ist ein alter DB & Ich kann nicht die Tatsache ändern, dass ich User zu UserHouseMap mit user.name, die ein nicht primärer Schlüssel ist.So verbinden Sie Tabellen auf nicht Primärschlüssel mit JPA und Hibernate

Hibernate hält mir eine Fehlermeldung sagen, dass ich es als Primärschlüssel haben müssen, oder ich bekomme Fehler sagen A JPA error occurred (Unable to build EntityManagerFactory): Unable to find column with logical name: name in org.hibernate.mapping.Table(users) and its related supertables and secondary tables

ich versucht habe @Formula als Behelfslösung, aber das hat nicht funktioniert. Ich habe auch versucht , aber das hat nicht funktioniert entweder. Hier ist meine Lösung mit @Formula

@Expose 
@ManyToOne(targetEntity = House.class) 
@Formula("(select * from houses inner join user_house_map on houses.house_name = user_house_map.house_name where user_house_map.user_name=name)") 
public House house; 

Hier war mein Versuch einer @JoinColumnOrFormula Lösung.

@Expose 
@ManyToOne(targetEntity = House.class) 
@JoinColumnsOrFormulas({ 
     @JoinColumnOrFormula([email protected](value="select name from users where users.id= id", referencedColumnName="name")), 
     @JoinColumnOrFormula(column = @JoinColumn(name= "house_name", referencedColumnName="house_name")) 
}) 
public House house; 

Hier ist meine Mapping

@Id 
@GeneratedValue 
@Expose 
public Long id; 

@Expose 
@Required 
@ManyToOne 
@JoinTable(
     name="user_house_map", 
     joinColumns= 
     @JoinColumn(unique=true,name="user_name", referencedColumnName="name"), 
     inverseJoinColumns= 
     @JoinColumn(name="house_name", referencedColumnName="house_name")) 
private House house; 

Hier werden die DB-Schemata

Benutzer

       Table "public.users" 
     Column   |   Type    |   Modifiers   
-----------------------+-----------------------------+----------------------------- 
name     | character varying(255)  | 
id     | integer      | not null 
Indexes: 
    "user_pkey" PRIMARY KEY, btree (id) 
Foreign-key constraints: 
    "housing_fkey" FOREIGN KEY (name) REFERENCES user_house_map(user_name) DEFERRABLE INITIALLY DEFERRED 

Häuser

sind
   Table "public.houses" 
    Column  |   Type   | Modifiers 
---------------+------------------------+----------- 
house_name | character varying(255) | not null 
address  | text     | 
city   | text     | 
state   | text     | 
zip   | integer    | 
zip_ext  | integer    | 
phone   | text     | 
Indexes: 
    "house_pkey" PRIMARY KEY, btree (house_name) 
Referenced by: 
    TABLE "user_house_map" CONSTRAINT "house_map_fkey" FOREIGN KEY (house_name) REFERENCES house(house_name) DEFERRABLE INITIALLY DEFERRED 

UserHouseMap

  Table "public.user_house_map" 
    Column |   Type   | Modifiers 
-------------+------------------------+----------- 
user_name | character varying(255) | not null 
house_name | character varying(255) | not null 
Indexes: 
    "user_house_map_pkey" PRIMARY KEY, btree (user_name) 
    "user_house_map_house_key" btree (house_name) 
Foreign-key constraints: 
    "user_house_map_house_fkey" FOREIGN KEY (house_name) REFERENCES houses(house_name) DEFERRABLE INITIALLY DEFERRED 
Referenced by: 
    TABLE "users" CONSTRAINT "housing_fkey" FOREIGN KEY (name) REFERENCES user_house_map(user_name) DEFERRABLE INITIALLY DEFERRED 

Antwort

25

Dies ist, wie Sie Ihre Mapping aussehen sollte:

@Entity 
public class User { 

    @Id 
    private Long id; 

    private String name; 

    @OneToMany(mappedBy = "user") 
    private List<UserHouseMap> houses = new ArrayList<>(); 
} 

@Entity 
public class House { 

    @Id 
    @Column(name = "house_name", nullable = false, unique = true) 
    private String house_name; 

    private String address; 

    @OneToMany(mappedBy = "house") 
    private List<UserHouseMap> users = new ArrayList<>(); 
} 

@Entity 
public class UserHouseMap implements Serializable { 

    @Id @ManyToOne 
    @JoinColumn(name = "user_name", referencedColumnName = "name") 
    private User user; 

    @Id @ManyToOne 
    @JoinColumn(name = "house_name", referencedColumnName = "house_name") 
    private House house; 
} 

Sowohl User und House Zugang zu ihren zugeordneten UserHouseMap Einheiten, dazu passende das Datenbankschema.

Mit two one-to-many associations ist immer besser, als sich auf viele-zu-viele-Beziehungen verlassen.

+0

Ich weiß, das ist alt, aber ich hatte eine Hölle Zeit mit dem gleichen Fehler. Ihre Lösung funktioniert, aber ich musste eine kleine Änderung vornehmen, aber ich musste @Column hinzufügen (name = "name", nullable = false) private String name; Wenn ich raten musste, warum, ist mein Name der Variablen/Eigenschaft nicht derselbe wie der Name der Spalte als Datenbanktabelle. Nur ein Hinweis für alle anderen, die gleiche/ähnliche Probleme haben. –

+0

Danke. Ich fügte sowohl 'nullable = false' als auch 'unique = true' hinzu, was von jeder Bezeichnerspalte erzwungen werden muss. –

+0

Dies funktioniert nicht, wenn user_name und house_name nicht-primäre Schlüssel sind !! – Archi

Verwandte Themen