@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 的国家有很多。

results matching ""

    No results matching ""