具有外键和生成的库伦的复合ID,无法保存

时间:2018-12-11 11:38:32

标签: java hibernate jpa

我正在尝试找出一种方法来管理包含自动生成的值和外键的表上的复合ID。 但是,永远无法使用@IdClass@EmbeddedId。 在这两种情况下,当我尝试在数据库中插入实体时都会出现异常。

我做了sample project来展示我的问题。该项目基于Hibernate test case templates

公共部分:

应将所有Agent链接到的Mission实体。

@Getter
@Setter
@Entity
public class Agent implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    private String login;

    private String lastName;
    private String firstName;
}

@IdClass情况:

@IdClass ID

@Data
@NoArgsConstructor
@AllArgsConstructor
public class IdClassTypeMissionId implements Serializable {
    private static final long serialVersionUID = 1L;
    private Long id;
    private String agent;
}

Mission实体,使用@IdClass批注:

@Getter
@Setter
@Entity
@IdClass(IdClassTypeMissionId.class)
public class IdClassTypeMission implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Id
    @ManyToOne(optional = false)
    @JoinColumn(name = "agent_login", referencedColumnName = "login", foreignKey = @ForeignKey(name = "fk_id_class_type_mission_agent"))
    private Agent agent;

    private LocalDateTime dateEnd;
    private LocalDateTime dateStart;
    private String city;
}

测试用例

@Test
public void idClassTypeMissionTest() throws Exception {
    EntityManager entityManager = entityManagerFactory.createEntityManager();
    entityManager.getTransaction().begin();

    final Agent agent = new Agent();
    agent.setLogin("jdoe");
    agent.setFirstName("John");
    agent.setLastName("Doe");

    entityManager.persist(agent);
    entityManager.flush();
    entityManager.refresh(agent);

    final IdClassTypeMission mission = new IdClassTypeMission();
    mission.setCity("New York");
    mission.setDateStart(LocalDateTime.of(2018, 12, 5, 7, 30));
    mission.setDateEnd(LocalDateTime.of(2018, 12, 6, 18, 30));
    mission.setAgent(agent);

    entityManager.persist(mission); // <- It fails here.
    entityManager.flush();
    entityManager.refresh(mission);

    final IdClassTypeMission result = entityManager.find(IdClassTypeMission.class, new IdClassTypeMissionId(mission.getId(), "jdoe"));
    assertNotNull(result);
    assertNotNull(result.getId());
    assertNotNull(result.getAgent());
    assertEquals("jdoe", result.getAgent().getLogin());
    assertEquals("New York", result.getCity());

    entityManager.getTransaction().commit();
    entityManager.close();
}

我收到以下异常:

Caused by: org.hibernate.HibernateException: No part of a composite identifier may be null

@EmbeddedId情况:

@Embedded部分:

@Data
@Embeddable
@NoArgsConstructor
@AllArgsConstructor
public class EmbeddedTypeMissionId implements Serializable {
    private static final long serialVersionUID = 1L;

    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String agentLogin;
}

Mission实体:

@Getter
@Setter
@Entity
public class EmbeddedTypeMission implements Serializable {
    private static final long serialVersionUID = 1L;

    @EmbeddedId
    private EmbeddedTypeMissionId id;

    @MapsId("agentLogin")
    @ManyToOne(optional = false)
    @JoinColumn(name = "agent_login", referencedColumnName = "login", foreignKey = @ForeignKey(name = "fk_embedded_type_mission_agent"))
    private Agent agent;

    private LocalDateTime dateEnd;
    private LocalDateTime dateStart;
    private String city;
}

测试用例

@Test
public void embeddedIdTypeMissionTest() throws Exception {
    final EntityManager entityManager = entityManagerFactory.createEntityManager();
    entityManager.getTransaction().begin();

    final Agent agent = new Agent();
    agent.setLogin("jdoe");
    agent.setFirstName("John");
    agent.setLastName("Doe");

    entityManager.persist(agent);
    entityManager.flush();
    entityManager.refresh(agent);

    final EmbeddedTypeMission mission = new EmbeddedTypeMission();
    mission.setCity("New York");
    mission.setDateStart(LocalDateTime.of(2018, 12, 5, 7, 30));
    mission.setDateEnd(LocalDateTime.of(2018, 12, 6, 18, 30));
    mission.setAgent(agent);

    entityManager.persist(mission);
    entityManager.flush(); // <- It fails here.
    entityManager.refresh(mission);

    final EmbeddedTypeMission result = entityManager.find(EmbeddedTypeMission.class, new EmbeddedTypeMissionId(mission.getId().getId(), "jdoe"));
    assertNotNull(result);
    assertNotNull(result.getId());
    assertNotNull(result.getId().getId());
    assertEquals("jdoe", result.getId().getAgent());
    assertEquals("New York", result.getCity());

    entityManager.getTransaction().commit();
    entityManager.close();
}

我收到以下异常:

Caused by: org.h2.jdbc.JdbcSQLException: NULL not allowed for column "ID"; SQL statement:
insert into EmbeddedTypeMission (city, dateEnd, dateStart, agent_login, id) values (?, ?, ?, ?, ?) [23502-176]

分析

使用@IdClass案例,我找到了一个bug ticket on Hibernate。为什么要尝试使用@EmbeddedId

起初,我认为这是可行的:使用save中的@Repository方法保存实体似乎可行。但是,当尝试使用EntityManager插入实体时,它失败了……

我错过了什么吗? 我的测试有问题吗? 有什么建议可以使其正常工作吗?

0 个答案:

没有答案