Java – @ stateless WebService with JPA JTA: how to submit changes to managed entities?
I have the following simple WebService declared as @ freeless EJB in GlassFish 3.1 Run on 2.2, eclipse link 2.4 1. Use JTA datasource to connect to MySQL database:
@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(); }
Entity class of 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 (no < persistence > tag):
<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>
Web service declaration:
@Path("row") @Stateless public class TimeRowWebService { @PersistenceContext(unitName = "test") private EntityManager em; ... }
The problem is that if entities exist, changes are only stored in the persistencecontext, but they are not committed to the database This means that I can use the changes to retrieve the correct data, but for example, if I restart as, the changes will disappear There are no errors in the as log
So I think I have to do some bean level manual transactions to do this What exactly do I need to add to make it work?
Solution
After trying to make @ embeddedid work, I try to implement it with the generated @ ID, and then add a unique constraint for these two key fields
entity
public class TimeRow implements Serializable { @Id @GeneratedValue private long id; @JoinColumn(name = "USERID",referencedColumnName = "USERID") @ManyToOne(optional = false) private UserTable table; @Basic(optional = false) @Column(name = "DAY") @Temporal(TemporalType.DATE) private Date date; @Lob @Column(name="ROWVALUES") private List<Double> values; ... }
In addition, I have changed the database engine from MyISAM to InnoDB for better foreign key support To this end, I added default storage engine = InnoDB to / etc / MySQL / my. Under the [mysqld] section cnf.
After generating the database structure using DDL, I have added a unique constraint for userid and day:
alter table TIMEROW add unique index(USERID,DAY);
Now it works normally and the data has been modified correctly:) thank you very much to all those who have contributed to this problem!