【问题标题】:JPA Entity mapping for join columns连接列的 JPA 实体映射
【发布时间】:2019-10-28 00:53:24
【问题描述】:

我有三个表 EmployeeDepartment、EmployeeGroup 和 EmpplyeeDetails 表。 EmployeeDepartment 表有主键departmentId 和一列groupId,EmployeeGroupTable 有主键groupid,它应该从数据库序列GroupIdGenerator 中生成。 EmployeeDetails 有两个主键,即 groupid 和employeeid。 Groupid 应与上表相同 所有表中的这些值都应插入到一个事务中。 你能帮我正确的 JAP 实体映射吗?

我已经尝试过使用不同的生成值和序列生成器组合,但无法将数据保存到表中。

  @Entity
   @Table(name="EMPLOYEE_DEPARTMENT")
   public class EmployeeDepartment {

   @Column(name = "DEPARTMENT_ID")
   @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = 
      "departmentid-gen")
   @Id
   @NotNull
   @SequenceGenerator(name = "departmentid-gen", sequenceName = 
     "DEAPARTMENT_ID_GENERATOR" )
   private  long departmentId;

   @OneToOne(mappedBy = "employeeGroup")
      private EmployeeGroup employeeGroup;
      }
  @Coulmn(name="GROUP_ID") 
  private long groupId;




   @Entity
   @Table(name="EMPLOYEE_GROUP")
   public class EmployeeGroup {

   @Column(name = "GROUP_ID")
   @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = 
      "groupid-gen")
   @Id
   @NotNull
   @SequenceGenerator(name = "groupid-gen", sequenceName = 
     "GROUIP_ID_GENERATOR" )
   private  long groupId;

   @OneToMany(mappedBy = "employeeDetail")
      private List<EmployeeDetail> employeeDetails;

  @OneToOne
  @JoinColumn(name = "DEPARTMENT_ID", insertable=false , 
        updatable=false)
      private EmployeeDepartment employeeDepatment;
      }



@Entity
   @Table(name = "EMPLOYEE_DETAIL")
   @IdClass(EmployeeID.class)
   public class EmployeeDetail {

  @ManyToOne
  @JoinColumn(name = "GROUP_ID", insertable=false , updatable=false)
  private EmployeeGroup employeeGroup;

  @Id
  @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = 
     "groupid-gen")
  @SequenceGenerator(name = "groupid-gen", sequenceName = 
    "GROUIP_ID_GENERATOR" )
  @Column(name = "GROUP_ID")
  @Nonnull
     private Long groupId;

  @Id
  @Nonnull
  @Column(name = "EMPLOYEE_ID")
    private Long employeeId;

}

public class EmployeeId{

private Long groupId;

private Long employeeId;

public EmployeeId(final Long groupId, final Long employeeId) {
    this.groupId = groupId;
    this.employeeId = employeeId;
}

public EmployeeId() {
}

}

这 3 个表中的预期结果应该具有适当的值,例如。

表员工部门

DepartmentID   GroupId
   1               1

表员工组

 GroupID  
   1

表 EmployeeDetail

GroupId       EmployeeId
  1            1
  1            2
  1            3

实际结果如下

表员工部门

DepartmentID   GroupId
   1               0

表员工组

 GroupID  
   1

表 EmployeeDetail

GroupId       EmployeeId
  2            1
  3            2
  4            3

【问题讨论】:

  • 为什么员工有一个复合主键而不是一个序列,然后是一个外键来分组?
  • 实际上它是一个遗留域模型,由于某种原因我们无法更改它。这导致更新我的问题陈述。因此,只需将它们视为复合键而不是外键。
  • 但是 groupId 是一个外键并且你配置了一个序列生成器。怎么样?
  • 你的意思是在EmployeeDetail中说对吧?如果我不使用它,我会在保存到 EmployeeDetail 时得到一个异常,例如 groupId 的 value cannot ne null。
  • 是的,因为如果你想添加员工,你必须分配一个组

标签: jpa spring-data-jpa jpa-2.0 openjpa


【解决方案1】:

重要的注解是@MapsId("groupId")

