2016-01-15 4 views
0

Прежде чем описать проблему, позвольте мне объяснить, что я использую Playframework 2.4.4 с Hibernate 5.0.5 и используя чистые методы JPA, т.е. , У меня нет доступа к методам «saveOrUpdate» Hibernate, но они должны использовать либо слияние, либо сохранение. Кроме того, в соответствии с последней рекомендацией playframework (когда не используется ebean) мой класс Model не расширяет класс play.db.ebean.Model.Playframework: функция слияния EntityManager JPA не работает - не использует значения переменных члена субъекта

Проблема:

Мой призыв к EntityManager.merge терпит неудачу с исключением «NULL не допускаются для столбца», хотя связанный с переменной-члена в экземпляре объекта действительно заполнен!

Детали:

  1. Класс; три поля, два из которых образуют составной первичный ключ.
  2. Существует новый экземпляр этого класса, заполненный привязкой формы Play. Я проверил содержимое экземпляра и действительно содержит значения для столбца проблемы.
  3. Стол пуст.
  4. Хотя значения заполнены, значения не поступают в инструкцию SQL, и поскольку задействован первичный ключ, этот результат, конечно, возникает в исключении [error] - org.hibernate.engine.jdbc.spi. SqlExceptionHelper - NULL не разрешено для столбца «IDTYPECODE»; SQL заявление:

Вопрос:

Тем не менее, мой объект полностью заполнен. Так почему это произошло? Согласно всем, что я прочитал, функция слияния должна успешно вставить новую несогласованную запись в этом случае! Что я сделал не так? Persist WILL работает в этом случае, но на самом деле, в моей конкретной ситуации я не могу узнать, сохранились ли эти объекты в базе данных или нет. Хотелось бы избежать поиска, чтобы проверить это существование! По моему мнению, это должно быть возможно!

Дальнейшие подробности:

Вот определение класса

@Entity 
public class IdType implements Serializable 
{ 
    /** 
    * User specified Unique identifier. 
    * Both idTypeCode and idCategory are together 
    * a compound key, so as to ensure that the 
    * combination of the both can not occur more 
    * than once in the table. 
    */ 
    @Id 
    public String idTypeCode; 
    @Id 
    public IdCategory idCategory; 

    public String idTypeName; 
} 

Мой контроллер очень прост;

@Transactional 
public Result updateIds() 
{ 
    IdType idType = Form.form(IdType.class).bindFromRequest().get(); 

    System.out.println("idTypeCode is: "+idType.idTypeCode); 

    EntityManager em = entityManager(); 
    em.merge(idType); 

    return redirect(routes.Application.index()); 
} 

Выход консоли от попытки сохранить этот объект таким образом, заключается в следующем:

idTypeCode is: national_number 
[error] - org.hibernate.engine.jdbc.spi.SqlExceptionHelper - NULL not allowed for column "IDTYPECODE"; SQL statement: 
insert into IdType (idTypeName, idTypeCode, idCategory) values (?, ?, ?) [23502-187] 
[error] - play.core.server.netty.PlayDefaultUpstreamHandler - Cannot invoke the action 
javax.persistence.RollbackException: Error while committing the transaction 
    at org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:86) ~[hibernate-entitymanager-5.0.5.Final.jar:5.0.5.Final] 
    at play.db.jpa.DefaultJPAApi.withTransaction(DefaultJPAApi.java:142) ~[play-java-jpa_2.11-2.4.4.jar:2.4.4] 
    at play.db.jpa.JPA.withTransaction(JPA.java:159) ~[play-java-jpa_2.11-2.4.4.jar:2.4.4] 
    at play.db.jpa.TransactionalAction.call(TransactionalAction.java:16) ~[play-java-jpa_2.11-2.4.4.jar:2.4.4] 
    at play.core.j.JavaAction$$anonfun$7.apply(JavaAction.scala:94) ~[play_2.11-2.4.4.jar:2.4.4] 

Как вы можете видеть, SQL заявление, работающий в данном случае это именно то, что я хотел бы надеяться, ибо, учитывая, что объект не существует:

insert into IdType (idTypeName, idTypeCode, idCategory) values (?, ?, ?) [23502-187] 

Тем не менее, по какой-то причине, хотя я знаю, что есть значение «idTypeName» в моем объекте, он говорит мне, что:

[error] - org.hibernate.engine.jdbc.spi.SqlExceptionHelper - NULL not allowed for column "IDTYPECODE"; SQL statement: 

Так почему же оно игнорирует мою явно заполненную стоимость?

Я читал в другом месте, что слияние должно работать; то есть, если объект существует в базе данных, он будет выполнять обновление, если нет, вставку. Является ли это странное поведение результатом Playframework, изменяющего нормальное поведение библиотеки JPA (в этом случае я использую Hibernate).

Любые идеи?

ОБНОВЛЕНИЕ !!!!!

ОК, наконец, настало время посмотреть дальше в этом. Кажется, это не имеет никакого отношения к игре. Я протестировал сейчас тот же самый сценарий с прямым консольным приложением JPA/Hibernate. У меня такая же проблема. Проблема возникает, как только у меня есть составной ключ (как в данном примере). Как только я удалю один из столбцов в качестве ключа, слияние будет работать. Теперь я исследую, почему это так, и как избежать проблемы (при этом мне нужна модель). Я обновлю эту проблему, как только у меня появится дополнительная информация.

ответ

0

OK. Поэтому я, наконец, решил. Похоже, я неправильно создал свой составной/составной первичный ключ JPA.

Я думал, что могу просто указать свой составной ключ только с аннотацией ИД. Например:

@Entity 
public class IdType implements Serializable 
{ 
    /** 
    * User specified Unique identifier. 
    * Both idTypeCode and idCategory are together 
    * a compound key, so as to ensure that the 
    * combination of the both can not occur more 
    * than once in the table. 
    */ 
    @Id 
    public String idTypeCode; 
    @Id 
    public IdCategory idCategory; 

    public String idTypeName; 
} 

Но я был неправ. Мне нужно использовать отдельный IdClass. В противном случае я получаю загадочные сообщения об ошибках, как описано выше. Теперь мой класс (ы) выглядеть следующим образом:

@Entity @IdClass(IdTypeCompoundId.class) 
public class IdType implements Serializable 
{ 
    /** 
    * User specified Unique identifier. 
    * Both idTypeCode and idCategory are together 
    * a compound key, so as to ensure that the 
    * combination of the both can not occur more 
    * than once in the table. 
    */ 
    @Id 
    public String idTypeCode; 
    @Id 
    public IdCategory idCategory; 

    public String idTypeName; 
} 


public class IdTypeCompoundId implements Serializable 
{ 
    public String idTypeCode; 

    public IdCategory idCategory; 
} 

и это все счастливы. Слияние проходит без проблем. т. Е. Первое слияние вызывает вставку, второе слияние с теми же деталями (и в моем случае, например, с другим идентификатором idTypeName) вызывает обновление существующей строки таблицы IdType.

Я действительно не понимаю, почему JPA требует использования отдельной таблицы «IdClass» для создания сложного ключа. Я бы подумал, что он имеет всю необходимую информацию через два (в моем случае) атрибуты, аннотированные с помощью Id. Но, видимо, этого недостаточно.

В любом случае проблема решена. Я надеюсь, что кому-нибудь это поможет.

 Смежные вопросы

  • Нет связанных вопросов^_^