2016-04-25 3 views
0

Если у вас есть приложение JEE6, которое отлично работает на Glassfish 3.1.1 с лет. Теперь нужно переместить его в JEE7/Glassfish 4.1.1 и побежал в несколько проблем в отношении JPA/EclipseLink:JPA 2.1 однонаправленное отображение OneToMany: EDITED

а) У меня есть объект Заявителю, который содержит несколько списков отображенный в качестве однонаправленного OneToMany отношений ,

@Entity 
@Table(name="applicant") 
@AttributeOverride(name="id", [email protected](name="UserID", insertable=false, updatable=false)) 
public class Applicant extends BaseEntityVersioned implements Serializable { 
.. 
.. 
@OneToMany(cascade=CascadeType.ALL, orphanRemoval=true) 
@JoinColumn(name="BewerberID", nullable=false) 
private List<ITKenntnis> itKenntnisse = new ArrayList<ITKenntnis>(); 
.. 

    public List<ITKenntnis> getITKenntnisse() { 
     return this.itKenntnisse; 
    } 

    public void setITKenntnisse(List<ITKenntnis> itKenntnisse) { 
     this.itKenntnisse = itKenntnisse; 
    } 

    public ITKenntnis createITKenntnis(){ 
     return new ITKenntnis(); 
    } 

    public boolean addITKenntnis(ITKenntnis itKenntnis) { 
     getITKenntnisse().add(itKenntnis); 
     return true; 
    } 
... 
} 

и сущность ITKEnntnis

@Entity 
@Table(name="ITKenntnis") 
public class ITKenntnis extends BaseEntityVersioned implements Serializable { 
    private static final long serialVersionUID = 1L; 

    @Id 
    @GeneratedValue(strategy=GenerationType.IDENTITY) 
    @Column(name="ID") 
    private Integer id; 

    @Override 
    public Integer getId() { 
     return id; 
    } 

    @Override 
    public void setId(Integer id) { 
     this.id=id; 
    } 
} 

До сих пор я просто добавили новый экземпляр ITKentnis заявителя с addKenntnis и сохранялись заявитель. С Glassfish 4.1.1 Я получаю сообщение об ошибке ->

javax.persistence.PersistenceException: Исключение [EclipseLink-4002] (Eclipse, послесвечение услуги - 2.6.2.qualifier): org.eclipse.persistence.exceptions.DatabaseException Внутренняя Исключение: java.sql.SQLException: поле «BewerberID» не имеет значения по умолчанию код с ошибки: 1364

поле «BewerberID» является внешним ключом в моей таблице базы данных, которая не может быть пустым, и Я не могу изменить это определение.

Единственным обходным решением, которое я нашел до сих пор, было переопределение отношения к двунаправленному. Поскольку у меня много отношений, и код работал с JPA 2.0, я был бы признателен, если бы было более простое решение.

b) У меня есть объект Приложение, которое определяет однонаправленное отношение @ManyToOne к Заявителю.

@Entity 
@Table(name="bewerbungen") 
public class Application extends BaseEntityVersioned implements Serializable { 
... 
// uni-directional 
@ManyToOne (fetch=FetchType.LAZY) 
@JoinColumn(name="BewerberID") 
private Bewerberprofil bewerberprofil; 
... 

} 

Независимо от погодного это хороший дизайн или нет (у меня были причины, чтобы отобразить его, что путь) -> когда я пытаюсь удалить объект, когда я вижу обновление, которое устанавливает поле «BewerberID» в нуль, вместо удаления. Почему это в JPA 2.1 и как я могу это изменить?

Извините за длинный пост.

Томас

EDIT: Я сделал дальнейшие исследования этих проблем, отладка заявления SQL, сгенерированные на Glasfish 3.1.1. сервер, который работает.

Добавление нового ребенка объект имеет следующие операторы SQL, которые являются такими же, как на новом сервере ->

