JPA 2.1单向OneToMany映射:已编辑

时间:2016-04-25 14:59:09

标签: java-ee jpa-2.0 jpa-2.1 glassfish-4.1.1

如果有一个JEE6应用程序可以在Glassfish 3.1.1上正常使用多年。现在必须将其移至JEE7 / Glassfish 4.1.1并遇到有关JPA / Eclipselink的几个问题:

a)我有一个实体申请人,其中包含几个列为单向OneToMany关系的列表。

@Entity
@Table(name="applicant")
@AttributeOverride(name="id", column=@Column(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;
    }
}

到目前为止,我只是通过addKenntnis向申请人添加了一个新的ITKentnis实例并坚持申请人。 使用Glassfish 4.1.1我收到错误 - &gt;

javax.persistence.PersistenceException:Exception [EclipseLink-4002](Eclipse Persistence Services - 2.6.2.qualifier):org.eclipse.persistence.exceptions.DatabaseException 内部异常:java.sql.SQLException:字段&#39; BewerberID&#39;没有默认值 错误代码:1364

该领域&#34; BewerberID&#34;是我的数据库表中的外键不能为空,我无法更改此定义。

到目前为止,我发现的唯一解决方法是将关系重新定义为双向关系。由于我有很多关系并且代码适用于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;
...

}

无论这是一个好的设计还是没有(我有理由以这种方式绘制) - &gt;当我尝试删除实体时,我看到一个更新设置字段&#34; BewerberID&#34;为null,而不是删除。为什么在JPA 2.1中,我该如何改变呢?

对不起,很长的帖子。

托马斯

编辑: 我对这些问题进行了进一步调查,调试了Glasfish 3.1.1上生成的SQL语句。服务器正在工作。

添加新的子实体具有以下SQL语句,这些语句与新服务器上的相同 - &gt;

[#|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失败,因为字段&#34; BewerberID&#34;不能为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]
这是有趣的,因为在新服务器上我有相同的更新声明&#34; UPDATE bewerbungen SET BewerberID =?,....&#34;但是它立即失败并使用空约束!

1 个答案:

答案 0 :(得分:0)

正如我在Chris Delahunt的帮助下发现的那样,问题不是JPA 2.0和2.1之间的区别,而是数据库(驱动程序)行为的问题。上面的SQL语句也暗示了这一点。

解决方案是,我刚从

更改了Glsassfish 4.1.1中的JDBC定义
<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">

现在插入和删除工作方式与以前一样。 :)