Skip to content

Commit 056a995

Browse files
bchen-godaddygsmet
authored andcommitted
HHH-12866 Add a test to verify Oracle can executed the generated SQL
1 parent caf7513 commit 056a995

File tree

2 files changed

+164
-0
lines changed

2 files changed

+164
-0
lines changed
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* Hibernate, Relational Persistence for Idiomatic Java
3+
*
4+
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
5+
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
6+
*/
7+
package org.hibernate.test.locking;
8+
9+
import javax.persistence.Column;
10+
import javax.persistence.Entity;
11+
import javax.persistence.GeneratedValue;
12+
import javax.persistence.Id;
13+
import javax.persistence.JoinColumn;
14+
import javax.persistence.OneToOne;
15+
import javax.persistence.Table;
16+
17+
import org.hibernate.annotations.GenericGenerator;
18+
19+
@Entity
20+
@Table(name = "T_LOCK_B")
21+
public class B {
22+
23+
private Long id;
24+
private A a;
25+
private String value;
26+
27+
public B() {
28+
}
29+
30+
public B(String value) {
31+
this.value = value;
32+
}
33+
34+
@Id
35+
@GeneratedValue(generator = "increment")
36+
@GenericGenerator(name = "increment", strategy = "increment")
37+
public Long getId() {
38+
return id;
39+
}
40+
41+
public void setId(Long id) {
42+
this.id = id;
43+
}
44+
45+
@Column(name = "b_value")
46+
public String getValue() {
47+
return value;
48+
}
49+
50+
public void setValue(String value) {
51+
this.value = value;
52+
}
53+
54+
@OneToOne
55+
@JoinColumn(name = "a_id")
56+
public A getA() {
57+
return a;
58+
}
59+
60+
public void setA(A a) {
61+
this.a = a;
62+
}
63+
}
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*
2+
* Hibernate, Relational Persistence for Idiomatic Java
3+
*
4+
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
5+
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
6+
*/
7+
package org.hibernate.test.locking;
8+
9+
import static java.util.regex.Pattern.CASE_INSENSITIVE;
10+
import static java.util.regex.Pattern.MULTILINE;
11+
import static org.junit.Assert.assertTrue;
12+
13+
import java.util.regex.Matcher;
14+
import java.util.regex.Pattern;
15+
16+
import org.hibernate.LockMode;
17+
import org.hibernate.Session;
18+
import org.hibernate.boot.SessionFactoryBuilder;
19+
import org.hibernate.dialect.Oracle10gDialect;
20+
import org.hibernate.dialect.Oracle12cDialect;
21+
import org.hibernate.dialect.Oracle8iDialect;
22+
import org.hibernate.dialect.Oracle9iDialect;
23+
import org.hibernate.testing.RequiresDialect;
24+
import org.hibernate.testing.jdbc.SQLStatementInterceptor;
25+
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
26+
import org.junit.Before;
27+
import org.junit.Test;
28+
29+
/**
30+
* @author Bin Chen ([email protected])
31+
*/
32+
public class PessimisticWriteLockWithAliasTest
33+
extends BaseNonConfigCoreFunctionalTestCase {
34+
35+
private SQLStatementInterceptor sqlStatementInterceptor;
36+
37+
@Override
38+
protected Class<?>[] getAnnotatedClasses() {
39+
return new Class[]{ A.class, B.class };
40+
}
41+
42+
@Override
43+
protected void configureSessionFactoryBuilder(SessionFactoryBuilder sfb) {
44+
sqlStatementInterceptor = new SQLStatementInterceptor( sfb );
45+
}
46+
47+
private A entityA;
48+
private B entityB;
49+
50+
@Before
51+
public void createTestData() {
52+
Session session = sessionFactory().openSession();
53+
session.beginTransaction();
54+
try {
55+
entityA = new A();
56+
session.persist( entityA );
57+
entityB = new B( "foo" );
58+
entityB.setA( entityA );
59+
session.persist( entityB );
60+
}
61+
finally {
62+
session.getTransaction().commit();
63+
session.close();
64+
}
65+
}
66+
67+
@Test
68+
@RequiresDialect({ Oracle8iDialect.class, Oracle9iDialect.class,
69+
Oracle10gDialect.class, Oracle12cDialect.class })
70+
public void testSetLockModeWithAlias() {
71+
72+
Session session = sessionFactory().openSession();
73+
session.beginTransaction();
74+
try {
75+
session.createQuery(
76+
"select b from B b left join fetch b.a", B.class )
77+
.unwrap( org.hibernate.query.Query.class )
78+
.setLockMode( "b", LockMode.PESSIMISTIC_WRITE )
79+
.list();
80+
81+
/*
82+
* The generated SQL would be like: <pre> select b0_.id as id1_1_0_, a1_.id as id1_0_1_, b0_.a_id as
83+
* a_id3_1_0_, b0_.b_value as b_value2_1_0_, a1_.a_value as a_value2_0_1_ from T_LOCK_B b0_ left outer join
84+
* T_LOCK_A a1_ on b0_.a_id=a1_.id for update of b0_.id </pre>
85+
*/
86+
String lockingQuery = sqlStatementInterceptor.getSqlQueries().getLast().toLowerCase();
87+
88+
// attempt to get the alias that is specified in the from clause
89+
Pattern fromTableAliasPattern = Pattern.compile( "from t_lock_b (\\S+)", CASE_INSENSITIVE | MULTILINE );
90+
Matcher aliasGroup = fromTableAliasPattern.matcher( lockingQuery );
91+
assertTrue( "Fail to locate alias in the from clause: " + lockingQuery, aliasGroup.find() );
92+
assertTrue( "Actual query: " + lockingQuery,
93+
lockingQuery.endsWith( " for update of " + aliasGroup.group( 1 ) + ".id" ) );
94+
}
95+
finally {
96+
session.getTransaction().commit();
97+
session.close();
98+
}
99+
}
100+
101+
}

0 commit comments

Comments
 (0)