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.slf4j.Logger;
17 import org.slf4j.LoggerFactory;
18 import org.junit.Before;
19 import org.junit.Test;
20
21 public class QueryLocksTest extends QueryBase {
22 private static final Logger log = LoggerFactory.getLogger(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 if (!em_.contains(actor.getPerson())) {
88 em_.persist(actor.getPerson());
89 }
90 em_.persist(actor);
91 action=Action.INSERT;
92 } else {
93 log.debug(context + " updating entity");
94 actors.get(0).setBirthDate(actor.getBirthDate());
95 action=Action.UPDATE;
96 }
97 em_.flush();
98 log.debug(context + " committing transaction version=" + actor.getVersion());
99 em_.getTransaction().commit();
100 log.debug(context + " committed transaction version=" + actor.getVersion());
101 } catch (PersistenceException ex) {
102 log.debug(context + " failed " + ex);
103 em_.getTransaction().rollback();
104 action = Action.FAIL; errorText = ex.toString();
105 } finally {
106 em_.close(); em_=null;
107 }
108 }
109 }
110
111
112
113
114
115
116 protected int testUpsert(LockModeType lockMode, int count) {
117 List<Writer> writers = new ArrayList<QueryLocksTest.Writer>();
118
119 for (int i=0; i<count; i++) {
120 Date birthDate = new GregorianCalendar(1969+i, Calendar.MAY, 25).getTime();
121 Actor actor = new Actor(new Person("test-actor" + i)
122 .setFirstName("Anne")
123 .setLastName("Heche")
124 .setBirthDate(birthDate));
125 writers.add(new Writer("writer" + i, actor, lockMode));
126 }
127
128
129 List<Writer> working = new ArrayList<Writer>();
130 for (Writer writer : writers) {
131 working.add(writer); writer.start();
132 }
133
134
135 while (!working.isEmpty()) {
136 try { Thread.sleep(100); } catch (Exception ex) {}
137 Iterator<Writer> itr = working.iterator();
138 while (itr.hasNext()) {
139 if (itr.next().isDone()) { itr.remove(); }
140 }
141 }
142
143
144 List<Actor> actors = em.createQuery(
145 "select a from Actor a JOIN FETCH a.person as p " +
146 "where p.firstName=:firstName and p.lastName=:lastName", Actor.class)
147 .setParameter("firstName", "Anne")
148 .setParameter("lastName", "Heche")
149 .getResultList();
150 log.debug("actors=" + actors);
151 for (Writer w : writers) {
152 log.debug(String.format("%s => %s %s", w.getContext(), w.getAction(), w.getErrorText()==null?"":w.getErrorText()));
153 }
154 return actors.size();
155 }
156
157 @Test
158 public void testSimple() {
159 log.info("*** testPersistentSimple ***");
160 assertEquals("unexpected number of actors", 1, testUpsert(LockModeType.NONE, 1));
161 }
162
163 @Test
164 public void testNONE() {
165 log.info("*** testNONE ***");
166 int count=testUpsert(LockModeType.NONE, 5);
167 for (int i=0; i<10 && count<=1; i++) {
168
169 cleanup(em);
170 populate(em);
171 count=testUpsert(LockModeType.NONE, 5);
172 }
173 assertTrue("unexpected number of actors", count > 1);
174 }
175
176 @Test
177 public void testPessimisticWrite1() {
178 log.info("*** testPersistentWrite1 ***");
179 assertEquals("unexpected number of actors", 1, testUpsert(LockModeType.PESSIMISTIC_WRITE, 1));
180 }
181
182 @Test @org.junit.Ignore
183 public void testPessimisticWrite() {
184 log.info("*** testPersistentWrite ***");
185 assertEquals("unexpected number of actors", 1, testUpsert(LockModeType.PESSIMISTIC_WRITE, 5));
186 }
187
188 @Test @org.junit.Ignore
189 public void testPessimisticForceIncrement() {
190 log.info("*** testPersistentForceIncrement ***");
191 assertEquals("unexpected number of actors", 1, testUpsert(LockModeType.PESSIMISTIC_FORCE_INCREMENT, 5));
192 }
193 }