我正在尝试找出一种方法来管理包含自动生成的值和外键的表上的复合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
插入实体时,它失败了……
我错过了什么吗? 我的测试有问题吗? 有什么建议可以使其正常工作吗?