mam następujący prosty usługa zadeklarowane jako @Stateless
EJB działa na GlassFish 3.1.2.2 z EclipseLink 2.4.1 używając JTA DataSource
aby połączyć się z bazą danych MySQL:@Stateless webservice with JPA + JTA: Jak zatwierdzać zmiany zarządzanego obiektu?
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response update(TimeRow e) throws Exception {
if ((e.getKey() == null) || !e.getKey().keyValid()) {
return Response.status(400).build();
}
TimeRow existing = em.find(TimeRow.class, e.getKey());
if (existing == null) {
em.persist(e);
} else {
existing.setValues(e.getValues());
em.flush();
}
return Response.status(204).build();
}
klasy podmiotu TimeRow
:
@Entity
@NamedQueries({
@NamedQuery(name="TimeRow.findAllByUser",
query="SELECT t FROM TimeRow t WHERE t.table.userId = :uid")
})
public class TimeRow implements Serializable {
@EmbeddedId
private TimeRowPK key;
@MapsId("userId")
@JoinColumn(name = "USERID", referencedColumnName = "userId")
@ManyToOne
private UserTable table;
@Column(name="ROWVALUES")
private List<Double> values;
public TimeRow() {
this.key = new TimeRowPK();
this.values = new ArrayList<Double>(20);
extendValuesTo20();
}
public TimeRow(String uid, Date date) {
this.key = new TimeRowPK(date, uid);
this.table = new UserTable(uid);
this.values = new ArrayList<Double>(20);
extendValuesTo20();
}
public List<Double> getValues() {
return values;
}
public void setValues(List<Double> values) {
this.values = values;
extendValuesTo20();
}
private void extendValuesTo20() {
if (this.values.size() < 20) {
for (int i = this.values.size(); i < 20; i++) {
this.values.add(0.0);
}
}
}
}
@EmbeddableId
TimeRowPK
:
@Embeddable
public class TimeRowPK implements Serializable {
public TimeRowPK() { }
public TimeRowPK(Date date, String userId) {
this.date = date;
this.userId = userId;
}
@Column(name="DAY")
private Date date;
@Column(name = "USERID")
private String userId;
public boolean keyValid() {
return ((date != null) && ((userId != null) && !userId.isEmpty()));
}
}
persistence.xml
(bez metki <persistence>
):
<persistence-unit name="test" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>jdbc/test</jta-data-source>
<class>com.test.TimeRow</class>
<class>com.test.TimeRowPK</class>
<class>...</class>
<properties>
<property name="eclipselink.ddl-generation" value="create-tables" />
<property name="eclipselink.ddl-generation.output-mode" value="database" />
</properties>
</persistence-unit>
deklaracja Webservice:
@Path("row")
@Stateless
public class TimeRowWebService {
@PersistenceContext(unitName = "test")
private EntityManager em;
...
}
Problemem jest to, że jeśli jednostka nie istnieje, zmiany są zapisywane tylko w PersistenceContext
, ale nie są zobowiązani do baza danych. Oznacza to, że mogę pobrać poprawne dane ze zmianami, ale na przykład, jeśli ponownie uruchomię AS, zmiany znikną. W dzienniku systemu AS nie ma błędów.
Sądzę więc, że muszę wykonać ręczną obsługę transakcji na poziomie fasoli, aby uzyskać tę pracę. Co dokładnie muszę dodać, aby to zadziałało?
Czy ziarno zostało uznane za @Stateless? –
Tak, to prawda! –
W tym przypadku nie widzę tutaj błędu ... '@ Stateless' implikuje' @TransactionAttribute (REQUIRED) 'jeśli go nie zmienisz ... Może znajduje się w' MyEntity.setValues () 'lub w samej deklaracji "MyEntity".Czy możesz opublikować kod 'MyEntity'? –