package org.example.demo.hibernate;

import java.io.Serializable;

import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Persistence;

import org.hibernate.annotations.NotFound;
import org.hibernate.annotations.NotFoundAction;

public class Test {
    public static void main(String[] args) throws Exception {
        EntityManagerFactory factory = Persistence.createEntityManagerFactory("test");
        EntityManager entityManager = factory.createEntityManager();

        City _NewYork = new City();
        _NewYork.setName("New York");

        Person person = new Person();
        person.setName("John Doe");
        person.setCityName("New York");

        entityManager.getTransaction().begin();
        entityManager.persist(_NewYork);
        entityManager.persist(person);
        entityManager.getTransaction().commit();

        entityManager.clear();

        Person p = entityManager.find(Person.class, person.id);
        // New York
        System.out.println(p.city.name);

        entityManager.close();
        factory.close();
    }

    @Entity(name = "Person")
    public static class Person {
        @Id
        @GeneratedValue
        private Long id;

        String name;
        String cityName;

        @ManyToOne(fetch = FetchType.LAZY)
        @NotFound(action = NotFoundAction.IGNORE)
        @JoinColumn(name = "cityName", referencedColumnName = "name", insertable = false, updatable = false)
        private City city;

        public void setName(String name) {
            this.name = name;
        }

        public void setCityName(String cityName) {
            this.cityName = cityName;
        }

        public void setCity(City city) {
            this.city = city;
        }
    }

    @Entity(name = "City")
    public static class City implements Serializable {
        @Id
        @GeneratedValue
        private Long id;

        String name;

        public void setName(String name) {
            this.name = name;
        }
    }
}

生成 SQL

drop table if exists City cascade
drop table if exists Person cascade
drop sequence if exists hibernate_sequence

create sequence hibernate_sequence start 1 increment 1
create table City (id int8 not null, name varchar(255), primary key (id))
create table Person (id int8 not null, cityName varchar(255), name varchar(255), primary key (id))
alter table City add constraint UK_b6tpfd3sd1ch530wfapd41nyq unique (name)
select nextval ('hibernate_sequence')
select nextval ('hibernate_sequence')
insert into City (name, id) values ('New York', 1)
insert into Person (cityName, name, id) values ('New York', 'John Doe', 2)

select test_perso0_.id as id1_1_0_, test_perso0_.cityName as cityName2_1_0_, test_perso0_.name as name3_1_0_ from Person test_perso0_ where test_perso0_.id=2
select test_city0_.id as id1_0_0_, test_city0_.name as name2_0_0_ from City test_city0_ where test_city0_.name='New York'

注意: City 必须 implements Serializable 。否则抛异常

Caused by: java.lang.ClassCastException: org.example.demo.hibernate.Test$City cannot be cast to java.io.Serializable
    at org.hibernate.type.ManyToOneType.hydrate(ManyToOneType.java:179)

这应该是因为自定义了 @JoinColumn 导致的。

如果将第 28 行改为 person.setCityName("Atlantis"); 则第 39 行 p.city 为 null

results matching ""

    No results matching ""