Составной идентификатор с внешним ключом и сгенерированным столбцом, не удается сохранить - PullRequest
0 голосов
/ 11 декабря 2018

Я пытаюсь найти способ управления составным идентификатором таблицы, которая содержит автоматически сгенерированное значение и внешний ключ.Но использование @IdClass или @EmbeddedId не работает.В обоих случаях у меня есть исключение при попытке вставить объект в базу данных.

Я создал пример проекта , чтобы продемонстрировать свою проблему.Этот проект основан на шаблонах тестовых примеров Hibernate .

Общая часть:

Сущность 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 case:

ID для объекта @IdClass:

@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 case:

Часть @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 мне удалось найти билет с ошибкой в Hibernate .Вот почему я пытался использовать @EmbeddedId.

Сначала я подумал, что это работает: сохранение объекта с использованием метода save из @Repository, похоже, работает.Но при попытке вставить сущность с помощью EntityManager не получилось ...

Я что-то пропустил?Это проблема в моих тестах?Любое предложение, чтобы заставить его работать?

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