@org.hibernate.annotations.JoinColumnOrFormula 用于自定义外键 join
package org.example.demo.hibernate;
import java.io.Serializable;
import java.util.Objects;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Persistence;
import javax.persistence.Table;
import org.hibernate.annotations.JoinColumnOrFormula;
import org.hibernate.annotations.JoinFormula;
public class Test {
public static void main(String[] args) throws Exception {
EntityManagerFactory factory = Persistence.createEntityManagerFactory("test");
EntityManager em = factory.createEntityManager();
Country US = new Country();
US.setName("United States");
US.setDefault(true);
US.setPrimaryLanguage("English");
Country Romania = new Country();
Romania.setName("Romania");
Romania.setDefault(true);
Romania.setPrimaryLanguage("Romanian");
User user1 = new User();
user1.language = "English";
User user2 = new User();
user2.language = "Romanian";
em.getTransaction().begin();
em.persist(US);
em.persist(Romania);
em.persist(user1);
em.persist(user2);
em.getTransaction().commit();
em.clear();
User john = em.find(User.class, user1.id);
// United States
System.out.println(john.country.name);
User vlad = em.find(User.class, user2.id);
// Romania
System.out.println(vlad.country.name);
em.close();
factory.close();
}
@Entity(name = "User")
@Table(name = "users")
public static class User {
@Id
@GeneratedValue
private Long id;
String language;
@ManyToOne
@JoinColumnOrFormula(column = @JoinColumn(name = "language", referencedColumnName = "primaryLanguage", insertable = false, updatable = false))
@JoinColumnOrFormula(formula = @JoinFormula(value = "true", referencedColumnName = "is_default"))
private Country country;
}
@Entity(name = "Country")
@Table(name = "countries")
public static class Country implements Serializable {
@Id
@GeneratedValue
private Integer id;
private String name;
private String primaryLanguage;
@Column(name = "is_default")
private boolean _default;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPrimaryLanguage() {
return primaryLanguage;
}
public void setPrimaryLanguage(String primaryLanguage) {
this.primaryLanguage = primaryLanguage;
}
public boolean isDefault() {
return _default;
}
public void setDefault(boolean _default) {
this._default = _default;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof Country)) {
return false;
}
Country country = (Country) o;
return Objects.equals(getId(), country.getId());
}
@Override
public int hashCode() {
return Objects.hash(getId());
}
}
}
生成 SQL
drop table if exists countries cascade
drop table if exists users cascade
drop sequence if exists hibernate_sequence
create sequence hibernate_sequence start 1 increment 1
create table countries (id int4 not null, is_default boolean, name varchar(255), primaryLanguage varchar(255), primary key (id))
create table users (id int8 not null, language varchar(255), primary key (id))
alter table countries add constraint UK_r6ly3pxsnl696ws88l4yq3sbx unique (primaryLanguage, is_default)
select nextval ('hibernate_sequence')
select nextval ('hibernate_sequence')
select nextval ('hibernate_sequence')
select nextval ('hibernate_sequence')
insert into countries (is_default, name, primaryLanguage, id) values (true, 'United States', 'English', 1)
insert into countries (is_default, name, primaryLanguage, id) values (true, 'Romania', 'Romanian', 2)
insert into users (language, id) values ('English', 3)
insert into users (language, id) values ('Romanian', 4)
select test_user0_.id as id1_1_0_, test_user0_.language as language2_1_0_, true as formula1_0_, test_count1_.id as id1_0_1_, test_count1_.is_default as is_defau2_0_1_, test_count1_.name as name3_0_1_, test_count1_.primaryLanguage as primaryL4_0_1_ from users test_user0_ left outer join countries test_count1_ on test_user0_.language=test_count1_.primaryLanguage and true=test_count1_.is_default where test_user0_.id=3
select test_user0_.id as id1_1_0_, test_user0_.language as language2_1_0_, true as formula1_0_, test_count1_.id as id1_0_1_, test_count1_.is_default as is_defau2_0_1_, test_count1_.name as name3_0_1_, test_count1_.primaryLanguage as primaryL4_0_1_ from users test_user0_ left outer join countries test_count1_ on test_user0_.language=test_count1_.primaryLanguage and true=test_count1_.is_default where test_user0_.id=4
注意
- Country 必须 implements Serializable ,否则抛异常
- countries 表上自动建立一个 UK (primaryLanguage, is_default) 这好像不符合要求,因为 is_default = false, primaryLanguage = english 的国家有很多。