java - 尝试了解 @JoinTable 和 @JoinColumn 的工作原理

标签 java hibernate join

我正在学习 hibernate 并遇到了以下问题

有两个表

CREATE TABLE department (
 department_id int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
 caption varchar(255) DEFAULT NULL) ENGINE=InnoDB;
CREATE TABLE employee (
 employee_id int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
 fio varchar(255) DEFAULT NULL,
 fk_department_id int(11) NOT NULL,
 FOREIGN KEY (fk_department_id) REFERENCES department (department_id) 
) ENGINE=InnoDB ;

和两个类(在第一个类中注释掉的代码看起来像工作解决方案)

@Entity
@Table(name = "department")
public class Department {
....
    @OneToMany(cascade = CascadeType.ALL)
    @JoinTable(name = "employee", joinColumns = {
            @JoinColumn(name = "fk_department_id", referencedColumnName = "department_id") })
    /*
     * @OneToMany(fetch = FetchType.LAZY, mappedBy = "department", cascade =
     * CascadeType.ALL)
     */
    public Set<Employee> getEmployies() {
        return employees;
    }
<小时/>
@Entity
@Table(name = "employee")
public class Employee {
......
    @ManyToOne
    @JoinColumn(name = "fk_department_id")
    public Department getDepartment() {
        return department;
    }

这会导致

INFO: HHH000423: Disabling contextual LOB creation as JDBC driver reported JDBC version [3] less than 4
Exception in thread "main" org.hibernate.MappingException: Foreign key (FK3cspe1b06hmsik5l8y1i11xmd:employee [employies_employee_id])) must have same number of columns as the referenced primary key (employee [fk_department_id,employies_employee_id])
    at org.hibernate.mapping.ForeignKey.alignColumns(ForeignKey.java:148)
    at org.hibernate.mapping.ForeignKey.alignColumns(ForeignKey.java:130)

请帮助我理解为什么这不起作用

最佳答案

以下内容应该可以正常工作。您会注意到我没有指定任何连接列关系,因为我允许 Hibernate 自动为我生成这些关系。

@Entity
public class Department {
  @OneToMany
  @JoinTable(name = "department_employees")
  private List<Employee> employees;
}

@Entity
public class Employee {
  @ManyToOne
  private Department department;
}

但是假设您想要明确连接列。

@Entity
public class Department {
  @Id
  @Column(name = "department_id")
  private Integer id;
  @OneToMany
  @JoinTable(
     name = "department_employees",
     joinColumns = @JoinColumn(name = "department_id"),
     inverseJoinColumns = @JoinColumn(name = "employee_id"))
  private List<Employee> employees;
}

@Entity
public class Employee {
  @Id
  @Column(name = "employee_id")
  private Integer id;
  @ManyToOne
  @JoinTable(
     name = "department_employees",
     joinColumns = @JoinColumn(name = "department_id", insertable = false, updatable = false),
     inverseJoinColumns = @JoinColumn(name = "employee_id", insertable = false, updatable = false))
  private Department department;
}

从中得出的要点是:

  • 连接表的名称指定维护 Department 之间关系的中间表。和Employee实体。它不应该指Employee表如您的代码所示。
  • joinColumns attribute 表示包含实体的主键属性,在本例中为 Department ,因此我使用 department_id .
  • inverseColumns attribute 表示关联实体的主键属性,在本例中为 Employee ,因此我使用 employee_id .

更新:

如果您想消除 @JoinTable并仅维持 Department 之间的关系和Employee ,您可以按如下方式更改映射:

@Entity
public class Department {
  @OneToMany(mappedBy = "department")
  private List<Employee> employees;
}

@Entity
public class Employee {
  @ManyToOne
  private Department department;
}

希望有帮助。

关于java - 尝试了解 @JoinTable 和 @JoinColumn 的工作原理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39040029/

相关文章:

c# - 映射JoinedSubclassMapping

mysql - 连接多个表中的列

对象的Java空检查

java - 当使用 HBase 作为 MapReduce 的源时,我可以扩展 TableInputFormatBase 来为每个区域创建多个拆分和多个映射器吗?

java - 获取文件路径 - Hibernate SessionFactory

mysql - 按时间顺序对连接中的数据进行排序以获得最新条目

sql - 将多个 SQL 字段显示为单个字段

Java - 如何仅读取输入流的某些部分

java - 查找异常类型

java - 修改 Oracle Sql 查询返回的结果内容