[#|2016-04-26T17:22:55.613+0200|INFO|glassfish3.1.1|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=25;_ThreadName=Thread-2;|[EL Fine]: 2016-04-26 17:22:55.613--ClientSession(1645443748)--Connection(1826150217)--Thread(Thread[http-thread-pool-80(2),5,grizzly-kernel])--INSERT INTO bewerberedv (Bearbeitet, Bereich, Bewertung, Dauer, Kenntnis, Version, ZuletztVerwendet) VALUES (?, ?, ?, ?, ?, ?, ?) 
    bind => [true, 6, 1, null, 377, 2016-04-26 17:24:08.0, null] 
|#] 

[#|2016-04-26T17:22:55.628+0200|INFO|glassfish3.1.1|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=25;_ThreadName=Thread-2;|[EL Fine]: 2016-04-26 17:22:55.628--ClientSession(1645443748)--Connection(1826150217)--Thread(Thread[http-thread-pool-80(2),5,grizzly-kernel])--SELECT LAST_INSERT_ID() 
|#] 

[#|2016-04-26T17:22:55.644+0200|INFO|glassfish3.1.1|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=25;_ThreadName=Thread-2;|[EL Fine]: 2016-04-26 17:22:55.644--ClientSession(1645443748)--Connection(1826150217)--Thread(Thread[http-thread-pool-80(2),5,grizzly-kernel])--UPDATE bewerberedv SET BewerberID = ? WHERE (ID = ?) 
    bind => [2575, 1223970] 
|#] 

Разница заключается в том, что на новом сервере INSERT терпит неудачу, потому что поле «BewerberID» не может быть NULL. Как-то проверка в базе данных, похоже, отличается.

То же самое для DELETE, которая имеет следующий вывод ->

[#|2016-04-26T17:13:39.363+0200|INFO|glassfish3.1.1|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=31;_ThreadName=Thread-2;|[EL Fine]: 2016-04-26 17:13:39.363--ClientSession(792940001)--Connection(1806567172)--Thread(Thread[http-thread-pool-80(4),5,grizzly-kernel])--UPDATE bewerbungen SET BewerberID = ?, PositionID = ?, InseratID = ?, Version = ? WHERE ((ID = ?) AND (Version = ?)) 
    bind => [null, null, null, 2016-04-26 17:14:52.0, 1304157, 2016-04-26 17:14:25.0] 
|#] 

[#|2016-04-26T17:13:39.363+0200|INFO|glassfish3.1.1|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=31;_ThreadName=Thread-2;|[EL Fine]: 2016-04-26 17:13:39.363--ClientSession(792940001)--Connection(1806567172)--Thread(Thread[http-thread-pool-80(4),5,grizzly-kernel])--UPDATE inserateanz SET AnzahlBew = ?, AnzOffeneBewerbung = ?, AnzNeueBewerbung = ? WHERE (ID = ?) 
    bind => [0, 0, 0, 61277] 
|#] 

[#|2016-04-26T17:13:39.363+0200|INFO|glassfish3.1.1|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=31;_ThreadName=Thread-2;|[EL Fine]: 2016-04-26 17:13:39.363--ClientSession(792940001)--Connection(1806567172)--Thread(Thread[http-thread-pool-80(4),5,grizzly-kernel])--UPDATE positionenanz SET AnzahlBew = ?, AnzOffeneBewerbung = ?, AnzNeueBewerbung = ? WHERE (ID = ?) 
    bind => [0, 0, 0, 44726] 
|#] 

[#|2016-04-26T17:13:39.363+0200|INFO|glassfish3.1.1|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=31;_ThreadName=Thread-2;|[EL Fine]: 2016-04-26 17:13:39.363--ClientSession(792940001)--Connection(1806567172)--Thread(Thread[http-thread-pool-80(4),5,grizzly-kernel])--DELETE FROM bewerbungen WHERE ((ID = ?) AND (Version = ?)) 
    bind => [1304157, 2016-04-26 17:14:52.0] 

То interresting, потому что на новом сервере я имею такое же обновление заявление "? UPDATE bewerbungen SET BewerberID = ....", но там он сбой немедленно с нулевым ограничением!

+0

Однонаправленные отношения OneToMany используют таблицу соединений. Вы предлагаете, чтобы вы работали без этого раньше? См. § 2.2.10.1 спецификации JPA (2.0 или 2.1) –

+0

Да, она работает с 2011 года с JPA2.0. Также ознакомьтесь с https://en.wikibooks.org/wiki/Java_Persistence/OneToMany в разделе «Дополнительно». –

+0

Также см. «Pro JPA 2» главы Майка Кейта «Расширенное объектно-реляционное сопоставление»: избегание таблиц соединений До этого момента мы обсуждали однонаправленное отображение «один ко многим» в контексте использования таблицы соединений, но это также можно сопоставить однонаправленное отображение без использования таблицы соединений. Это требует, чтобы внешний ключ находился в целевой таблице , или «много» стороне отношения, даже если целевой объект не имеет ссылки на «одну» сторону. Это называется однонаправленным сопоставлением внешнего ключа «один ко многим», поскольку внешний ключ находится в целевой таблице вместо ... –

ответ

0

Как я узнал с помощью Криса Делахунта, проблема заключается не в различии между JPA 2.0 и 2.1, а в отношении поведения базы данных (драйвера). Это также подразумевалось приведенными выше высказываниями SQL.

Решение было то, что я только что изменил определение JDBC в Glsassfish 4.1.1 от

<jdbc-connection-pool datasource-classname="com.mysql.jdbc.jdbc2.optional.MysqlDataSource" name="Test" res-type="javax.sql.DataSource"> 

в

<jdbc-connection-pool datasource-classname="com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource" name="Test" res-type="javax.sql.ConnectionPoolDataSource"> 

Теперь вставки и удаления работу, как и прежде. :)

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