如何使用 JPA 和 Hibernate 在非主键上连接表
Posted
技术标签:
【中文标题】如何使用 JPA 和 Hibernate 在非主键上连接表【英文标题】:How to join tables on non Primary Key using JPA and Hibernate 【发布时间】:2015-06-15 14:45:21 【问题描述】:我有 3 个模型 User
、House
、UserHouseMap
。我需要通过地图访问用户的房子。唯一的问题是这是一个旧数据库,我无法改变我需要使用非主键 user.name
将 User
映射到 UserHouseMap
的事实。
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;
这里是数据库架构
用户
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
用户住宅地图
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
【问题讨论】:
【参考方案1】:您的映射应该是这样的:
@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;
User
和 House
都可以访问与数据库架构匹配的关联 UserHouseMap
实体。
【讨论】:
我知道这很旧,但我遇到了同样的错误。您的解决方案有效,但是我必须稍作更改,但我必须添加 @Column(name = "name", nullable = false) private String name;如果我不得不猜测原因,我的变量/属性名称与数据库表中的列名称不同。仅供遇到相同/类似问题的其他人参考。 谢谢。我添加了nullable=false
和unique=true
,它们必须由任何标识符列强制执行。
如果 user_name 和 house_name 是非主键,这将不起作用!!以上是关于如何使用 JPA 和 Hibernate 在非主键上连接表的主要内容,如果未能解决你的问题,请参考以下文章