1 package myorg.queryex;
2
3 import static org.junit.Assert.*;
4
5 import java.util.ArrayList;
6 import java.util.Calendar;
7 import java.util.Date;
8 import java.util.GregorianCalendar;
9 import java.util.Iterator;
10 import java.util.List;
11
12 import javax.persistence.EntityManager;
13 import javax.persistence.LockModeType;
14 import javax.persistence.PersistenceException;
15
16 import org.apache.commons.logging.Log;
17 import org.apache.commons.logging.LogFactory;
18 import org.junit.Before;
19 import org.junit.Test;
20
21 public class QueryLocksTest extends QueryBase {
22 private static final Log log = LogFactory.getLog(QueryLocksTest.class);
23 public static enum Action { INSERT, UPDATE, FAIL };
24
25 @Before
26 public void setUpLocksTest() {
27 em.getTransaction().commit();
28 cleanup(em);
29 populate(em);
30 }
31
32
33
34
35
36 private class Writer extends Thread {
37 private String context;
38 private Actor actor;
39 private LockModeType lockMode;
40 private EntityManager em_;
41 private Action action;
42 private int sleepTime=100;
43 private String errorText;
44 public Writer(String context, Actor actor, LockModeType lockMode) {
45 this.context = context;
46 this.actor = actor;
47 this.lockMode = lockMode;
48 em_ = emf.createEntityManager();
49 em_.getTransaction().begin();
50 log.debug(context + " transaction started");
51 }
52 public boolean isDone() { return action != null && em_==null; }
53 public String getContext() { return context; }
54 public Action getAction() { return action; }
55 public String getErrorText() { return errorText; }
56 public void run() {
57 try {
58 log.debug(context + " selecting with lockMode=" + lockMode);
59
60 List<Actor> actors = em_.createQuery(
61 "select a from Actor a "
62 + "where a.person in ("
63 + "select p from Person p "
64 + "where p.firstName=:firstName and p.lastName=:lastName "
65 + "or p.firstName='" + context + "')", Actor.class)
66 .setLockMode(lockMode)
67 .setParameter("firstName", actor.getFirstName())
68 .setParameter("lastName", actor.getLastName())
69 .setMaxResults(1)
70 .getResultList();
71
72
73
74
75
76
77
78
79
80
81 try {
82 log.debug(context + " sleeping " + sleepTime + " msecs");
83 Thread.sleep(sleepTime);
84 } catch (Exception ex){}
85 if (actors.size()==0) {
86 log.debug(context + " creating entity");
87 em_.persist(actor);
88 action=Action.INSERT;
89 } else {
90 log.debug(context + " updating entity");
91 actors.get(0).setBirthDate(actor.getBirthDate());
92 action=Action.UPDATE;
93 }
94 em_.flush();
95 log.debug(context + " committing transaction version=" + actor.getVersion());
96 em_.getTransaction().commit();
97 log.debug(context + " committed transaction version=" + actor.getVersion());
98 } catch (PersistenceException ex) {
99 log.debug(context + " failed " + ex);
100 em_.getTransaction().rollback();
101 action = Action.FAIL; errorText = ex.toString();
102 } finally {
103 em_.close(); em_=null;
104 }
105 }
106 }
107
108
109
110
111
112
113 protected int testUpsert(LockModeType lockMode, int count) {
114 List<Writer> writers = new ArrayList<QueryLocksTest.Writer>();
115
116 for (int i=0; i<count; i++) {
117 Date birthDate = new GregorianCalendar(1969+i, Calendar.MAY, 25).getTime();
118 Actor actor = new Actor(new Person("test-actor" + i)
119 .setFirstName("Anne")
120 .setLastName("Heche")
121 .setBirthDate(birthDate));
122 writers.add(new Writer("writer" + i, actor, lockMode));
123 }
124
125
126 List<Writer> working = new ArrayList<Writer>();
127 for (Writer writer : writers) {
128 working.add(writer); writer.start();
129 }
130
131
132 while (!working.isEmpty()) {
133 try { Thread.sleep(100); } catch (Exception ex) {}
134 Iterator<Writer> itr = working.iterator();
135 while (itr.hasNext()) {
136 if (itr.next().isDone()) { itr.remove(); }
137 }
138 }
139
140
141 List<Actor> actors = em.createQuery(
142 "select a from Actor a JOIN FETCH a.person as p " +
143 "where p.firstName=:firstName and p.lastName=:lastName", Actor.class)
144 .setParameter("firstName", "Anne")
145 .setParameter("lastName", "Heche")
146 .getResultList();
147 log.debug("actors=" + actors);
148 for (Writer w : writers) {
149 log.debug(String.format("%s => %s %s", w.getContext(), w.getAction(), w.getErrorText()==null?"":w.getErrorText()));
150 }
151 return actors.size();
152 }
153
154 @Test
155 public void testSimple() {
156 log.info("*** testPersistentSimple ***");
157 assertEquals("unexpected number of actors", 1, testUpsert(LockModeType.NONE, 1));
158 }
159
160 @Test
161 public void testNONE() {
162 log.info("*** testNONE ***");
163 int count=testUpsert(LockModeType.NONE, 5);
164 for (int i=0; i<10 && count<=1; i++) {
165
166 cleanup(em);
167 populate(em);
168 count=testUpsert(LockModeType.NONE, 5);
169 }
170 assertTrue("unexpected number of actors", count > 1);
171 }
172
173 @Test
174 public void testPessimisticWrite1() {
175 log.info("*** testPersistentWrite1 ***");
176 assertEquals("unexpected number of actors", 1, testUpsert(LockModeType.PESSIMISTIC_WRITE, 1));
177 }
178
179 @Test @org.junit.Ignore
180 public void testPessimisticWrite() {
181 log.info("*** testPersistentWrite ***");
182 assertEquals("unexpected number of actors", 1, testUpsert(LockModeType.PESSIMISTIC_WRITE, 5));
183 }
184
185 @Test @org.junit.Ignore
186 public void testPessimisticForceIncrement() {
187 log.info("*** testPersistentForceIncrement ***");
188 assertEquals("unexpected number of actors", 1, testUpsert(LockModeType.PESSIMISTIC_FORCE_INCREMENT, 5));
189 }
190 }