Как скопировать первичный ключ из основной таблицы в дочернюю таблицу в Hibernate - PullRequest
0 голосов
/ 31 января 2019

Как скопировать первичный ключ (Shared Key) из основной таблицы в дочернюю таблицу в Hibernate.Я пытаюсь сделать однонаправленное отображение (Employee имеет ссылку на Address, а не наоборот).

Дополнительная информация: Зависимость гибернации:

<dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-core</artifactId>
      <version>5.4.1.Final</version>
</dependency>

У меня есть Employee класс и Address сущности, как указано ниже.Я пытаюсь сгенерировать первичный ключ в сущности Employee для сущности Address.

Но, я вижу, employeeId в ADDRESS таблица всегда генерируется как 0 в спящем режиме (я ожидал, что это будет скопировано).Я думаю, я бы поступил неправильно при использовании @PrimaryKeyJoinColumn или @MapsId.Я попытался добавить оба или добавить один из них, но не повезло.

Ниже приведена схема соответствующих таблиц:

create table EMPLOYEE(
EMPLOYEE_ID int auto_increment,
NAME varchar(100),
SALARY double,
primary key(EMPLOYEE_ID)
);



create table ADDRESS
(
EMPLOYEE_ID int references EMPLOYEE.EMPLOYEE_ID,
STREET_NAME varchar(40),
CITY_NAME varchar(40),
STATE_NAME varchar(40),
ZIP_CODE varchar(40),
primary key(EMPLOYEE_ID)
);

Отображение сущности выглядит следующим образом:

Employee.java

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.MapsId;
import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;
import java.io.Serializable;

@Entity
@Table(name = "EMPLOYEE")
public class Employee implements Serializable {

    @Id
    @Column(name = "EMPLOYEE_ID")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    @Column(name = "NAME")
    private String name;

    @Column(name = "SALARY")
    private double salary;

    @OneToOne
    @JoinColumn(name="EMPLOYEE_ID")
   @MapsId
    //@PrimaryKeyJoinColumn
    private Address address;

    public int getId() {
        return id;
    }

    public Employee setId(int id) {
        this.id = id;
        return this;
    }

    public String getName() {
        return name;
    }

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

    public double getSalary() {
        return salary;
    }

    public Employee setSalary(double salary) {
        this.salary = salary;
        return this;
    }

    public Address getAddress() {
        return address;
    }

    public Employee setAddress(Address address) {
        this.address = address;
        return this;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", salary=" + salary +
                ", address=" + address +
                '}';
    }
}

Address.java

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MapsId;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;
import java.io.Serializable;

@Entity
@Table(name = "ADDRESS")
public class Address implements Serializable {

    @Id
    @Column(name = "EMPLOYEE_ID")
    private int id;

    @Column(name = "STREET_NAME")
    private String streetName;

    @Column(name = "CITY_NAME")
    private String cityName;

    @Column(name = "STATE_NAME")
    private String stateName;

    @Column(name = "ZIP_CODE")
    private String zipCode;

    public int getId() {
        return id;
    }

    public Address setId(int id) {
        this.id = id;
        return this;
    }

    public String getStreetName() {
        return streetName;
    }

    public Address setStreetName(String streetName) {
        this.streetName = streetName;
        return this;
    }

    public String getCityName() {
        return cityName;
    }

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

    public String getStateName() {
        return stateName;
    }

    public Address setStateName(String stateName) {
        this.stateName = stateName;
        return this;
    }

    public String getZipCode() {
        return zipCode;
    }

    public Address setZipCode(String zipCode) {
        this.zipCode = zipCode;
        return this;
    }

    @Override
    public String toString() {
        return "Address{" +
                "id=" + id +
                ", streetName='" + streetName + '\'' +
                ", cityName='" + cityName + '\'' +
                ", stateName='" + stateName + '\'' +
                ", zipCode='" + zipCode + '\'' +
                '}';
    }
}

Метод сохранения:

  public Employee save(Employee employee){

        Session session = HibernateUtil.buildSessionFactory().openSession();
        Transaction transaction = session.beginTransaction();
        session.save(address); // Should I do this?            
        session.save(employee);
        transaction.commit();
        return employee;
    }

Ответы [ 3 ]

0 голосов
/ 31 января 2019

