I am having a performance problem with JavaDB (Derby) writing transactions. Each transaction takes more than 500ms and I might have hundreds of thousands a day. I am expecting to deploy on MySql and I don't know if I am going to have the same problem there, but I am trying to improve the performance on Derby before trying it.
One transaction involves updating a string of records -- as many as 6 like so:
public void update(List<Tally> list) {
try {
utx.begin();
for (Tally tally : list) em.merge(tally);
utx.commit();
// etc
I wanted to see if an UPDATE query would work better, since JPA wouldn't have to keep track of the columns that updated and compose a SQL query (side question: is this a good theory?)
So I coded a named query that looks like this:
@NamedQuery(name="TallyUpdate",
query="UPDATE Tally t SET t.vote = t.vote + 1 WHERE t.id IN :idSet"
That is operated like this:
@PersistenceContext protected EntityManager em;
@Resource protected UserTransaction utx;
public void incrementVote(List<Long> idList) {
Query q = em.createNamedQuery("TallyUpdate");
q.setParameter("idSet", idList);
try {
utx.begin();
q.executeUpdate();
utx.commit();
//etc
THE executeUpdate() call always throws an exception:
SEVERE: javax.persistence.TransactionRequiredException: executeUpdate is not supported for a Query object obtained through non-transactional access of a container-managed transactional EntityManager
at com.sun.enterprise.container.common.impl.QueryWrapper.executeUpdate(QueryWrapper.java:225)
The JPA implementation is EclipseLink 2.3.0
What does that word-salad exception mean and how am I supposed to run the update?
RESULT POSTING:
I did move the createnamedQuery() call to after the utx.begin() call and the update started working. I am not sure why but I am going to run with it for now.No result yet regarding the relative performance, but my posting above is misleading. When a vote is tallied it is tallied about 24-36 different ways, not 6. So there are six calls to the original update() method (which uses merge()) each with a list of about 6 records. It is this collection of calls that take more than 500ms. If the Tally table is empty then that benchmark is only about 27ms, which is about the speed I would like to see. The 500ms+ number is what I see when the table fills to 50,000 rows or more.
If anyone is interested in me posting the results of where I end up on this, please comment saying so.
P.S. this is a JSF application running under GlassFish, not EJB. I am not sure if there is any implication of that related to performance.