2015-04-10 7 views
27

Ho 3 modelli User, House, UserHouseMap. E ho bisogno di accedere a casa di un utente attraverso la mappa. L'unico problema è che questo è un vecchio DB & Non posso cambiare il fatto che ho bisogno di mappare User a UserHouseMap usando user.name, che è una chiave non primaria.Come unire tabelle su chiave non primaria utilizzando JPA e Hibernate

Hibernate continua a darmi errori dicendo ho bisogno di avere come chiave primaria o io ottenere gli errori dicendo 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

ho cercato @Formula come soluzione alternativa, ma che non ha funzionato. Ho anche provato @JoinColumnOrFormula ma non ha funzionato. Qui è la mia soluzione con @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; 

Qui è stato il mio tentativo di una soluzione @JoinColumnOrFormula.

@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; 

Ecco il mio mappatura

@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; 

Qui ci sono gli schemi DB

Utenti

       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 

Case

   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 

risposta

25

Questo è come la mappatura dovrebbe essere simile:

@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; 
} 

Sia User e House avere accesso ai propri associati UserHouseMap entità, abbinando lo schema del database.

Utilizzare two one-to-many associations è sempre meglio che affidarsi a relazioni molti-a-molti.

+0

So che questo è vecchio ma ho avuto un tempo hellva con questo stesso errore. La tua soluzione funziona, tuttavia ho dovuto apportare una leggera modifica, ma ho dovuto aggiungere @Column (name = "name", nullable = false) private String name; Se dovessi indovinare perché, il mio nome di variabile/proprietà non è lo stesso del nome della colonna come tabella del database. Solo una FYI per chiunque abbia problemi simili/simili. –

+0

Grazie. Ho aggiunto sia 'nullable = false' e' unique = true', che devono essere applicati da qualsiasi colonna identificatore. –

+0

Questo non funzionerà se user_name e house_name non sono chiavi primarie !! – Archi

Problemi correlati