Hi.
I've configured and deployed a container-managed JPA application with Hibernate 4.2.2.Final on a Karaf 2.3.x following this manual:
http://docs.jboss.org/hibernate/orm/4.3/devguide/en-US/html/ch17.html
In particular, I've used:
- Hibernate 4.2.2.Final
- Aries JPA 1.0.1
- Aries Transaction 1.0.1
- Aries JNDI 1.0.0
- Karaf 2.3.x
Everything seems to work properly except when I want to flush changes on a persistent entity inside a JTA transaction. Usually, it is done automatically at the end of transaction but it is not the case. I must manually call "flush" method from entity manager to save this changes.
This is my configuration:
persistence.xmlCode:
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="mknotificationsUnit" transaction-type="JTA">
<jta-data-source>osgi:service/javax.sql.DataSource/(osgi.jndi.service.name=jdbc/testDb)</jta-data-source>
<properties>
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="hibernate.archive.autodetection" value="class" />
<property name="hibernate.transaction.flush_before_completion" value="true" />
</properties>
</persistence-unit>
</persistence>
datasource.xmlCode:
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0">
<bean id="mkDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost/mknotifications" />
<property name="username" value="xxx" />
<property name="password" value="xxx" />
</bean>
<service ref="mkDataSource" interface="javax.sql.DataSource">
<service-properties>
<entry key="osgi.jndi.service.name" value="jdbc/testDb" />
</service-properties>
</service>
</blueprint>
blueprint.xmlCode:
<bean id="notificationsHandler" class="com.proof.NotificationsHandlerImpl">
<jpa:context property="entityManager" unitname="mknotificationsUnit" />
<tx:transaction method="getOrCreate" />
</bean>
entity classCode:
@Entity
@Table(name = "notification", uniqueConstraints = {@UniqueConstraint(name = "uq_recipient_service", columnNames = {"recipient", "service" }) })
@NamedQueries({
@NamedQuery(name = "findUniqueNotification", query = "select n from Notification n where n.recipient = :recipientUri and n.service = :serviceUri"),
@NamedQuery(name = "findNotificationsByRecipient", query = "select n from Notification n where n.recipient = :recipientUri order by n.service asc") })
public class Notification extends GenericEntity {
private static final String URI_SCHEMA = "notification";
// Named Queries
public static final String NQ_UNIQUE = "findUniqueNotification";
public static final String NQ_BY_RECIPIENT = "findNotificationsByRecipient";
@Column(nullable = false)
private String recipient;
@Column(nullable = false)
private String service;
@Temporal(TemporalType.TIMESTAMP)
@Column(nullable = false, updatable = false)
private Date created;
@Temporal(TemporalType.TIMESTAMP)
@Column
private Date lastChange;
public String getRecipient() {
return recipient;
}
public void setRecipient(String recipient) {
this.recipient = recipient;
}
public String getService() {
return service;
}
public void setService(String service) {
this.service = service;
}
public Date getLastChange() {
return lastChange;
}
public void setLastChange(Date lastChange) {
this.lastChange = lastChange;
}
@PrePersist
protected void prePersist() {
created = new Date();
}
}
transactional methodCode:
// This method is transactional as you can see on configuration
public Notification getOrCreate(URI service, URI recipient) {
Notification notification = null;
try {
TypedQuery < Notification > query = entityManager.createNamedQuery(Notification.NQ_UNIQUE, Notification.class);
query.setParameter("recipientUri", recipient.toString());
query.setParameter("serviceUri", service.toString());
// Query is executed without problems
notification = query.getSingleResult();
} catch (NoResultException e) {
notification = new Notification();
notification.setService(service);
notification.setRecipient(recipient);
// Entity is persisted as I want
entityManager.persist(notification);
}
// I update "lastChange" field but this change is not persisted automatically.
// I have to manually do "entityManager.flush" later
notification.setLastChange(new Date());
return notification;
}
Note that I change the
"lastChange" property on Notification entity in the previous line before the end of method. This change is not synchronized at commit phase as usual in a typical JPA application. In this case, I must do "entityManager.flush()" to save the changes.
Is there any property to force the flush on commit phase?
Thanks!