web-dev-qa-db-ja.com

JPAおよびHibernateを使用して非主キーでテーブルを結合する方法

3つのモデルUserHouseUserHouseMapがあります。そして、マップを介してユーザーの家にアクセスする必要があります。唯一の問題は、これが古いDBであり、UserUserHouseMapにマップする必要があるという事実を、主キーではない_user.name_を使用して変更できないことです。

Hibernateは、主キーとして使用する必要があるというエラーを表示し続けるか、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というエラーが表示されます

回避策として_@Formula_を試しましたが、うまくいきませんでした。 _@JoinColumnOrFormula_も試しましたが、どちらも機能しませんでした。 _@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;
_

_@JoinColumnOrFormula_ソリューションに対する私の試みでした。

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

これが私のマッピングです

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

DBスキーマは次のとおりです

ユーザー

_                               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
_

住宅

_                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
_

serHouseMap

_         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
_
27
user2158382

マッピングは次のようになります。

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

UserHouseの両方が、データベーススキーマと一致する、関連付けられたUserHouseMapエンティティにアクセスできます。

2つの1対多の関連付け を使用することは、多対多の関係に依存するよりも常に優れています。

25
Vlad Mihalcea