I faced an issue earlier with JPA. I have two apps : the main one, using Java/JPA (EclipseLink), and a second one, using PHP. The two apps have access to the same database. Now, I'm accessing an "Expedition" object through Java, then calling the PHP app through a web-service (which is supposed to modify an attribute of this object in the shared database table "Expedition"), then accessing this attribute through the Java app.
Problem is, the object seems not to be modified in the Java app, even if it is modified in the database. I'm thinking about a cache problem.
The original code (simplified) :
System.out.println(expedition.getInfosexpedition()); // null
// Calling the web-service (modification of the "expedition" object in the database)
this.ec.eXtractor(expedition);
System.out.println(expedition.getInfosexpedition()); // Still null, should not be
Definitions of the "Expedition" and "Infosexpedition" classes :
Expedition :
@Entity
@Table(name = "expedition")
@XmlRootElement
public class Expedition implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "idExpedition")
private Integer idExpedition;
@OneToOne(cascade = CascadeType.ALL, mappedBy = "idExpedition")
@XmlTransient
private Infosexpedition infosexpedition;
Infosexpedition :
@Entity
@Table(name = "infosexpedition")
@XmlRootElement
public class Infosexpedition implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "idInfoExpedition")
private Integer idInfoExpedition;
@JoinColumn(name = "idExpedition", referencedColumnName = "idExpedition")
@OneToOne(optional = false)
@XmlTransient
private Expedition idExpedition;
I've been able to make the original code work by doing this :
System.out.println(expedition.getInfosexpedition()); // null
// Calling the web-service (modification of the "expedition" object in the database)
this.ec.eXtractor(expedition);
try
{
// Getting explicitly the "infosExpedition" item through a simple named request
Infosexpedition infos = this.ec.getFacade().getEm().createNamedQuery("Infosexpedition.findByIdExpedition", Infosexpedition.class)
.setParameter("idExpedition", expedition)
.setHint("eclipselink.refresh", "true")
.setHint("eclipselink.cache-usage", "DoNotCheckCache")
.setHint("eclipselink.read-only", "true") // This line did the trick
.getSingleResult();
expedition.setInfosexpedition(infos);
}
catch (NoResultException nre) {}
System.out.println(expedition.getInfosexpedition()); // Not null anymore, OK
I'm trying to understand what happens here, and why did I had to specify a "read-only" hint to make this work... Before that, I tried almost everything, from evictAll()
calls to detach()
/merge()
calls, and nothing worked.
Can someone help me to understand how the different levels of cache worked here ? And why is my newly created line "read-only" ?
Thanks a lot.