Skip to content

Commit bb8a1a8

Browse files
authored
Merge branch '5.6' into 5.6-perf-test
2 parents ee77773 + 5201a45 commit bb8a1a8

File tree

43 files changed

+2089
-571
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+2089
-571
lines changed

.github/workflows/codeql.yml

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
name: "CodeQL"
2+
3+
on:
4+
push:
5+
branches: [ '5.6' ]
6+
pull_request:
7+
# The branches below must be a subset of the branches above
8+
branches: [ '5.6' ]
9+
schedule:
10+
- cron: '34 11 * * 4'
11+
12+
jobs:
13+
analyze:
14+
name: Analyze
15+
runs-on: ubuntu-latest
16+
permissions:
17+
actions: read
18+
contents: read
19+
security-events: write
20+
21+
strategy:
22+
fail-fast: false
23+
matrix:
24+
language: [ 'java' ]
25+
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
26+
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
27+
28+
steps:
29+
- name: Checkout repository
30+
uses: actions/checkout@v3
31+
32+
# Initializes the CodeQL tools for scanning.
33+
- name: Initialize CodeQL
34+
uses: github/codeql-action/init@v2
35+
with:
36+
languages: ${{ matrix.language }}
37+
# If you wish to specify custom queries, you can do so here or in a config file.
38+
# By default, queries listed here will override any specified in a config file.
39+
# Prefix the list here with "+" to use these queries and those in the config file.
40+
41+
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
42+
queries: +security-and-quality
43+
44+
45+
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
46+
# If this step fails, then you should remove it and run the build manually (see below)
47+
- name: Autobuild
48+
uses: github/codeql-action/autobuild@v2
49+
50+
# ℹ️ Command-line programs to run using the OS shell.
51+
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
52+
53+
# If the Autobuild fails above, remove it and uncomment the following three lines.
54+
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
55+
56+
# - run: |
57+
# echo "Run, Build Application using script"
58+
# ./location_of_script_within_repo/buildscript.sh
59+
60+
- name: Perform CodeQL Analysis
61+
uses: github/codeql-action/analyze@v2
62+
with:
63+
category: "/language:${{matrix.language}}"

Jenkinsfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ stage('Configure') {
3636
// buildEnv(defaultJdk, 'db2'),
3737
// buildEnv(defaultJdk, 'mssql'),
3838
// buildEnv(defaultJdk, 'sybase'),
39-
buildEnv(defaultJdk, 'hana', 'HANA'),
39+
// buildEnv(defaultJdk, 'hana', 'HANA'),
4040
// buildEnv(defaultJdk, 's390x', 's390x'),
4141
// buildEnv(defaultJdk, 'tidb', 'tidb', '[email protected]'),
4242
// Disable EDB for now as the image is not available anymore

README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ It also provides an implementation of the JPA specification, which is the standa
88

99
This is the repository of its source code: see [Hibernate.org](https://hibernate.org/orm/) for additional information.
1010

11-
[![Build Status](https://ci.hibernate.org/job/hibernate-orm-main-h2-main/badge/icon)](https://ci.hibernate.org/job/hibernate-orm-main-h2-main/)
12-
[![Language grade: Java](https://img.shields.io/lgtm/grade/java/g/hibernate/hibernate-orm.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/hibernate/hibernate-orm/context:java)
11+
[![Build Status](https://ci.hibernate.org/job/hibernate-orm-pipeline/job/5.6/badge/icon)](https://ci.hibernate.org/job/hibernate-orm-pipeline/job/5.6/)
1312

1413
Building from sources
1514
=========

changelog.txt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,25 @@ Hibernate 5 Changelog
33

44
Note: Please refer to JIRA to learn more about each issue.
55

6+
Changes in 5.6.15.Final (February 06, 2023)
7+
------------------------------------------------------------------------------------------------------------------------
8+
9+
https://hibernate.atlassian.net/projects/HHH/versions/32121
10+
11+
** Bug
12+
* [HHH-16049] - Setting a property to its current value with bytecode enhancement enabled results in unnecessary SQL Update in some (many) cases
13+
* [HHH-15665] - Mariadb is missing identifier quote on SEQUENCE QUERY
14+
* [HHH-15618] - Procedure should accept TypedParameterValue as parameter
15+
16+
** Improvement
17+
* [HHH-15693] - Introduce a fast-path access for ClassLoaderService being retrieved from ServiceRegistry
18+
* [HHH-15690] - HQLQueryPlan to have a direct reference to QueryTranslatorFactory
19+
* [HHH-15685] - Improve efficiency of Dialect lookup in Loader and HqlSqlWalker
20+
21+
** Patch
22+
* [HHH-15792] - Explicitly add JavaDoc to make @deprecated hint for createSQLQuery visible in Eclipse
23+
24+
625
Changes in 5.6.14.Final (November 04, 2022)
726
------------------------------------------------------------------------------------------------------------------------
827

ci/jpa-2.2-tck.Jenkinsfile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ pipeline {
77
tools {
88
jdk 'OpenJDK 8 Latest'
99
}
10+
options {
11+
rateLimitBuilds(throttle: [count: 1, durationName: 'day', userBoost: true])
12+
buildDiscarder(logRotator(numToKeepStr: '3', artifactNumToKeepStr: '3'))
13+
disableConcurrentBuilds(abortPrevious: true)
14+
}
1015
parameters {
1116
booleanParam(name: 'NO_SLEEP', defaultValue: true, description: 'Whether the NO_SLEEP patch should be applied to speed up the TCK execution')
1217
}

ci/jpa-3.0-tck.Jenkinsfile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ pipeline {
77
tools {
88
jdk 'OpenJDK 8 Latest'
99
}
10+
options {
11+
rateLimitBuilds(throttle: [count: 1, durationName: 'day', userBoost: true])
12+
buildDiscarder(logRotator(numToKeepStr: '3', artifactNumToKeepStr: '3'))
13+
disableConcurrentBuilds(abortPrevious: true)
14+
}
1015
parameters {
1116
choice(name: 'IMAGE_JDK', choices: ['jdk8', 'jdk11'], description: 'The JDK base image version to use for the TCK image.')
1217
string(name: 'TCK_VERSION', defaultValue: '3.0.0', description: 'The version of the Jakarta JPA TCK i.e. `2.2.0` or `3.0.1`')

documentation/src/test/java/org/hibernate/userguide/caching/SecondLevelCacheTest.java

Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,23 +22,27 @@
2222
import org.hibernate.Session;
2323
import org.hibernate.annotations.CacheConcurrencyStrategy;
2424
import org.hibernate.annotations.NaturalId;
25+
import org.hibernate.annotations.NaturalIdCache;
2526
import org.hibernate.cfg.AvailableSettings;
27+
import org.hibernate.internal.SessionFactoryImpl;
2628
import org.hibernate.jpa.QueryHints;
2729
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
2830
import org.hibernate.stat.CacheRegionStatistics;
2931
import org.hibernate.stat.Statistics;
3032

33+
import org.hibernate.testing.TestForIssue;
3134
import org.junit.Ignore;
3235
import org.junit.Test;
3336

3437
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
38+
import static org.junit.Assert.assertEquals;
3539
import static org.junit.Assert.assertNotNull;
3640

3741

3842
/**
3943
* @author Vlad Mihalcea
4044
*/
41-
@Ignore
45+
4246
//@FailureExpected( jiraKey = "HHH-12146", message = "No idea why those changes cause this to fail, especially in the way it does" )
4347
public class SecondLevelCacheTest extends BaseEntityManagerFunctionalTestCase {
4448

@@ -251,10 +255,89 @@ public void testCache() {
251255
});
252256
}
253257

258+
@Test
259+
@TestForIssue( jiraKey = "HHH-14944") // issue is also reproduceable in Hibernate 5.4
260+
public void testCacheVerifyHits() {
261+
doInJPA( this::entityManagerFactory, entityManager -> {
262+
entityManager.persist( new Person() );
263+
Person aPerson= new Person();
264+
aPerson.setName( "John Doe" );
265+
aPerson.setCode( "unique-code" );
266+
entityManager.persist( aPerson );
267+
Session session = entityManager.unwrap(Session.class);
268+
SessionFactoryImpl sfi = (SessionFactoryImpl) session.getSessionFactory();
269+
sfi.getStatistics().clear();
270+
return aPerson;
271+
});
272+
273+
doInJPA(this::entityManagerFactory, entityManager -> {
274+
log.info("Native load by natural-id, generate first hit");
275+
276+
Session session = entityManager.unwrap(Session.class);
277+
SessionFactoryImpl sfi = (SessionFactoryImpl) session.getSessionFactory();
278+
//tag::caching-entity-natural-id-example[]
279+
Person person = session
280+
.byNaturalId(Person.class)
281+
.using("code", "unique-code")
282+
.load();
283+
284+
assertNotNull(person);
285+
log.info("NaturalIdCacheHitCount: " + sfi.getStatistics().getNaturalIdCacheHitCount());
286+
log.info("SecondLevelCacheHitCount: " + sfi.getStatistics().getSecondLevelCacheHitCount());
287+
assertEquals(1, sfi.getStatistics().getNaturalIdCacheHitCount());
288+
assertEquals(1, sfi.getStatistics().getSecondLevelCacheHitCount());
289+
//end::caching-entity-natural-id-example[]
290+
});
291+
292+
doInJPA(this::entityManagerFactory, entityManager -> {
293+
log.info("Native load by natural-id, generate second hit");
294+
295+
Session session = entityManager.unwrap(Session.class);
296+
SessionFactoryImpl sfi = (SessionFactoryImpl) session.getSessionFactory();
297+
//tag::caching-entity-natural-id-example[]
298+
Person person = session.bySimpleNaturalId(Person.class).load("unique-code");
299+
assertNotNull(person);
300+
301+
// resolve in persistence context (first level cache)
302+
session.bySimpleNaturalId(Person.class).load("unique-code");
303+
log.info("NaturalIdCacheHitCount: " + sfi.getStatistics().getNaturalIdCacheHitCount());
304+
log.info("SecondLevelCacheHitCount: " + sfi.getStatistics().getSecondLevelCacheHitCount());
305+
assertEquals(2, sfi.getStatistics().getNaturalIdCacheHitCount());
306+
assertEquals(2, sfi.getStatistics().getSecondLevelCacheHitCount());
307+
308+
session.clear();
309+
// persistence context (first level cache) empty, should resolve from second level cache
310+
log.info("Native load by natural-id, generate third hit");
311+
person = session.bySimpleNaturalId(Person.class).load("unique-code");
312+
log.info("NaturalIdCacheHitCount: " + sfi.getStatistics().getNaturalIdCacheHitCount());
313+
log.info("SecondLevelCacheHitCount: " + sfi.getStatistics().getSecondLevelCacheHitCount());
314+
assertNotNull(person);
315+
assertEquals(3, sfi.getStatistics().getNaturalIdCacheHitCount());
316+
assertEquals(3, sfi.getStatistics().getSecondLevelCacheHitCount());
317+
318+
//Remove the entity from the persistence context
319+
Long id = person.getId();
320+
321+
entityManager.detach(person); // still it should resolve from second level cache after this
322+
323+
log.info("Native load by natural-id, generate 4. hit");
324+
person = session.bySimpleNaturalId(Person.class).load("unique-code");
325+
log.info("NaturalIdCacheHitCount: " + sfi.getStatistics().getNaturalIdCacheHitCount());
326+
assertEquals("we expected now 4 hits" , 4, sfi.getStatistics().getNaturalIdCacheHitCount());
327+
assertNotNull(person);
328+
session.delete(person); // evicts natural-id from first & second level cache
329+
person = session.bySimpleNaturalId(Person.class).load("unique-code");
330+
assertEquals(4, sfi.getStatistics().getNaturalIdCacheHitCount()); // thus hits should not increment
331+
332+
//end::caching-entity-natural-id-example[]
333+
});
334+
}
335+
254336
//tag::caching-entity-natural-id-mapping-example[]
255337
@Entity(name = "Person")
256338
@Cacheable
257339
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
340+
@NaturalIdCache
258341
public static class Person {
259342

260343
@Id

gradle/version.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
hibernateVersion=5.6.15-SNAPSHOT
1+
hibernateVersion=5.6.16-SNAPSHOT

hibernate-core/src/main/java/org/hibernate/Session.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1171,6 +1171,16 @@ interface LockRequest {
11711171

11721172
<T> org.hibernate.query.Query<T> createNamedQuery(String name, Class<T> resultType);
11731173

1174+
/**
1175+
* Create a {@link NativeQuery} instance for the given SQL query string.
1176+
*
1177+
* @param queryString The SQL query
1178+
*
1179+
* @return The query instance for manipulation and execution
1180+
*
1181+
* @deprecated (since 5.2) use {@link #createNativeQuery(String)} instead
1182+
*/
1183+
@Deprecated
11741184
@Override
11751185
NativeQuery createSQLQuery(String queryString);
11761186
}

hibernate-core/src/main/java/org/hibernate/action/internal/EntityUpdateAction.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import java.io.Serializable;
1010

1111
import org.hibernate.AssertionFailure;
12+
import org.hibernate.CacheMode;
1213
import org.hibernate.HibernateException;
1314
import org.hibernate.cache.CacheException;
1415
import org.hibernate.cache.spi.access.EntityDataAccess;
@@ -254,7 +255,7 @@ public void execute() throws HibernateException {
254255

255256
final StatisticsImplementor statistics = factory.getStatistics();
256257
if ( persister.canWriteToCache() ) {
257-
if ( persister.isCacheInvalidationRequired() || entry.getStatus() != Status.MANAGED ) {
258+
if ( isCacheInvalidationRequired( persister, session ) || entry.getStatus() != Status.MANAGED ) {
258259
persister.getCacheAccessStrategy().remove( session, ck );
259260
}
260261
else if ( session.getCacheMode().isPutEnabled() ) {
@@ -288,6 +289,13 @@ else if ( session.getCacheMode().isPutEnabled() ) {
288289

289290
}
290291

292+
private static boolean isCacheInvalidationRequired(
293+
EntityPersister persister,
294+
SharedSessionContractImplementor session) {
295+
// the cache has to be invalidated when CacheMode is equal to GET or IGNORE
296+
return persister.isCacheInvalidationRequired() || session.getCacheMode() == CacheMode.GET || session.getCacheMode() == CacheMode.IGNORE;
297+
}
298+
291299
protected boolean cacheUpdate(EntityPersister persister, Object previousVersion, Object ck) {
292300
final SharedSessionContractImplementor session = getSession();
293301
try {

hibernate-core/src/main/java/org/hibernate/boot/model/naming/Identifier.java

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,64 @@ public static Identifier toIdentifier(String text, boolean quote) {
7575
}
7676
}
7777

78+
/**
79+
* Means to generate an {@link Identifier} instance from its simple text form.
80+
* <p>
81+
* If passed text is {@code null}, {@code null} is returned.
82+
* <p>
83+
* If passed text is surrounded in quote markers, the generated Identifier
84+
* is considered quoted. Quote markers include back-ticks (`),
85+
* double-quotes (") and brackets ([ and ]).
86+
*
87+
* @param text The text form
88+
* @param quote Whether to quote unquoted text forms
89+
* @param quoteOnNonIdentifierChar Controls whether to treat the result as quoted if text contains characters that are invalid for identifiers
90+
*
91+
* @return The identifier form, or {@code null} if text was {@code null}
92+
*/
93+
public static Identifier toIdentifier(String text, boolean quote, boolean quoteOnNonIdentifierChar) {
94+
if ( StringHelper.isEmpty( text ) ) {
95+
return null;
96+
}
97+
int start = 0;
98+
int end = text.length();
99+
while ( start < end ) {
100+
if ( !Character.isWhitespace( text.charAt( start ) ) ) {
101+
break;
102+
}
103+
start++;
104+
}
105+
while ( start < end ) {
106+
if ( !Character.isWhitespace( text.charAt( end - 1 ) ) ) {
107+
break;
108+
}
109+
end--;
110+
}
111+
if ( isQuoted( text, start, end ) ) {
112+
start++;
113+
end--;
114+
quote = true;
115+
}
116+
else if ( quoteOnNonIdentifierChar && !quote ) {
117+
// Check the letters to determine if we must quote the text
118+
char c = text.charAt( start );
119+
if ( !Character.isLetter( c ) && c != '_' ) {
120+
// SQL identifiers must begin with a letter or underscore
121+
quote = true;
122+
}
123+
else {
124+
for ( int i = start + 1; i < end; i++ ) {
125+
c = text.charAt( i );
126+
if ( !Character.isLetterOrDigit( c ) && c != '_' ) {
127+
quote = true;
128+
break;
129+
}
130+
}
131+
}
132+
}
133+
return new Identifier( text.substring( start, end ), quote );
134+
}
135+
78136
/**
79137
* Is the given identifier text considered quoted. The following patterns are
80138
* recognized as quoted:<ul>
@@ -96,6 +154,20 @@ public static boolean isQuoted(String name) {
96154
|| ( name.startsWith( "\"" ) && name.endsWith( "\"" ) );
97155
}
98156

157+
public static boolean isQuoted(String name, int start, int end) {
158+
if ( start + 2 < end ) {
159+
switch ( name.charAt( start ) ) {
160+
case '`':
161+
return name.charAt( end - 1 ) == '`';
162+
case '[':
163+
return name.charAt( end - 1 ) == ']';
164+
case '"':
165+
return name.charAt( end - 1 ) == '"';
166+
}
167+
}
168+
return false;
169+
}
170+
99171
/**
100172
* Constructs an identifier instance.
101173
*

0 commit comments

Comments
 (0)