Make sure Hibernate works with the Jakarta Persistence 3.1 API

This commit is contained in:
Christian Beikov 2022-02-23 13:18:03 +01:00
parent 6b8fdf3b70
commit b737231416
19 changed files with 3120 additions and 19 deletions

View File

@ -23,9 +23,7 @@ pipeline {
} }
dir('hibernate') { dir('hibernate') {
checkout scm checkout scm
sh """ \ sh './gradlew publishToMavenLocal'
./gradlew publishToMavenLocal
"""
script { script {
env.HIBERNATE_VERSION = sh ( env.HIBERNATE_VERSION = sh (
script: "grep hibernateVersion gradle/version.properties|cut -d'=' -f2", script: "grep hibernateVersion gradle/version.properties|cut -d'=' -f2",
@ -45,7 +43,7 @@ pipeline {
steps { steps {
sh """ \ sh """ \
docker rm -f tck || true docker rm -f tck || true
docker rm -f tck-vol || true docker volume rm -f tck-vol || true
docker volume create tck-vol docker volume create tck-vol
docker run -v ~/.m2/repository/org/hibernate:/root/.m2/repository/org/hibernate:z -v tck-vol:/tck/persistence-tck/tmp/:z -e NO_SLEEP=${params.NO_SLEEP} -e HIBERNATE_VERSION=$HIBERNATE_VERSION --name tck jakarta-tck-runner docker run -v ~/.m2/repository/org/hibernate:/root/.m2/repository/org/hibernate:z -v tck-vol:/tck/persistence-tck/tmp/:z -e NO_SLEEP=${params.NO_SLEEP} -e HIBERNATE_VERSION=$HIBERNATE_VERSION --name tck jakarta-tck-runner
docker cp tck:/tck/persistence-tck/tmp/ ./results docker cp tck:/tck/persistence-tck/tmp/ ./results

View File

@ -0,0 +1,79 @@
@Library('hibernate-jenkins-pipeline-helpers@1.5') _
pipeline {
agent {
label 'LongDuration'
}
tools {
jdk 'OpenJDK 11 Latest'
}
parameters {
choice(name: 'IMAGE_JDK', choices: ['jdk11'], description: 'The JDK base image version to use for the TCK image.')
string(name: 'TCK_VERSION', defaultValue: '3.1.0', description: 'The version of the Jakarta JPA TCK i.e. `2.2.0` or `3.0.1`')
string(name: 'TCK_SHA'/* Avoid default since the version is non-final, defaultValue: '33c8a9380fbdf223e84113a4e20866b42ba2b60a46f1d8ac25d240f0bc919294'*/, description: 'The SHA256 of the Jakarta JPA TCK that is distributed under https://download.eclipse.org/jakartaee/persistence/3.0/jakarta-persistence-tck-${TCK_VERSION}.zip.sha256')
booleanParam(name: 'NO_SLEEP', defaultValue: true, description: 'Whether the NO_SLEEP patch should be applied to speed up the TCK execution')
}
stages {
stage('Build') {
steps {
script {
docker.withRegistry('https://index.docker.io/v1/', 'hibernateci.hub.docker.com') {
docker.image('openjdk:11-jdk').pull()
}
}
dir('hibernate') {
checkout scm
sh './gradlew publishToMavenLocal -DjakartaJpaVersion=3.1.0-SNAPSHOT'
script {
env.HIBERNATE_VERSION = sh (
script: "grep hibernateVersion gradle/version.properties|cut -d'=' -f2",
returnStdout: true
).trim()
}
}
dir('tck') {
checkout changelog: false, poll: false, scm: [$class: 'GitSCM', branches: [[name: '*/main']], extensions: [], userRemoteConfigs: [[url: 'https://github.com/hibernate/jakarta-tck-runner.git']]]
sh """ \
cd jpa-3.1; docker build -f Dockerfile.${params.IMAGE_JDK} -t jakarta-tck-runner --build-arg TCK_VERSION=${params.TCK_VERSION} --build-arg TCK_SHA=${params.TCK_SHA} .
"""
}
}
}
stage('Run TCK') {
steps {
sh """ \
docker rm -f tck || true
docker volume rm -f tck-vol || true
docker volume create tck-vol
docker run -v ~/.m2/repository/org/hibernate:/root/.m2/repository/org/hibernate:z -v tck-vol:/tck/persistence-tck/tmp/:z -e NO_SLEEP=${params.NO_SLEEP} -e HIBERNATE_VERSION=$HIBERNATE_VERSION --name tck jakarta-tck-runner
docker cp tck:/tck/persistence-tck/tmp/ ./results
"""
archiveArtifacts artifacts: 'results/**'
script {
failures = sh (
script: """ \
set +x
while read line; do
if [[ "\$line" != *"Passed." ]]; then
echo "\$line"
fi
done <results/JTreport/text/summary.txt
""",
returnStdout: true
).trim()
if ( !failures.isEmpty() ) {
echo "Some TCK tests failed:"
echo failures
currentBuild.result = 'FAILURE'
}
}
}
}
}
post {
always {
// Space-separated
notifyBuildResult maintainers: 'christian.beikov@gmail.com'
}
}
}

View File

@ -32,8 +32,9 @@ ext {
ormVersion = HibernateVersion.fromFile(ormVersionFile, project) ormVersion = HibernateVersion.fromFile(ormVersionFile, project)
} }
def version = System.getProperty( 'jakartaJpaVersion', '3.0.0' )
jpaVersion = new JpaVersion('2.2') jpaVersion = new JpaVersion('2.2')
jakartaJpaVersion = new JpaVersion('3.0.0') jakartaJpaVersion = new JpaVersion(version)
} }
group = 'org.hibernate.orm' group = 'org.hibernate.orm'

View File

@ -98,9 +98,7 @@ public class IdGeneratorInterpreterImpl implements IdGeneratorStrategyInterprete
case TABLE: { case TABLE: {
return org.hibernate.id.enhanced.TableGenerator.class.getName(); return org.hibernate.id.enhanced.TableGenerator.class.getName();
} }
default: { case AUTO: {
// AUTO
if ( "increment".equalsIgnoreCase( context.getGeneratedValueGeneratorName() ) ) { if ( "increment".equalsIgnoreCase( context.getGeneratedValueGeneratorName() ) ) {
return IncrementGenerator.class.getName(); return IncrementGenerator.class.getName();
} }
@ -112,6 +110,13 @@ public class IdGeneratorInterpreterImpl implements IdGeneratorStrategyInterprete
return SequenceStyleGenerator.class.getName(); return SequenceStyleGenerator.class.getName();
} }
default: {
// UNKNOWN
if ( "UUID".equals( generationType.name() ) ) {
return UUIDGenerator.class.getName();
}
throw new UnsupportedOperationException( "Unsupported generation type:" + generationType );
}
} }
} }

View File

@ -50,6 +50,9 @@ public class LocalXmlResourceResolver implements javax.xml.stream.XMLResolver {
else if ( MappingXsdSupport.jpa30.getNamespaceUri().matches( namespace ) ) { else if ( MappingXsdSupport.jpa30.getNamespaceUri().matches( namespace ) ) {
return openUrlStream( LocalSchemaLocator.resolveLocalSchemaUrl( MappingXsdSupport.jpa30.getLocalResourceName() ) ); return openUrlStream( LocalSchemaLocator.resolveLocalSchemaUrl( MappingXsdSupport.jpa30.getLocalResourceName() ) );
} }
else if ( MappingXsdSupport.jpa31.getNamespaceUri().matches( namespace ) ) {
return openUrlStream( LocalSchemaLocator.resolveLocalSchemaUrl( MappingXsdSupport.jpa31.getLocalResourceName() ) );
}
else if ( ConfigXsdSupport.getJPA10().getNamespaceUri().matches( namespace ) ) { else if ( ConfigXsdSupport.getJPA10().getNamespaceUri().matches( namespace ) ) {
// JPA 1.0 and 2.0 share the same namespace URI // JPA 1.0 and 2.0 share the same namespace URI
return openUrlStream( LocalSchemaLocator.resolveLocalSchemaUrl( ConfigXsdSupport.getJPA10().getLocalResourceName() ) ); return openUrlStream( LocalSchemaLocator.resolveLocalSchemaUrl( ConfigXsdSupport.getJPA10().getLocalResourceName() ) );
@ -61,6 +64,9 @@ public class LocalXmlResourceResolver implements javax.xml.stream.XMLResolver {
else if ( ConfigXsdSupport.getJPA30().getNamespaceUri().matches( namespace ) ) { else if ( ConfigXsdSupport.getJPA30().getNamespaceUri().matches( namespace ) ) {
return openUrlStream( LocalSchemaLocator.resolveLocalSchemaUrl( ConfigXsdSupport.getJPA30().getLocalResourceName() ) ); return openUrlStream( LocalSchemaLocator.resolveLocalSchemaUrl( ConfigXsdSupport.getJPA30().getLocalResourceName() ) );
} }
else if ( ConfigXsdSupport.getJPA31().getNamespaceUri().matches( namespace ) ) {
return openUrlStream( LocalSchemaLocator.resolveLocalSchemaUrl( ConfigXsdSupport.getJPA31().getLocalResourceName() ) );
}
else if ( MappingXsdSupport.hibernateMappingXml.getNamespaceUri().matches( namespace ) ) { else if ( MappingXsdSupport.hibernateMappingXml.getNamespaceUri().matches( namespace ) ) {
return openUrlStream( LocalSchemaLocator.resolveLocalSchemaUrl( MappingXsdSupport.hibernateMappingXml.getLocalResourceName() ) ); return openUrlStream( LocalSchemaLocator.resolveLocalSchemaUrl( MappingXsdSupport.hibernateMappingXml.getLocalResourceName() ) );
} }

View File

@ -31,11 +31,12 @@ public class ConfigXsdSupport {
* 3: JPA 2.1 * 3: JPA 2.1
* 4: JPA 2.2 (default) * 4: JPA 2.2 (default)
* 5: Jakarta Persistence 3.0 * 5: Jakarta Persistence 3.0
* 6: Jakarta Persistence 3.1
*/ */
private static final XsdDescriptor[] xsdCache = new XsdDescriptor[6]; private static final XsdDescriptor[] xsdCache = new XsdDescriptor[7];
public XsdDescriptor latestJpaDescriptor() { public XsdDescriptor latestJpaDescriptor() {
return getJPA22(); return getJPA30();
} }
public static boolean shouldBeMappedToLatestJpaDescriptor(String uri) { public static boolean shouldBeMappedToLatestJpaDescriptor(String uri) {
@ -60,6 +61,9 @@ public class ConfigXsdSupport {
case "3.0": { case "3.0": {
return getJPA30(); return getJPA30();
} }
case "3.1": {
return getJPA31();
}
default: { default: {
throw new IllegalArgumentException( "Unrecognized JPA persistence.xml XSD version : `" + version + "`" ); throw new IllegalArgumentException( "Unrecognized JPA persistence.xml XSD version : `" + version + "`" );
} }
@ -161,5 +165,21 @@ public class ConfigXsdSupport {
return jpa30; return jpa30;
} }
} }
public static XsdDescriptor getJPA31() {
final int index = 6;
synchronized ( xsdCache ) {
XsdDescriptor jpa31 = xsdCache[index];
if ( jpa31 == null ) {
jpa31 = LocalXsdResolver.buildXsdDescriptor(
"org/hibernate/jpa/persistence_3_1.xsd",
"3.1",
"https://jakarta.ee/xml/ns/persistence"
);
xsdCache[index] = jpa31;
}
return jpa31;
}
}
} }

View File

@ -31,7 +31,7 @@ import org.xml.sax.SAXException;
public class LocalXsdResolver { public class LocalXsdResolver {
public static String latestJpaVerison() { public static String latestJpaVerison() {
return "2.2"; return "3.0";
} }
public static boolean isValidJpaVersion(String version) { public static boolean isValidJpaVersion(String version) {
@ -41,6 +41,7 @@ public class LocalXsdResolver {
case "2.1": case "2.1":
case "2.2": case "2.2":
case "3.0": case "3.0":
case "3.1":
return true; return true;
default: default:
return false; return false;

View File

@ -53,6 +53,12 @@ public class MappingXsdSupport {
"https://jakarta.ee/xml/ns/persistence/orm" "https://jakarta.ee/xml/ns/persistence/orm"
); );
public static final XsdDescriptor jpa31 = LocalXsdResolver.buildXsdDescriptor(
"org/hibernate/jpa/orm_3_1.xsd",
"3.1",
"https://jakarta.ee/xml/ns/persistence/orm"
);
public static final XsdDescriptor hbmXml = LocalXsdResolver.buildXsdDescriptor( public static final XsdDescriptor hbmXml = LocalXsdResolver.buildXsdDescriptor(
"org/hibernate/xsd/mapping/legacy-mapping-4.0.xsd", "org/hibernate/xsd/mapping/legacy-mapping-4.0.xsd",
"4.0", "4.0",
@ -85,6 +91,7 @@ public class MappingXsdSupport {
case "2.1": case "2.1":
case "2.2": case "2.2":
case "3.0": case "3.0":
case "3.1":
return true; return true;
default: default:
return false; return false;
@ -108,6 +115,9 @@ public class MappingXsdSupport {
case "3.0:": { case "3.0:": {
return jpa30; return jpa30;
} }
case "3.1:": {
return jpa31;
}
default: { default: {
throw new IllegalArgumentException( "Unrecognized JPA orm.xml XSD version : `" + version + "`" ); throw new IllegalArgumentException( "Unrecognized JPA orm.xml XSD version : `" + version + "`" );
} }

View File

@ -6,7 +6,6 @@
*/ */
package org.hibernate.bytecode.spi; package org.hibernate.bytecode.spi;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain; import java.security.ProtectionDomain;
/** /**
@ -36,5 +35,5 @@ public interface ClassTransformer extends jakarta.persistence.spi.ClassTransform
String className, String className,
Class<?> classBeingRedefined, Class<?> classBeingRedefined,
ProtectionDomain protectionDomain, ProtectionDomain protectionDomain,
byte[] classfileBuffer) throws IllegalClassFormatException; byte[] classfileBuffer);
} }

View File

@ -98,6 +98,12 @@ public class StandardIdentifierGeneratorFactory
generatorTypeStrategyMap.put( GenerationType.SEQUENCE, SequenceGenerationTypeStrategy.INSTANCE ); generatorTypeStrategyMap.put( GenerationType.SEQUENCE, SequenceGenerationTypeStrategy.INSTANCE );
generatorTypeStrategyMap.put( GenerationType.TABLE, TableGenerationTypeStrategy.INSTANCE ); generatorTypeStrategyMap.put( GenerationType.TABLE, TableGenerationTypeStrategy.INSTANCE );
generatorTypeStrategyMap.put( GenerationType.IDENTITY, IdentityGenerationTypeStrategy.INSTANCE ); generatorTypeStrategyMap.put( GenerationType.IDENTITY, IdentityGenerationTypeStrategy.INSTANCE );
try {
generatorTypeStrategyMap.put( GenerationType.valueOf( "UUID" ), UUIDGenerationTypeStrategy.INSTANCE );
}
catch (IllegalArgumentException ex) {
// Ignore
}
final ClassLoaderService classLoaderService = serviceRegistry.getService( ClassLoaderService.class ); final ClassLoaderService classLoaderService = serviceRegistry.getService( ClassLoaderService.class );
final Collection<GenerationTypeStrategyRegistration> generationTypeStrategyRegistrations = classLoaderService.loadJavaServices( GenerationTypeStrategyRegistration.class ); final Collection<GenerationTypeStrategyRegistration> generationTypeStrategyRegistrations = classLoaderService.loadJavaServices( GenerationTypeStrategyRegistration.class );

View File

@ -0,0 +1,36 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.id.factory.internal;
import java.util.Properties;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.factory.spi.GenerationTypeStrategy;
import org.hibernate.id.factory.spi.GeneratorDefinitionResolver;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.type.descriptor.java.JavaType;
import jakarta.persistence.GenerationType;
public class UUIDGenerationTypeStrategy implements GenerationTypeStrategy {
/**
* Singleton access
*/
public static final UUIDGenerationTypeStrategy INSTANCE = new UUIDGenerationTypeStrategy();
@Override
public IdentifierGenerator createIdentifierGenerator(
GenerationType generationType,
String generatorName,
JavaType<?> javaType,
Properties config,
GeneratorDefinitionResolver definitionResolver,
ServiceRegistry serviceRegistry) {
throw new NotYetImplementedFor6Exception( getClass() );
}
}

View File

@ -7,6 +7,7 @@
package org.hibernate.jpa.internal.enhance; package org.hibernate.jpa.internal.enhance;
import java.lang.instrument.IllegalClassFormatException; import java.lang.instrument.IllegalClassFormatException;
import java.lang.reflect.Constructor;
import java.security.ProtectionDomain; import java.security.ProtectionDomain;
import org.hibernate.bytecode.enhance.spi.EnhancementContext; import org.hibernate.bytecode.enhance.spi.EnhancementContext;
@ -14,6 +15,7 @@ import org.hibernate.bytecode.enhance.spi.EnhancementContextWrapper;
import org.hibernate.bytecode.enhance.spi.Enhancer; import org.hibernate.bytecode.enhance.spi.Enhancer;
import org.hibernate.bytecode.spi.ClassTransformer; import org.hibernate.bytecode.spi.ClassTransformer;
import org.hibernate.cfg.Environment; import org.hibernate.cfg.Environment;
import org.hibernate.internal.util.ExceptionHelper;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
@ -21,6 +23,21 @@ import org.hibernate.cfg.Environment;
*/ */
public class EnhancingClassTransformerImpl implements ClassTransformer { public class EnhancingClassTransformerImpl implements ClassTransformer {
private static final Constructor<Exception> TRANSFORMER_CONSTRUCTOR;
static {
Constructor<Exception> constructor = null;
try {
final Class<?> transformerException = Class.forName( "jakarta.persistence.spi.TransformerException" );
//noinspection unchecked
constructor = (Constructor<Exception>) transformerException.getConstructor( String.class, Throwable.class );
}
catch (ClassNotFoundException | NoSuchMethodException e) {
// Ignore
}
TRANSFORMER_CONSTRUCTOR = constructor;
}
private final EnhancementContext enhancementContext; private final EnhancementContext enhancementContext;
public EnhancingClassTransformerImpl(EnhancementContext enhancementContext) { public EnhancingClassTransformerImpl(EnhancementContext enhancementContext) {
@ -33,7 +50,7 @@ public class EnhancingClassTransformerImpl implements ClassTransformer {
String className, String className,
Class<?> classBeingRedefined, Class<?> classBeingRedefined,
ProtectionDomain protectionDomain, ProtectionDomain protectionDomain,
byte[] classfileBuffer) throws IllegalClassFormatException { byte[] classfileBuffer) {
// The first design had the enhancer as a class variable. That approach had some goods and bads. // The first design had the enhancer as a class variable. That approach had some goods and bads.
// We don't have to create an enhancer for each class, but on the other end it would stay in memory forever. // We don't have to create an enhancer for each class, but on the other end it would stay in memory forever.
@ -44,12 +61,30 @@ public class EnhancingClassTransformerImpl implements ClassTransformer {
return enhancer.enhance( className, classfileBuffer ); return enhancer.enhance( className, classfileBuffer );
} }
catch (final Exception e) { catch (final Exception e) {
throw new IllegalClassFormatException( "Error performing enhancement of " + className ) { Throwable t;
@Override if ( TRANSFORMER_CONSTRUCTOR == null ) {
public synchronized Throwable getCause() { t = new IllegalClassFormatException( "Error performing enhancement of " + className ) {
return e; @Override
public synchronized Throwable getCause() {
return e;
}
};
}
else {
try {
t = TRANSFORMER_CONSTRUCTOR.newInstance( "Error performing enhancement of " + className, e );
} }
}; catch (Exception ex) {
t = new IllegalClassFormatException( "Error performing enhancement of " + className ) {
@Override
public synchronized Throwable getCause() {
return e;
}
};
}
}
ExceptionHelper.doThrow( t );
return null;
} }
} }

View File

@ -9,6 +9,7 @@ package org.hibernate.query.criteria;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.BigInteger; import java.math.BigInteger;
import java.sql.Date; import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.time.Instant; import java.time.Instant;
import java.util.Collection; import java.util.Collection;
@ -104,6 +105,100 @@ public interface HibernateCriteriaBuilder extends CriteriaBuilder {
<T> JpaCriteriaQuery<T> except(boolean all, CriteriaQuery<? extends T> query1, CriteriaQuery<?>... queries); <T> JpaCriteriaQuery<T> except(boolean all, CriteriaQuery<? extends T> query1, CriteriaQuery<?>... queries);
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// JPA 3.1
/**
* Create an expression that returns the sign of its
* argument, that is, {@code 1} if its argument is
* positive, {@code -1} if its argument is negative,
* or {@code 0} if its argument is exactly zero.
* @param x expression
* @return sign
*/
JpaExpression<Integer> sign(Expression<? extends Number> x);
/**
* Create an expression that returns the ceiling of its
* argument, that is, the smallest integer greater than
* or equal to its argument.
* @param x expression
* @return ceiling
*/
<N extends Number> JpaExpression<N> ceiling(Expression<N> x);
/**
* Create an expression that returns the floor of its
* argument, that is, the largest integer smaller than
* or equal to its argument.
* @param x expression
* @return floor
*/
<N extends Number> JpaExpression<N> floor(Expression<N> x);
/**
* Create an expression that returns the exponential
* of its argument, that is, Euler's number <i>e</i>
* raised to the power of its argument.
* @param x expression
* @return exponential
*/
JpaExpression<Double> exp(Expression<? extends Number> x);
/**
* Create an expression that returns the natural logarithm
* of its argument.
* @param x expression
* @return natural logarithm
*/
JpaExpression<Double> ln(Expression<? extends Number> x);
/**
* Create an expression that returns the first argument
* raised to the power of its second argument.
* @param x base
* @param y exponent
* @return the base raised to the power of the exponent
*/
JpaExpression<Double> power(Expression<? extends Number> x, Expression<? extends Number> y);
/**
* Create an expression that returns the first argument
* raised to the power of its second argument.
* @param x base
* @param y exponent
* @return the base raised to the power of the exponent
*/
JpaExpression<Double> power(Expression<? extends Number> x, Number y);
/**
* Create an expression that returns the first argument
* rounded to the number of decimal places given by the
* second argument.
* @param x base
* @param n number of decimal places
* @return the rounded value
*/
<T extends Number> JpaExpression<T> round(Expression<T> x, Integer n);
/**
* Create expression to return current local date.
* @return expression for current date
*/
JpaExpression<java.time.LocalDate> localDate();
/**
* Create expression to return current local datetime.
* @return expression for current timestamp
*/
JpaExpression<java.time.LocalDateTime> localDateTime();
/**
* Create expression to return current local time.
* @return expression for current time
*/
JpaExpression<java.time.LocalTime> localTime();
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Paths // Paths
@ -348,6 +443,9 @@ public interface HibernateCriteriaBuilder extends CriteriaBuilder {
@Override @Override
JpaFunction<Date> currentDate(); JpaFunction<Date> currentDate();
@Override
JpaFunction<Time> currentTime();
@Override @Override
JpaFunction<Timestamp> currentTimestamp(); JpaFunction<Timestamp> currentTimestamp();

View File

@ -22,6 +22,12 @@ public interface JpaSimpleCase<C,R> extends JpaExpression<R>, CriteriaBuilder.Si
@Override @Override
JpaSimpleCase<C, R> when(C condition, Expression<? extends R> result); JpaSimpleCase<C, R> when(C condition, Expression<? extends R> result);
// @Override
JpaSimpleCase<C, R> when(Expression<? extends C> condition, R result);
// @Override
JpaSimpleCase<C, R> when(Expression<? extends C> condition, Expression<? extends R> result);
@Override @Override
JpaSimpleCase<C,R> otherwise(R result); JpaSimpleCase<C,R> otherwise(R result);

View File

@ -14,6 +14,9 @@ import java.sql.Date;
import java.sql.Time; import java.sql.Time;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.time.Instant; import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
@ -687,6 +690,86 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
); );
} }
@Override
public JpaExpression<Integer> sign(Expression<? extends Number> x) {
return getFunctionDescriptor( "sign" ).generateSqmExpression(
(SqmExpression<?>) x,
null,
queryEngine,
getJpaMetamodel().getTypeConfiguration()
);
}
@Override
public <N extends Number> JpaExpression<N> ceiling(Expression<N> x) {
return getFunctionDescriptor( "ceiling" ).generateSqmExpression(
(SqmExpression<?>) x,
null,
queryEngine,
getJpaMetamodel().getTypeConfiguration()
);
}
@Override
public <N extends Number> JpaExpression<N> floor(Expression<N> x) {
return getFunctionDescriptor( "floor" ).generateSqmExpression(
(SqmExpression<?>) x,
null,
queryEngine,
getJpaMetamodel().getTypeConfiguration()
);
}
@Override
public JpaExpression<Double> exp(Expression<? extends Number> x) {
return getFunctionDescriptor( "exp" ).generateSqmExpression(
(SqmExpression<?>) x,
null,
queryEngine,
getJpaMetamodel().getTypeConfiguration()
);
}
@Override
public JpaExpression<Double> ln(Expression<? extends Number> x) {
return getFunctionDescriptor( "ln" ).generateSqmExpression(
(SqmExpression<?>) x,
null,
queryEngine,
getJpaMetamodel().getTypeConfiguration()
);
}
@Override
public JpaExpression<Double> power(Expression<? extends Number> x, Expression<? extends Number> y) {
return getFunctionDescriptor( "power" ).generateSqmExpression(
Arrays.asList( (SqmExpression<?>) x, (SqmExpression<?>) y),
null,
queryEngine,
getJpaMetamodel().getTypeConfiguration()
);
}
@Override
public JpaExpression<Double> power(Expression<? extends Number> x, Number y) {
return getFunctionDescriptor( "power" ).generateSqmExpression(
Arrays.asList( (SqmExpression<?>) x, (SqmExpression<?>) y),
null,
queryEngine,
getJpaMetamodel().getTypeConfiguration()
);
}
@Override
public <T extends Number> JpaExpression<T> round(Expression<T> x, Integer n) {
return getFunctionDescriptor( "round" ).generateSqmExpression(
Arrays.asList( (SqmExpression<?>) x, value( n ) ),
null,
queryEngine,
getJpaMetamodel().getTypeConfiguration()
);
}
@Override @Override
public <N extends Number> SqmExpression<N> neg(Expression<N> x) { public <N extends Number> SqmExpression<N> neg(Expression<N> x) {
final SqmExpression<N> sqmExpression = (SqmExpression<N>) x; final SqmExpression<N> sqmExpression = (SqmExpression<N>) x;
@ -1345,6 +1428,36 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
); );
} }
@Override
public JpaExpression<LocalDate> localDate() {
return getFunctionDescriptor("local_date")
.generateSqmExpression(
null,
queryEngine,
getJpaMetamodel().getTypeConfiguration()
);
}
@Override
public JpaExpression<LocalDateTime> localDateTime() {
return getFunctionDescriptor("local_datetime")
.generateSqmExpression(
null,
queryEngine,
getJpaMetamodel().getTypeConfiguration()
);
}
@Override
public JpaExpression<LocalTime> localTime() {
return getFunctionDescriptor("local_time")
.generateSqmExpression(
null,
queryEngine,
getJpaMetamodel().getTypeConfiguration()
);
}
@Override @Override
public <T> SqmFunction<T> function(String name, Class<T> type, Expression<?>[] args) { public <T> SqmFunction<T> function(String name, Class<T> type, Expression<?>[] args) {
SqmFunctionDescriptor functionTemplate = getFunctionDescriptor( name ); SqmFunctionDescriptor functionTemplate = getFunctionDescriptor( name );

View File

@ -216,6 +216,19 @@ public class SqmCaseSimple<T, R>
return this; return this;
} }
@Override
public JpaSimpleCase<T, R> when(Expression<? extends T> condition, R result) {
when( condition, nodeBuilder().value( result ) );
return this;
}
@Override
public JpaSimpleCase<T, R> when(Expression<? extends T> condition, Expression<? extends R> result) {
//noinspection unchecked
when( (SqmExpression<T>) condition, (SqmExpression<R>) result );
return this;
}
@Override @Override
public JpaSimpleCase<T, R> otherwise(R result) { public JpaSimpleCase<T, R> otherwise(R result) {
otherwise( nodeBuilder().value( result ) ); otherwise( nodeBuilder().value( result ) );

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,342 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2008, 2020 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0 which is available at
http://www.eclipse.org/legal/epl-2.0,
or the Eclipse Distribution License v. 1.0 which is available at
http://www.eclipse.org/org/documents/edl-v10.php.
SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
-->
<!-- persistence.xml schema -->
<xsd:schema targetNamespace="https://jakarta.ee/xml/ns/persistence"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:persistence="https://jakarta.ee/xml/ns/persistence"
elementFormDefault="qualified"
attributeFormDefault="unqualified"
version="3.1">
<xsd:annotation>
<xsd:documentation><![CDATA[
This is the XML Schema for the persistence configuration file.
The file must be named "META-INF/persistence.xml" in the
persistence archive.
Persistence configuration files must indicate
the persistence schema by using the persistence namespace:
https://jakarta.ee/xml/ns/persistence
and indicate the version of the schema by
using the version element as shown below:
<persistence xmlns="https://jakarta.ee/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence
https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd"
version="3.1">
...
</persistence>
]]></xsd:documentation>
</xsd:annotation>
<xsd:simpleType name="versionType">
<xsd:restriction base="xsd:token">
<xsd:pattern value="[0-9]+(\.[0-9]+)*"/>
</xsd:restriction>
</xsd:simpleType>
<!-- **************************************************** -->
<xsd:element name="persistence">
<xsd:complexType>
<xsd:sequence>
<!-- **************************************************** -->
<xsd:element name="persistence-unit"
minOccurs="1" maxOccurs="unbounded">
<xsd:complexType>
<xsd:annotation>
<xsd:documentation>
Configuration of a persistence unit.
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<!-- **************************************************** -->
<xsd:element name="description" type="xsd:string"
minOccurs="0">
<xsd:annotation>
<xsd:documentation>
Description of this persistence unit.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<!-- **************************************************** -->
<xsd:element name="provider" type="xsd:string"
minOccurs="0">
<xsd:annotation>
<xsd:documentation>
Provider class that supplies EntityManagers for this
persistence unit.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<!-- **************************************************** -->
<xsd:element name="jta-data-source" type="xsd:string"
minOccurs="0">
<xsd:annotation>
<xsd:documentation>
The container-specific name of the JTA datasource to use.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<!-- **************************************************** -->
<xsd:element name="non-jta-data-source" type="xsd:string"
minOccurs="0">
<xsd:annotation>
<xsd:documentation>
The container-specific name of a non-JTA datasource to use.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<!-- **************************************************** -->
<xsd:element name="mapping-file" type="xsd:string"
minOccurs="0" maxOccurs="unbounded">
<xsd:annotation>
<xsd:documentation>
File containing mapping information. Loaded as a resource
by the persistence provider.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<!-- **************************************************** -->
<xsd:element name="jar-file" type="xsd:string"
minOccurs="0" maxOccurs="unbounded">
<xsd:annotation>
<xsd:documentation>
Jar file that is to be scanned for managed classes.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<!-- **************************************************** -->
<xsd:element name="class" type="xsd:string"
minOccurs="0" maxOccurs="unbounded">
<xsd:annotation>
<xsd:documentation>
Managed class to be included in the persistence unit and
to scan for annotations. It should be annotated
with either @Entity, @Embeddable or @MappedSuperclass.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<!-- **************************************************** -->
<xsd:element name="exclude-unlisted-classes" type="xsd:boolean"
default="true" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
When set to true then only listed classes and jars will
be scanned for persistent classes, otherwise the
enclosing jar or directory will also be scanned.
Not applicable to Java SE persistence units.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<!-- **************************************************** -->
<xsd:element name="shared-cache-mode"
type="persistence:persistence-unit-caching-type"
minOccurs="0">
<xsd:annotation>
<xsd:documentation>
Defines whether caching is enabled for the
persistence unit if caching is supported by the
persistence provider. When set to ALL, all entities
will be cached. When set to NONE, no entities will
be cached. When set to ENABLE_SELECTIVE, only entities
specified as cacheable will be cached. When set to
DISABLE_SELECTIVE, entities specified as not cacheable
will not be cached. When not specified or when set to
UNSPECIFIED, provider defaults may apply.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<!-- **************************************************** -->
<xsd:element name="validation-mode"
type="persistence:persistence-unit-validation-mode-type"
minOccurs="0">
<xsd:annotation>
<xsd:documentation>
The validation mode to be used for the persistence unit.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<!-- **************************************************** -->
<xsd:element name="properties" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
A list of standard and vendor-specific properties
and hints.
</xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:element name="property"
minOccurs="0" maxOccurs="unbounded">
<xsd:annotation>
<xsd:documentation>
A name-value pair.
</xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:attribute name="name" type="xsd:string"
use="required"/>
<xsd:attribute name="value" type="xsd:string"
use="required"/>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
<!-- **************************************************** -->
<xsd:attribute name="name" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation>
Name used in code to reference this persistence unit.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<!-- **************************************************** -->
<xsd:attribute name="transaction-type"
type="persistence:persistence-unit-transaction-type">
<xsd:annotation>
<xsd:documentation>
Type of transactions used by EntityManagers from this
persistence unit.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
<xsd:attribute name="version" type="persistence:versionType"
fixed="3.1" use="required"/>
</xsd:complexType>
</xsd:element>
<!-- **************************************************** -->
<xsd:simpleType name="persistence-unit-transaction-type">
<xsd:annotation>
<xsd:documentation>
public enum PersistenceUnitTransactionType {JTA, RESOURCE_LOCAL};
</xsd:documentation>
</xsd:annotation>
<xsd:restriction base="xsd:token">
<xsd:enumeration value="JTA"/>
<xsd:enumeration value="RESOURCE_LOCAL"/>
</xsd:restriction>
</xsd:simpleType>
<!-- **************************************************** -->
<xsd:simpleType name="persistence-unit-caching-type">
<xsd:annotation>
<xsd:documentation>
public enum SharedCacheMode { ALL, NONE, ENABLE_SELECTIVE, DISABLE_SELECTIVE, UNSPECIFIED};
</xsd:documentation>
</xsd:annotation>
<xsd:restriction base="xsd:token">
<xsd:enumeration value="ALL"/>
<xsd:enumeration value="NONE"/>
<xsd:enumeration value="ENABLE_SELECTIVE"/>
<xsd:enumeration value="DISABLE_SELECTIVE"/>
<xsd:enumeration value="UNSPECIFIED"/>
</xsd:restriction>
</xsd:simpleType>
<!-- **************************************************** -->
<xsd:simpleType name="persistence-unit-validation-mode-type">
<xsd:annotation>
<xsd:documentation>
public enum ValidationMode { AUTO, CALLBACK, NONE};
</xsd:documentation>
</xsd:annotation>
<xsd:restriction base="xsd:token">
<xsd:enumeration value="AUTO"/>
<xsd:enumeration value="CALLBACK"/>
<xsd:enumeration value="NONE"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>

View File

@ -23,6 +23,14 @@ plugins {
dependencyResolutionManagement { dependencyResolutionManagement {
repositories { repositories {
mavenCentral() mavenCentral()
// Needed for the RC versions of Jakarta Persistence
maven {
url "https://jakarta.oss.sonatype.org/content/repositories/releases/"
}
// Needed for the SNAPSHOT versions of Jakarta Persistence
maven {
url "https://jakarta.oss.sonatype.org/content/repositories/snapshots/"
}
//Allow loading additional dependencies from a local path; //Allow loading additional dependencies from a local path;
//useful to load JDBC drivers which can not be distributed in public. //useful to load JDBC drivers which can not be distributed in public.