你的映射应该是这样的:

   @Entity
   @Table(name="EMPLOYEE_DEPARTMENT")
   public class EmployeeDepartment {

   @Column(name = "DEPARTMENT_ID")
   @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = 
      "departmentid-gen")
   @Id
   @NotNull
   @SequenceGenerator(name = "departmentid-gen", sequenceName = 
     "DEAPARTMENT_ID_GENERATOR" )
   private  long departmentId;

   @OneToOne(mappedBy = "employeeGroup")
   private EmployeeGroup employeeGroup;

   @Column(name="GROUP_ID") 
   private long groupId;


   @Entity
   @Table(name="EMPLOYEE_GROUP")
   public class EmployeeGroup {

   @Column(name = "GROUP_ID")
   @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = 
      "groupid-gen")
   @Id
   @NotNull
   @SequenceGenerator(name = "groupid-gen", sequenceName = 
     "GROUIP_ID_GENERATOR" )
   private  long groupId;

   @OneToMany(mappedBy = "employeeDetail")
   private List<EmployeeDetail> employeeDetails;

   @OneToOne
   @JoinColumn(name = "DEPARTMENT_ID", insertable=false, updatable=false)
   private EmployeeDepartment employeeDepatment;


   @Entity
   @Table(name = "EMPLOYEE_DETAIL")
   @IdClass(EmployeeID.class)
   public class EmployeeDetail {

   @MapsId("groupId")
   @ManyToOne
   @JoinColumn(name = "GROUP_ID", insertable=false , updatable=false)
   private EmployeeGroup employeeGroup;

   @Id
   @Nonnull
   @Column(name = "EMPLOYEE_ID")
   private Long employeeId;

【讨论】:

  • MapsId 我已经尝试过,并且在尝试修复此问题时收到了类似的异常。像 grouId 不能为空。
  • ERROR o.h.e.jdbc.spi.SqlExceptionHelper - NULL 不允许用于列“GROUP_ID”; SQL 语句:插入 EMPLOYEE_DEPARTMENT(GROUP_ID,DEPARTMENT_ID,HEADER_ENG,HEADER_GE,DEP_NAME,DEP_ADDRESS)值(?,?,?,?,?,?) [23502-197] 16:22:17.396 [https-jsse-nio- auto-1-exec-6] 错误 ohiExceptionMapperStandardImpl - HHH000346:托管刷新期间出错 [org.hibernate.exception.ConstraintViolationException:无法执行语句] org.springframework.dao.DataIntegrityViolationException:无法执行语句; SQL [不适用];约束[空];嵌套异常是
  • 但是您向员工添加了一个组?您无法保存没有组分配的员工
  • 是的,因为如果您看到 EmployeeId 类,它同时具有 groupId 和 departmentId,所以如果我们不向员工添加组,那么它会在构建过程中失败,说没有在 EmployeeDetail 类中定义 groupId。我同意你的观点,没有团队员工的详细信息将不会被保存。但这不适用于您建议的映射。或者我不知道我做错了什么。
【解决方案2】:
 @Entity
   @Table(name="EMPLOYEE_DEPARTMENT")
   public class EmployeeDepartment {

   @Column(name = "DEPARTMENT_ID")
   @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = 
      "departmentid-gen")
   @Id
   @NotNull
   @SequenceGenerator(name = "departmentid-gen", sequenceName = 
     "DEAPARTMENT_ID_GENERATOR" )
   private  Long departmentId;

   @OneToOne(mappedBy = "employeeGroup")
      private EmployeeGroup employeeGroup;
      }
  @Column(name="GROUP_ID") 
  private EmployeeGroup group;




   @Entity
   @Table(name="EMPLOYEE_GROUP")
   public class EmployeeGroup {

   @Column(name = "GROUP_ID")
   @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = 
      "groupid-gen")
   @Id
   @NotNull
   @SequenceGenerator(name = "groupid-gen", sequenceName = 
     "GROUIP_ID_GENERATOR" )
   private  Long groupId;

   @OneToMany(mappedBy = "employeeDetail")
      private List<EmployeeDetail> employeeDetails;

  @OneToOne
  @JoinColumn(name = "DEPARTMENT_ID", insertable=false , 
        updatable=false)
      private EmployeeDepartment employeeDepatment;
      }



@Entity
   @Table(name = "EMPLOYEE_DETAIL")
   @IdClass(EmployeeID.class)
   public class EmployeeDetail {

  @Id
  @ManyToOne
  @JoinColumn(name = "GROUP_ID", insertable=false , updatable=false)
  private EmployeeGroup employeeGroup;

  @Id
  @Nonnull
  @Column(name = "EMPLOYEE_ID")
    private Long employeeId;

您还需要相应地更改 EmployeeId:

public class EmployeeId{

private EmployeeGroup employeeGroup;

private Long employeeId;

public EmployeeId(final EmployeeGroup employeeGroup, final Long employeeId) {
    this.employeeGroup= employeeGroup;
    this.employeeId = employeeId;
}

但是,我以前没有以这种方式使用复合键。如果不起作用,则将 EmployeeId 更改为 EmbeddedId:

@Embeddable
public class EmployeeId implements Serializable{

@ManyToOne(fetch = FetchType.LAZY, optional = false)
private EmployeeGroup employeeGroup;

@Nonnull
@Column(name = "EMPLOYEE_ID")
private Long employeeId;

public EmployeeId(final EmployeeGroup employeeGroup, final Long employeeId) {
    this.employeeGroup= employeeGroup;
    this.employeeId = employeeId;
}


@Entity
@Table(name = "EMPLOYEE_DETAIL")
public class EmployeeDetail {

  @EmbeddedId
  private EmployeeId id;

  @ManyToOne
  @JoinColumn(name = "GROUP_ID", insertable=false , updatable=false)
  private EmployeeGroup employeeGroup;

}

如果还是不行,请在你创建实体的地方附上代码sn-p。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-07-13
    • 1970-01-01
    • 1970-01-01
    • 2021-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-29
    相关资源
    最近更新 更多