Вам необходимо смоделировать связь для объекта, который копирует значение первичного ключа.Если вы сделаете это, вы можете аннотировать ассоциацию с помощью @MapsId.

. В вашем примере первичный ключ сущности Employee создается с использованием стратегии IDENTITY и Address субъект должен использовать то же значение.Чтобы это работало, вам нужно смоделировать однозначную ассоциацию на сущности Address.Вы можете использовать либо двунаправленное, либо однонаправленное сопоставление связей.

Если вы предпочитаете однонаправленную, вы можете использовать те же аннотации сопоставления, что и для атрибута address вашей сущности Employee.После этого вам, конечно, потребуется удалить атрибут address;)

В двунаправленном отображении ваша сущность Employee будет выглядеть следующим образом:

@Entity
@Table(name = "EMPLOYEE")
public class Employee implements Serializable {

    @Id
    @Column(name = "EMPLOYEE_ID")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    @Column(name = "NAME")
    private String name;

    @Column(name = "SALARY")
    private double salary;

    @OneToOne
    @JoinColumn(name="EMPLOYEE_ID")
    private Address address;

    public int getId() {
        return id;
    }

    public Employee setId(int id) {
        this.id = id;
        return this;
    }

    public String getName() {
        return name;
    }

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

    public double getSalary() {
        return salary;
    }

    public Employee setSalary(double salary) {
        this.salary = salary;
        return this;
    }

    public Address getAddress() {
        return address;
    }

    public Employee setAddress(Address address) {
        this.address = address;
        return this;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", salary=" + salary +
                ", address=" + address +
                '}';
    }
}

И этоэто Address сущность.Важной частью этого сопоставления является аннотация @MapsId для однозначной ассоциации.

@Entity
@Table(name = "ADDRESS")
public class Address implements Serializable {

    @Id
    @Column(name = "EMPLOYEE_ID")
    private int id;

    @Column(name = "STREET_NAME")
    private String streetName;

    @Column(name = "CITY_NAME")
    private String cityName;

    @Column(name = "STATE_NAME")
    private String stateName;

    @Column(name = "ZIP_CODE")
    private String zipCode;

    @OneToOne(mappedBy="address")
    @MapsId
    private Employee employee

    public int getId() {
        return id;
    }

    public Address setId(int id) {
        this.id = id;
        return this;
    }

    public String getStreetName() {
        return streetName;
    }

    public Address setStreetName(String streetName) {
        this.streetName = streetName;
        return this;
    }

    public String getCityName() {
        return cityName;
    }

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

    public String getStateName() {
        return stateName;
    }

    public Address setStateName(String stateName) {
        this.stateName = stateName;
        return this;
    }

    public String getZipCode() {
        return zipCode;
    }

    public Address setZipCode(String zipCode) {
        this.zipCode = zipCode;
        return this;
    }

    public Employee getEmployee() {
        return employee;
    }

    public void setEmployee(Employee emp) {
        this.employee = emp;
    }

    @Override
    public String toString() {
        return "Address{" +
                "id=" + id +
                ", streetName='" + streetName + '\'' +
                ", cityName='" + cityName + '\'' +
                ", stateName='" + stateName + '\'' +
                ", zipCode='" + zipCode + '\'' +
                '}';
    }
}

Как видите, я удалил аннотацию @PrimaryKeyJoinColumn.Он используется только в том случае, если ваша сущность сопоставлена ​​с 2 таблицами базы данных.Это может иметь место, если вы используете стратегию наследования JOINED или если вы работаете с устаревшей базой данных и вам необходимо сопоставить 2 таблицы с одним и тем же объектом .

0 голосов
/ 08 февраля 2019

Я сопоставил объекты, как показано ниже:

Посмотрите на код ниже Employee.java

 @OneToOne(fetch = FetchType.LAZY)
   @PrimaryKeyJoinColumn
    private Address address;

Employee.java

@Entity
@Table(name = "EMPLOYEE")
public class Employee implements Serializable {

    public Employee(){

    }
    public Employee(String name){
        this.name = name;
    }

    public Employee(String name,double salary){
        this.name = name;
        this.salary = salary;
    }

    @Id
    @Column(name = "EMPLOYEE_ID")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    @Column(name = "NAME")
    private String name;

