We are using EclipseLink 2.5.2 and WildFly 9.0.0.
Here is a method that gets called a certain number of times every hour (specified by an EJB timer). For my testing purposes, I've changed it to fire off every minute, and in my specific configuration this method will get called 10 times per minute since there are 10 updates to be made:
@Stateless
public class NetCentricDataService {
@PersistenceContext(unitName = "NetCentricPersistenceUnit")
private EntityManager em;
public void insertUpdate(A a, B b, boolean insert) {
if (insert) {
em.persist(a);
em.flush();
if (b != null) {
em.persist(b);
em.flush();
}
} else {
em.merge(a);
if (b != null) {
em.merge(b);
}
em.flush();
}
}
}
When I clear the tables associated with the two entity classes below, the if(insert)
block executes, the persist
calls work fine, and the DB is updated; however, if there are existing entries in the DB, the else
block gets executed, the merge
calls run with no Exception
s, but the DB is not updated. I am checking this in SQL Developer after the method call is complete.
EDIT: For example, the following does not work:
A a = dataService.getA(); // gets exisiting A from DB
a.setSubject("My Subject");
B b = dataService.getB(); // gets existing B from DB
b.setFoo(123.45);
insertUpdate(a, b, false);
Here is entity class A:
@Entity
@Table(name = "A")
@SuppressWarnings("unused")
public class A implements Serializable {
/**
* Method called by container before DB insert.
*/
@PrePersist
public void beforeInsert() {
if (objectType == null) {
objectType = ObjectTypeEnum.UNKNOWN;
}
}
@Id
@Column(name = "MY_UID")
private String myUid;
@Column(name = "MY_NUMBER")
private int myNumber;
@Column(name = "SUBJECT")
private String subject;
@Enumerated(EnumType.ORDINAL)
@Column(name = "OBJECT_TYPE")
private ObjectTypeEnum objectType;
// other columns, getters, setters, equals, etc.
}
And here is entity class B:
@Entity
@Table(name = "B")
@SuppressWarnings("unused")
public class B implements Serializable {
@Id
@Column(name = "MY_UID", nullable = false)
private String myUid;
@Column(name = "FOO")
private double foo;
@Column(name = "BAR")
private double bar;
}
Note: MY_UID in B is a foreign key for MY_UID in A.
Note: There is no updatable=false property on any of the columns I'm trying to update.
Let me know if there are any other files/methods/etc. I can include or if there is any more information I can provide. It is also worth noting that I do not maintain any of the code I posted, but I've been working with it recently. I asked the maintainer, and he said he wasn't sure why this was happening. Thanks in advance for any help!
EDIT - Here is the datasources configuration from standalone-full.xml:
<subsystem xmlns="urn:jboss:domain:datasources:3.0">
<datasources>
<datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS" enabled="true" use-java-context="true">
<connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE</connection-url>
<driver>h2</driver>
<security>
<user-name>sa</user-name>
<password>****</password>
</security>
</datasource>
<datasource jta="true" jndi-name="java:jboss/datasources/SFDS" pool-name="SFDS" enabled="true" use-java-context="true" use-ccm="true">
<connection-url>jdbc:oracle:thin:@DB:1521:ORACLE_SID</connection-url>
<driver>ojdbc6</driver>
<new-connection-sql>select 1 from dual</new-connection-sql>
<pool>
<min-pool-size>10</min-pool-size>
<max-pool-size>100</max-pool-size>
<prefill>false</prefill>
<use-strict-min>false</use-strict-min>
<flush-strategy>FailingConnectionOnly</flush-strategy>
</pool>
<security>
<user-name>wildfly_user</user-name>
<password>****</password>
</security>
<validation>
<check-valid-connection-sql>select 1 from dual</check-valid-connection-sql>
<use-fast-fail>true</use-fast-fail>
</validation>
</datasource>
<drivers>
<driver name="h2" module="com.h2database.h2">
<xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
</driver>
<driver name="ojdbc6" module="com.oracle.jdbc">
<xa-datasource-class>oracle.jdbc.OracleDriver</xa-datasource-class>
</driver>
</drivers>
</datasources>
</subsystem>