    @Column(name = "SALARY")
    private double salary;

    @OneToOne(fetch = FetchType.LAZY)
   @PrimaryKeyJoinColumn
    private Address address;

    public int getId() {
        return id;
    }

    public Employee setId(int id) {
        this.id = id;
        return this;
    }

    public String getName() {
        return name;
    }

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

    public double getSalary() {
        return salary;
    }

    public Employee setSalary(double salary) {
        this.salary = salary;
        return this;
    }

    public Address getAddress() {
        return address;
    }

    public Employee setAddress(Address address) {
        this.address = address;
        return this;
    }

    @Override
    public String toString() {
        return "BiEmployee{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", salary=" + salary +
                ", address=" + address +
                '}';
    }
}

Address.java

@Entity
@Table(name = "ADDRESS")
public class Address implements Serializable {

    @Id
    @Column(name = "EMPLOYEE_ID")
    private int id;

    @Column(name = "STREET_NAME")
    private String streetName;

    @Column(name = "CITY_NAME")
    private String cityName;

    @Column(name = "STATE_NAME")
    private String stateName;

    @Column(name = "ZIP_CODE")
    private String zipCode;

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "COUNTRY_CODE")
    private Country country;

    public int getId() {
        return id;
    }

    public Address setId(int id) {
        this.id = id;
        return this;
    }

    public String getStreetName() {
        return streetName;
    }

    public Address setStreetName(String streetName) {
        this.streetName = streetName;
        return this;
    }

    public String getCityName() {
        return cityName;
    }

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

    public String getStateName() {
        return stateName;
    }

    public Address setStateName(String stateName) {
        this.stateName = stateName;
        return this;
    }

    public String getZipCode() {
        return zipCode;
    }

    public Address setZipCode(String zipCode) {
        this.zipCode = zipCode;
        return this;
    }

    public Country getCountry() {
        return country;
    }

    public Address setCountry(Country country) {
        this.country = country;
        return this;
    }

    @Override
    public String toString() {
        return "BiAddress{" +
                "id=" + id +
                ", streetName='" + streetName + '\'' +
                ", cityName='" + cityName + '\'' +
                ", stateName='" + stateName + '\'' +
                ", zipCode='" + zipCode + '\'' +
                '}';
    }
}

Добавление Country.java для полноты

@Entity
@Table(name = "COUNTRY")
public class Country {

    @Id
    @Column(name = "COUNTRY_CODE")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int countryCode;

    @Column(name = "COUNTRY_NAME")
    private String name;

    public int getCountryCode() {
        return countryCode;
    }

    public Country setCountryCode(int countryCode) {
        this.countryCode = countryCode;
        return this;
    }

    public String getName() {
        return name;
    }

    public Country setName(String name) {
        this.name = name;
        return this;
    }
}
0 голосов
/ 31 января 2019

Я думаю, вам не нужно копировать первичный ключ вручную.Если вы используете ORM, такой как hibernate, вам нужно фактически передать объект сущности (в вашем случае объект сущности Address) объекту класса (в вашем случае Employee), для которого вы хотите создать отображение 1-1.Hibernate автоматически использует первичный ключ сущностей (первичный ключ адресов), чтобы заполнить столбец (столбец адреса в таблице Employee) в сущности сопоставления.Вы можете посмотреть этот пример здесь, который очень похож на ваш случай: https://dzone.com/tutorials/java/hibernate/hibernate-example/hibernate-mapping-one-to-one-using-annotations-1.html

Здесь, если вы видите, у них есть первичный ключ для таблицы адресов, который является addressId.Теперь в классе учеников у них есть поле типа Address, которое помечено как @OneToOne, что означает его отображение.Теперь в конструктор студенческого класса мы передаем объект адреса.Теперь, в главной функции, если вы видите, мы сохраняем только объект студента (не объект адреса).Теперь, когда транзакция сохранена, hibernate будет знать, сначала создать объект адреса, потому что от него зависит объект студента, а затем сохранить объект студента с первичным ключом созданного объекта адреса.

Теперь, когда вы извлекаете сущность студента, hibernate автоматически извлечет сущность Address, также смотря на addressId в таблице ученика.Надеюсь, поможет.Дайте мне знать, если понадобятся дополнительные разъяснения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...