HHH-17076 - Numeric literal typing
https://hibernate.atlassian.net/browse/HHH-17076
This commit is contained in:
parent
c7ed34d159
commit
ab4ac5a64e
|
@ -62,9 +62,9 @@ INTEGER_LITERAL : INTEGER_NUMBER ('_' INTEGER_NUMBER)*;
|
||||||
|
|
||||||
LONG_LITERAL : INTEGER_NUMBER ('_' INTEGER_NUMBER)* LONG_SUFFIX;
|
LONG_LITERAL : INTEGER_NUMBER ('_' INTEGER_NUMBER)* LONG_SUFFIX;
|
||||||
|
|
||||||
FLOAT_LITERAL : FLOATING_POINT_NUMBER FLOAT_SUFFIX?;
|
FLOAT_LITERAL : FLOATING_POINT_NUMBER FLOAT_SUFFIX;
|
||||||
|
|
||||||
DOUBLE_LITERAL : FLOATING_POINT_NUMBER DOUBLE_SUFFIX;
|
DOUBLE_LITERAL : FLOATING_POINT_NUMBER DOUBLE_SUFFIX?;
|
||||||
|
|
||||||
BIG_INTEGER_LITERAL : INTEGER_NUMBER BIG_INTEGER_SUFFIX;
|
BIG_INTEGER_LITERAL : INTEGER_NUMBER BIG_INTEGER_SUFFIX;
|
||||||
|
|
||||||
|
|
|
@ -611,6 +611,7 @@ parameterOrIntegerLiteral
|
||||||
parameterOrNumberLiteral
|
parameterOrNumberLiteral
|
||||||
: parameter
|
: parameter
|
||||||
| INTEGER_LITERAL
|
| INTEGER_LITERAL
|
||||||
|
| LONG_LITERAL
|
||||||
| FLOAT_LITERAL
|
| FLOAT_LITERAL
|
||||||
| DOUBLE_LITERAL
|
| DOUBLE_LITERAL
|
||||||
;
|
;
|
||||||
|
@ -1006,7 +1007,7 @@ month: INTEGER_LITERAL;
|
||||||
day: INTEGER_LITERAL;
|
day: INTEGER_LITERAL;
|
||||||
hour: INTEGER_LITERAL;
|
hour: INTEGER_LITERAL;
|
||||||
minute: INTEGER_LITERAL;
|
minute: INTEGER_LITERAL;
|
||||||
second: INTEGER_LITERAL | FLOAT_LITERAL;
|
second: INTEGER_LITERAL | DOUBLE_LITERAL;
|
||||||
zoneId
|
zoneId
|
||||||
: IDENTIFIER (SLASH IDENTIFIER)?
|
: IDENTIFIER (SLASH IDENTIFIER)?
|
||||||
| STRING_LITERAL;
|
| STRING_LITERAL;
|
||||||
|
|
|
@ -145,6 +145,7 @@ import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmExtractUnit;
|
import org.hibernate.query.sqm.tree.expression.SqmExtractUnit;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmFormat;
|
import org.hibernate.query.sqm.tree.expression.SqmFormat;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmFunction;
|
import org.hibernate.query.sqm.tree.expression.SqmFunction;
|
||||||
|
import org.hibernate.query.sqm.tree.expression.SqmHqlNumericLiteral;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmLiteral;
|
import org.hibernate.query.sqm.tree.expression.SqmLiteral;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
|
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmLiteralNull;
|
import org.hibernate.query.sqm.tree.expression.SqmLiteralNull;
|
||||||
|
@ -1791,7 +1792,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
||||||
@Override
|
@Override
|
||||||
public SqmExpression<?> visitParameterOrIntegerLiteral(HqlParser.ParameterOrIntegerLiteralContext ctx) {
|
public SqmExpression<?> visitParameterOrIntegerLiteral(HqlParser.ParameterOrIntegerLiteralContext ctx) {
|
||||||
if ( ctx.INTEGER_LITERAL() != null ) {
|
if ( ctx.INTEGER_LITERAL() != null ) {
|
||||||
return integralLiteral( ctx.INTEGER_LITERAL().getText() );
|
return integerLiteral( ctx.INTEGER_LITERAL().getText() );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return (SqmExpression<?>) ctx.parameter().accept( this );
|
return (SqmExpression<?>) ctx.parameter().accept( this );
|
||||||
|
@ -1801,10 +1802,10 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
||||||
@Override
|
@Override
|
||||||
public SqmExpression<?> visitParameterOrNumberLiteral(HqlParser.ParameterOrNumberLiteralContext ctx) {
|
public SqmExpression<?> visitParameterOrNumberLiteral(HqlParser.ParameterOrNumberLiteralContext ctx) {
|
||||||
if ( ctx.INTEGER_LITERAL() != null ) {
|
if ( ctx.INTEGER_LITERAL() != null ) {
|
||||||
return integralLiteral( ctx.INTEGER_LITERAL().getText() );
|
return integerLiteral( ctx.INTEGER_LITERAL().getText() );
|
||||||
}
|
}
|
||||||
if ( ctx.FLOAT_LITERAL() != null ) {
|
if ( ctx.FLOAT_LITERAL() != null ) {
|
||||||
return numericLiteral( ctx.FLOAT_LITERAL().getText() );
|
return floatLiteral( ctx.FLOAT_LITERAL().getText() );
|
||||||
}
|
}
|
||||||
if ( ctx.DOUBLE_LITERAL() != null ) {
|
if ( ctx.DOUBLE_LITERAL() != null ) {
|
||||||
return doubleLiteral( ctx.DOUBLE_LITERAL().getText() );
|
return doubleLiteral( ctx.DOUBLE_LITERAL().getText() );
|
||||||
|
@ -1816,9 +1817,9 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
||||||
if ( firstChild instanceof TerminalNode ) {
|
if ( firstChild instanceof TerminalNode ) {
|
||||||
switch ( ( (TerminalNode) firstChild ).getSymbol().getType() ) {
|
switch ( ( (TerminalNode) firstChild ).getSymbol().getType() ) {
|
||||||
case HqlParser.INTEGER_LITERAL:
|
case HqlParser.INTEGER_LITERAL:
|
||||||
return integralLiteral( firstChild.getText() );
|
return integerLiteral( firstChild.getText() );
|
||||||
case HqlParser.FLOAT_LITERAL:
|
case HqlParser.FLOAT_LITERAL:
|
||||||
return numericLiteral( firstChild.getText() );
|
return floatLiteral( firstChild.getText() );
|
||||||
case HqlParser.DOUBLE_LITERAL:
|
case HqlParser.DOUBLE_LITERAL:
|
||||||
return doubleLiteral( firstChild.getText() );
|
return doubleLiteral( firstChild.getText() );
|
||||||
default:
|
default:
|
||||||
|
@ -3224,7 +3225,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
||||||
}
|
}
|
||||||
switch ( node.getSymbol().getType() ) {
|
switch ( node.getSymbol().getType() ) {
|
||||||
case HqlParser.INTEGER_LITERAL:
|
case HqlParser.INTEGER_LITERAL:
|
||||||
return integralLiteral( text );
|
return integerLiteral( text );
|
||||||
case HqlParser.LONG_LITERAL:
|
case HqlParser.LONG_LITERAL:
|
||||||
return longLiteral( text );
|
return longLiteral( text );
|
||||||
case HqlParser.BIG_INTEGER_LITERAL:
|
case HqlParser.BIG_INTEGER_LITERAL:
|
||||||
|
@ -3232,7 +3233,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
||||||
case HqlParser.HEX_LITERAL:
|
case HqlParser.HEX_LITERAL:
|
||||||
return hexLiteral( text );
|
return hexLiteral( text );
|
||||||
case HqlParser.FLOAT_LITERAL:
|
case HqlParser.FLOAT_LITERAL:
|
||||||
return numericLiteral( text );
|
return floatLiteral( text );
|
||||||
case HqlParser.DOUBLE_LITERAL:
|
case HqlParser.DOUBLE_LITERAL:
|
||||||
return doubleLiteral( text );
|
return doubleLiteral( text );
|
||||||
case HqlParser.BIG_DECIMAL_LITERAL:
|
case HqlParser.BIG_DECIMAL_LITERAL:
|
||||||
|
@ -3281,7 +3282,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
||||||
case HqlParser.JAVA_STRING_LITERAL:
|
case HqlParser.JAVA_STRING_LITERAL:
|
||||||
return javaStringLiteral( node.getText() );
|
return javaStringLiteral( node.getText() );
|
||||||
case HqlParser.INTEGER_LITERAL:
|
case HqlParser.INTEGER_LITERAL:
|
||||||
return integralLiteral( node.getText() );
|
return integerLiteral( node.getText() );
|
||||||
case HqlParser.LONG_LITERAL:
|
case HqlParser.LONG_LITERAL:
|
||||||
return longLiteral( node.getText() );
|
return longLiteral( node.getText() );
|
||||||
case HqlParser.BIG_INTEGER_LITERAL:
|
case HqlParser.BIG_INTEGER_LITERAL:
|
||||||
|
@ -3289,7 +3290,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
||||||
case HqlParser.HEX_LITERAL:
|
case HqlParser.HEX_LITERAL:
|
||||||
return hexLiteral( node.getText() );
|
return hexLiteral( node.getText() );
|
||||||
case HqlParser.FLOAT_LITERAL:
|
case HqlParser.FLOAT_LITERAL:
|
||||||
return numericLiteral( node.getText() );
|
return floatLiteral( node.getText() );
|
||||||
case HqlParser.DOUBLE_LITERAL:
|
case HqlParser.DOUBLE_LITERAL:
|
||||||
return doubleLiteral( node.getText() );
|
return doubleLiteral( node.getText() );
|
||||||
case HqlParser.BIG_DECIMAL_LITERAL:
|
case HqlParser.BIG_DECIMAL_LITERAL:
|
||||||
|
@ -3621,235 +3622,67 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SqmLiteral<? extends Number> integralLiteral(String text) {
|
private SqmHqlNumericLiteral<Integer> integerLiteral(String text) {
|
||||||
final String integralText = text.replace( "_", "" );
|
return new SqmHqlNumericLiteral<>(
|
||||||
final int decimalNumbers = integralText.length() - ( integralText.charAt( 0 ) == '-' ? 1 : 0 );
|
text.replace( "_", "" ),
|
||||||
if ( decimalNumbers > 19 ) {
|
integerDomainType,
|
||||||
try {
|
|
||||||
final BigInteger value = new BigInteger( integralText );
|
|
||||||
return new SqmLiteral<>(
|
|
||||||
value,
|
|
||||||
resolveExpressibleTypeBasic( BigInteger.class ),
|
|
||||||
creationContext.getNodeBuilder()
|
creationContext.getNodeBuilder()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
catch (NumberFormatException e) {
|
|
||||||
throw new LiteralNumberFormatException(
|
private SqmHqlNumericLiteral<Long> longLiteral(String text) {
|
||||||
"Unable to convert sqm literal [" + text + "] to BigInteger",
|
assert text.endsWith( "l" ) || text.endsWith( "L" );
|
||||||
e
|
return new SqmHqlNumericLiteral<>(
|
||||||
);
|
text.substring( 0, text.length() - 1 ).replace( "_", "" ),
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ( decimalNumbers > 10 ) {
|
|
||||||
try {
|
|
||||||
final Long value = Long.valueOf( integralText );
|
|
||||||
return new SqmLiteral<>(
|
|
||||||
value,
|
|
||||||
resolveExpressibleTypeBasic( Long.class ),
|
resolveExpressibleTypeBasic( Long.class ),
|
||||||
creationContext.getNodeBuilder()
|
creationContext.getNodeBuilder()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
catch (NumberFormatException e) {
|
|
||||||
try {
|
private SqmHqlNumericLiteral<BigInteger> bigIntegerLiteral(String text) {
|
||||||
final BigInteger value = new BigInteger( integralText );
|
assert text.endsWith( "bi" ) || text.endsWith( "BI" );
|
||||||
return new SqmLiteral<>(
|
return new SqmHqlNumericLiteral<>(
|
||||||
value,
|
text.substring( 0, text.length() - 2 ).replace( "_", "" ),
|
||||||
resolveExpressibleTypeBasic( BigInteger.class ),
|
resolveExpressibleTypeBasic( BigInteger.class ),
|
||||||
creationContext.getNodeBuilder()
|
creationContext.getNodeBuilder()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
catch (NumberFormatException e2) {
|
|
||||||
final LiteralNumberFormatException exception = new LiteralNumberFormatException(
|
|
||||||
"Unable to convert sqm literal [" + text + "] to Long or BigInteger",
|
|
||||||
e
|
|
||||||
);
|
|
||||||
exception.addSuppressed( e );
|
|
||||||
exception.addSuppressed( e2 );
|
|
||||||
throw exception;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
final Integer value = Integer.valueOf( integralText );
|
|
||||||
return new SqmLiteral<>(
|
|
||||||
value,
|
|
||||||
resolveExpressibleTypeBasic( Integer.class ),
|
|
||||||
creationContext.getNodeBuilder()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
catch (NumberFormatException e) {
|
|
||||||
try {
|
|
||||||
final Long value = Long.valueOf( integralText );
|
|
||||||
return new SqmLiteral<>(
|
|
||||||
value,
|
|
||||||
resolveExpressibleTypeBasic( Long.class ),
|
|
||||||
creationContext.getNodeBuilder()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
catch (NumberFormatException e2) {
|
|
||||||
try {
|
|
||||||
final BigInteger value = new BigInteger( integralText );
|
|
||||||
return new SqmLiteral<>(
|
|
||||||
value,
|
|
||||||
resolveExpressibleTypeBasic( BigInteger.class ),
|
|
||||||
creationContext.getNodeBuilder()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
catch (NumberFormatException e3) {
|
|
||||||
final LiteralNumberFormatException exception = new LiteralNumberFormatException(
|
|
||||||
"Unable to convert sqm literal [" + text + "] to Integer, Long or BigInteger",
|
|
||||||
e
|
|
||||||
);
|
|
||||||
exception.addSuppressed( e );
|
|
||||||
exception.addSuppressed( e2 );
|
|
||||||
exception.addSuppressed( e3 );
|
|
||||||
throw exception;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private SqmLiteral<Long> longLiteral(String text) {
|
private SqmHqlNumericLiteral<? extends Number> floatLiteral(String text) {
|
||||||
final String originalText = text;
|
assert text.endsWith( "f" ) || text.endsWith( "F" );
|
||||||
try {
|
return new SqmHqlNumericLiteral<>(
|
||||||
if ( text.endsWith( "l" ) || text.endsWith( "L" ) ) {
|
text.substring( 0, text.length() - 1 ).replace( "_", "" ),
|
||||||
text = text.substring( 0, text.length() - 1 ).replace("_", "");
|
|
||||||
}
|
|
||||||
final Long value = Long.valueOf( text );
|
|
||||||
return new SqmLiteral<>(
|
|
||||||
value,
|
|
||||||
resolveExpressibleTypeBasic( Long.class ),
|
|
||||||
creationContext.getNodeBuilder()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
catch (NumberFormatException e) {
|
|
||||||
throw new LiteralNumberFormatException(
|
|
||||||
"Unable to convert sqm literal [" + originalText + "] to Long",
|
|
||||||
e
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private SqmLiteral<? extends Number> hexLiteral(String text) {
|
|
||||||
final String originalText = text;
|
|
||||||
text = text.substring( 2 );
|
|
||||||
try {
|
|
||||||
if ( text.endsWith( "l" ) || text.endsWith( "L" ) ) {
|
|
||||||
text = text.substring( 0, text.length() - 1 );
|
|
||||||
final long value = Long.parseUnsignedLong( text, 16 );
|
|
||||||
return new SqmLiteral<>(
|
|
||||||
value,
|
|
||||||
resolveExpressibleTypeBasic( Long.class ),
|
|
||||||
creationContext.getNodeBuilder()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
final int value = Integer.parseUnsignedInt( text, 16 );
|
|
||||||
return new SqmLiteral<>(
|
|
||||||
value,
|
|
||||||
resolveExpressibleTypeBasic( Integer.class ),
|
|
||||||
creationContext.getNodeBuilder()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (NumberFormatException e) {
|
|
||||||
throw new LiteralNumberFormatException(
|
|
||||||
"Unable to convert sqm literal [" + originalText + "]",
|
|
||||||
e
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private SqmLiteral<BigInteger> bigIntegerLiteral(String text) {
|
|
||||||
final String originalText = text;
|
|
||||||
try {
|
|
||||||
if ( text.endsWith( "bi" ) || text.endsWith( "BI" ) ) {
|
|
||||||
text = text.substring( 0, text.length() - 2 );
|
|
||||||
}
|
|
||||||
return new SqmLiteral<>(
|
|
||||||
new BigInteger( text ),
|
|
||||||
resolveExpressibleTypeBasic( BigInteger.class ),
|
|
||||||
creationContext.getNodeBuilder()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
catch (NumberFormatException e) {
|
|
||||||
throw new LiteralNumberFormatException(
|
|
||||||
"Unable to convert sqm literal [" + originalText + "] to BigInteger",
|
|
||||||
e
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private SqmLiteral<? extends Number> numericLiteral(String text) {
|
|
||||||
final String numericText = text.replace( "_", "" );
|
|
||||||
final char lastChar = text.charAt( text.length() - 1 );
|
|
||||||
if ( lastChar == 'f' || lastChar == 'F' ) {
|
|
||||||
try {
|
|
||||||
return new SqmLiteral<>(
|
|
||||||
Float.valueOf( numericText ),
|
|
||||||
resolveExpressibleTypeBasic( Float.class ),
|
resolveExpressibleTypeBasic( Float.class ),
|
||||||
creationContext.getNodeBuilder()
|
creationContext.getNodeBuilder()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
catch (NumberFormatException e) {
|
|
||||||
throw new LiteralNumberFormatException(
|
|
||||||
"Unable to convert sqm literal [" + text + "] to Float",
|
|
||||||
e
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Treat numeric literals without a type suffix like BigDecimal
|
|
||||||
// according to the JPA spec 4.6.1 and SQL spec 5.3
|
|
||||||
try {
|
|
||||||
return new SqmLiteral<>(
|
|
||||||
new BigDecimal( numericText ),
|
|
||||||
resolveExpressibleTypeBasic( BigDecimal.class ),
|
|
||||||
creationContext.getNodeBuilder()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
catch (NumberFormatException e) {
|
|
||||||
throw new LiteralNumberFormatException(
|
|
||||||
"Unable to convert sqm literal [" + text + "] to BigDecimal",
|
|
||||||
e
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private SqmLiteral<Double> doubleLiteral(String text) {
|
private SqmHqlNumericLiteral<Double> doubleLiteral(String text) {
|
||||||
try {
|
if ( text.endsWith( "d" ) || text.endsWith( "D" ) ) {
|
||||||
return new SqmLiteral<>(
|
text = text.substring( 0, text.length() - 1 );
|
||||||
Double.valueOf( text ),
|
}
|
||||||
|
return new SqmHqlNumericLiteral<>(
|
||||||
|
text.replace( "_", "" ),
|
||||||
resolveExpressibleTypeBasic( Double.class ),
|
resolveExpressibleTypeBasic( Double.class ),
|
||||||
creationContext.getNodeBuilder()
|
creationContext.getNodeBuilder()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
catch (NumberFormatException e) {
|
|
||||||
throw new LiteralNumberFormatException(
|
|
||||||
"Unable to convert sqm literal [" + text + "] to Double",
|
|
||||||
e
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private SqmLiteral<BigDecimal> bigDecimalLiteral(String text) {
|
private SqmHqlNumericLiteral<BigDecimal> bigDecimalLiteral(String text) {
|
||||||
final String originalText = text;
|
assert text.endsWith( "bd" ) || text.endsWith( "BD" );
|
||||||
try {
|
return new SqmHqlNumericLiteral<>(
|
||||||
if ( text.endsWith( "bd" ) || text.endsWith( "BD" ) ) {
|
text.substring( 0, text.length() - 2 ).replace( "_", "" ),
|
||||||
text = text.substring( 0, text.length() - 2 );
|
|
||||||
}
|
|
||||||
return new SqmLiteral<>(
|
|
||||||
new BigDecimal( text ),
|
|
||||||
resolveExpressibleTypeBasic( BigDecimal.class ),
|
resolveExpressibleTypeBasic( BigDecimal.class ),
|
||||||
creationContext.getNodeBuilder()
|
creationContext.getNodeBuilder()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
catch (NumberFormatException e) {
|
|
||||||
throw new LiteralNumberFormatException(
|
private SqmHqlNumericLiteral<? extends Number> hexLiteral(String text) {
|
||||||
"Unable to convert sqm literal [" + originalText + "] to BigDecimal",
|
if ( text.endsWith( "l" ) || text.endsWith( "L" ) ) {
|
||||||
e
|
return longLiteral( text );
|
||||||
);
|
}
|
||||||
|
else {
|
||||||
|
return integerLiteral( text );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,7 @@ import org.hibernate.query.TypedParameterValue;
|
||||||
import org.hibernate.query.criteria.JpaExpression;
|
import org.hibernate.query.criteria.JpaExpression;
|
||||||
import org.hibernate.query.internal.QueryOptionsImpl;
|
import org.hibernate.query.internal.QueryOptionsImpl;
|
||||||
import org.hibernate.query.sqm.SqmExpressible;
|
import org.hibernate.query.sqm.SqmExpressible;
|
||||||
|
import org.hibernate.query.sqm.tree.expression.SqmHqlNumericLiteral;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmLiteral;
|
import org.hibernate.query.sqm.tree.expression.SqmLiteral;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmParameter;
|
import org.hibernate.query.sqm.tree.expression.SqmParameter;
|
||||||
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
|
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
|
||||||
|
@ -132,6 +133,10 @@ public abstract class AbstractCommonQueryContract implements CommonQueryContract
|
||||||
if ( expression instanceof SqmLiteral<?> ) {
|
if ( expression instanceof SqmLiteral<?> ) {
|
||||||
fetchValue = ( (SqmLiteral<Number>) expression ).getLiteralValue();
|
fetchValue = ( (SqmLiteral<Number>) expression ).getLiteralValue();
|
||||||
}
|
}
|
||||||
|
else if ( expression instanceof SqmHqlNumericLiteral ) {
|
||||||
|
final SqmHqlNumericLiteral<Number> hqlNumericLiteral = (SqmHqlNumericLiteral<Number>) expression;
|
||||||
|
fetchValue = hqlNumericLiteral.getTypeCategory().parseLiteralValue( hqlNumericLiteral.getLiteralValue() );
|
||||||
|
}
|
||||||
else if ( expression instanceof SqmParameter<?> ) {
|
else if ( expression instanceof SqmParameter<?> ) {
|
||||||
fetchValue = getParameterValue( (Parameter<Number>) expression );
|
fetchValue = getParameterValue( (Parameter<Number>) expression );
|
||||||
if ( fetchValue == null ) {
|
if ( fetchValue == null ) {
|
||||||
|
|
|
@ -64,6 +64,7 @@ import org.hibernate.query.sqm.tree.expression.SqmExtractUnit;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmFieldLiteral;
|
import org.hibernate.query.sqm.tree.expression.SqmFieldLiteral;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmFormat;
|
import org.hibernate.query.sqm.tree.expression.SqmFormat;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmFunction;
|
import org.hibernate.query.sqm.tree.expression.SqmFunction;
|
||||||
|
import org.hibernate.query.sqm.tree.expression.SqmHqlNumericLiteral;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmLiteral;
|
import org.hibernate.query.sqm.tree.expression.SqmLiteral;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
|
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmModifiedSubQueryExpression;
|
import org.hibernate.query.sqm.tree.expression.SqmModifiedSubQueryExpression;
|
||||||
|
@ -283,6 +284,8 @@ public interface SemanticQueryWalker<T> {
|
||||||
|
|
||||||
T visitFieldLiteral(SqmFieldLiteral<?> sqmFieldLiteral);
|
T visitFieldLiteral(SqmFieldLiteral<?> sqmFieldLiteral);
|
||||||
|
|
||||||
|
<N extends Number> T visitHqlNumericLiteral(SqmHqlNumericLiteral<N> numericLiteral);
|
||||||
|
|
||||||
T visitTuple(SqmTuple<?> sqmTuple);
|
T visitTuple(SqmTuple<?> sqmTuple);
|
||||||
|
|
||||||
T visitCollation(SqmCollation sqmCollate);
|
T visitCollation(SqmCollation sqmCollate);
|
||||||
|
|
|
@ -53,6 +53,7 @@ import org.hibernate.query.sqm.tree.expression.SqmExtractUnit;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmFieldLiteral;
|
import org.hibernate.query.sqm.tree.expression.SqmFieldLiteral;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmFormat;
|
import org.hibernate.query.sqm.tree.expression.SqmFormat;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmFunction;
|
import org.hibernate.query.sqm.tree.expression.SqmFunction;
|
||||||
|
import org.hibernate.query.sqm.tree.expression.SqmHqlNumericLiteral;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmLiteral;
|
import org.hibernate.query.sqm.tree.expression.SqmLiteral;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
|
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmModifiedSubQueryExpression;
|
import org.hibernate.query.sqm.tree.expression.SqmModifiedSubQueryExpression;
|
||||||
|
@ -1140,6 +1141,11 @@ public class SqmTreePrinter implements SemanticQueryWalker<Object> {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <N extends Number> Object visitHqlNumericLiteral(SqmHqlNumericLiteral<N> numericLiteral) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object visitFullyQualifiedClass(Class namedClass) {
|
public Object visitFullyQualifiedClass(Class namedClass) {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -54,6 +54,7 @@ import org.hibernate.query.sqm.tree.expression.SqmExtractUnit;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmFieldLiteral;
|
import org.hibernate.query.sqm.tree.expression.SqmFieldLiteral;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmFormat;
|
import org.hibernate.query.sqm.tree.expression.SqmFormat;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmFunction;
|
import org.hibernate.query.sqm.tree.expression.SqmFunction;
|
||||||
|
import org.hibernate.query.sqm.tree.expression.SqmHqlNumericLiteral;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmLiteral;
|
import org.hibernate.query.sqm.tree.expression.SqmLiteral;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
|
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmModifiedSubQueryExpression;
|
import org.hibernate.query.sqm.tree.expression.SqmModifiedSubQueryExpression;
|
||||||
|
@ -837,6 +838,11 @@ public abstract class BaseSemanticQueryWalker implements SemanticQueryWalker<Obj
|
||||||
return literal;
|
return literal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <N extends Number> Object visitHqlNumericLiteral(SqmHqlNumericLiteral<N> numericLiteral) {
|
||||||
|
return numericLiteral;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object visitTuple(SqmTuple<?> sqmTuple) {
|
public Object visitTuple(SqmTuple<?> sqmTuple) {
|
||||||
sqmTuple.getGroupedExpressions().forEach( e -> e.accept( this ) );
|
sqmTuple.getGroupedExpressions().forEach( e -> e.accept( this ) );
|
||||||
|
|
|
@ -216,6 +216,7 @@ import org.hibernate.query.sqm.tree.expression.SqmExtractUnit;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmFieldLiteral;
|
import org.hibernate.query.sqm.tree.expression.SqmFieldLiteral;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmFormat;
|
import org.hibernate.query.sqm.tree.expression.SqmFormat;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmFunction;
|
import org.hibernate.query.sqm.tree.expression.SqmFunction;
|
||||||
|
import org.hibernate.query.sqm.tree.expression.SqmHqlNumericLiteral;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmJpaCriteriaParameterWrapper;
|
import org.hibernate.query.sqm.tree.expression.SqmJpaCriteriaParameterWrapper;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmLiteral;
|
import org.hibernate.query.sqm.tree.expression.SqmLiteral;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
|
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
|
||||||
|
@ -338,6 +339,7 @@ import org.hibernate.sql.ast.tree.expression.Star;
|
||||||
import org.hibernate.sql.ast.tree.expression.Summarization;
|
import org.hibernate.sql.ast.tree.expression.Summarization;
|
||||||
import org.hibernate.sql.ast.tree.expression.TrimSpecification;
|
import org.hibernate.sql.ast.tree.expression.TrimSpecification;
|
||||||
import org.hibernate.sql.ast.tree.expression.UnaryOperation;
|
import org.hibernate.sql.ast.tree.expression.UnaryOperation;
|
||||||
|
import org.hibernate.sql.ast.tree.expression.UnparsedNumericLiteral;
|
||||||
import org.hibernate.sql.ast.tree.from.CorrelatedPluralTableGroup;
|
import org.hibernate.sql.ast.tree.from.CorrelatedPluralTableGroup;
|
||||||
import org.hibernate.sql.ast.tree.from.CorrelatedTableGroup;
|
import org.hibernate.sql.ast.tree.from.CorrelatedTableGroup;
|
||||||
import org.hibernate.sql.ast.tree.from.FromClause;
|
import org.hibernate.sql.ast.tree.from.FromClause;
|
||||||
|
@ -5506,6 +5508,64 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <N extends Number> Expression visitHqlNumericLiteral(SqmHqlNumericLiteral<N> numericLiteral) {
|
||||||
|
final BasicValuedMapping inferredExpressible = (BasicValuedMapping) getInferredValueMapping();
|
||||||
|
final BasicValuedMapping expressible;
|
||||||
|
if ( inferredExpressible == null ) {
|
||||||
|
expressible = (BasicValuedMapping) determineCurrentExpressible( numericLiteral );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
expressible = inferredExpressible;
|
||||||
|
}
|
||||||
|
|
||||||
|
final JdbcMapping jdbcMapping = expressible.getJdbcMapping();
|
||||||
|
if ( jdbcMapping.getValueConverter() != null ) {
|
||||||
|
// special case where we need to parse the value in order to apply the conversion
|
||||||
|
return handleConvertedUnparsedNumericLiteral( numericLiteral, expressible );
|
||||||
|
}
|
||||||
|
|
||||||
|
return new UnparsedNumericLiteral<>( numericLiteral.getLiteralValue(), jdbcMapping );
|
||||||
|
}
|
||||||
|
|
||||||
|
private <N extends Number> Expression handleConvertedUnparsedNumericLiteral(
|
||||||
|
SqmHqlNumericLiteral<N> numericLiteral,
|
||||||
|
BasicValuedMapping expressible) {
|
||||||
|
//noinspection rawtypes
|
||||||
|
final BasicValueConverter valueConverter = expressible.getJdbcMapping().getValueConverter();
|
||||||
|
assert valueConverter != null;
|
||||||
|
|
||||||
|
final Number parsedValue = numericLiteral.getTypeCategory().parseLiteralValue( numericLiteral.getLiteralValue() );
|
||||||
|
final Object sqlLiteralValue;
|
||||||
|
if ( valueConverter.getDomainJavaType().isInstance( parsedValue ) ) {
|
||||||
|
//noinspection unchecked
|
||||||
|
sqlLiteralValue = valueConverter.toRelationalValue( parsedValue );
|
||||||
|
}
|
||||||
|
else if ( valueConverter.getRelationalJavaType().isInstance( parsedValue ) ) {
|
||||||
|
sqlLiteralValue = parsedValue;
|
||||||
|
}
|
||||||
|
else if ( Number.class.isAssignableFrom( valueConverter.getRelationalJavaType().getJavaTypeClass() ) ) {
|
||||||
|
//noinspection unchecked
|
||||||
|
sqlLiteralValue = valueConverter.getRelationalJavaType().coerce(
|
||||||
|
parsedValue,
|
||||||
|
creationContext.getSessionFactory()::getTypeConfiguration
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new SemanticException(
|
||||||
|
String.format(
|
||||||
|
Locale.ROOT,
|
||||||
|
"Literal type '%s' did not match domain type '%s' nor converted type '%s'",
|
||||||
|
parsedValue.getClass(),
|
||||||
|
valueConverter.getDomainJavaType().getJavaTypeClass().getName(),
|
||||||
|
valueConverter.getRelationalJavaType().getJavaTypeClass().getName()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new QueryLiteral<>( sqlLiteralValue, expressible );
|
||||||
|
}
|
||||||
|
|
||||||
private MappingModelExpressible<?> getKeyExpressible(JdbcMappingContainer mappingModelExpressible) {
|
private MappingModelExpressible<?> getKeyExpressible(JdbcMappingContainer mappingModelExpressible) {
|
||||||
if ( mappingModelExpressible instanceof EntityAssociationMapping ) {
|
if ( mappingModelExpressible instanceof EntityAssociationMapping ) {
|
||||||
return ( (EntityAssociationMapping) mappingModelExpressible ).getKeyTargetMatchPart();
|
return ( (EntityAssociationMapping) mappingModelExpressible ).getKeyTargetMatchPart();
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* 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.query.sqm.tree.expression;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public enum NumericTypeCategory {
|
||||||
|
INTEGER,
|
||||||
|
LONG,
|
||||||
|
BIG_INTEGER,
|
||||||
|
DOUBLE,
|
||||||
|
FLOAT,
|
||||||
|
BIG_DECIMAL;
|
||||||
|
|
||||||
|
public <N extends Number> N parseLiteralValue(String value) {
|
||||||
|
switch ( this ) {
|
||||||
|
case INTEGER: {
|
||||||
|
//noinspection unchecked
|
||||||
|
return (N) Integer.valueOf( value );
|
||||||
|
}
|
||||||
|
case LONG: {
|
||||||
|
//noinspection unchecked
|
||||||
|
return (N) Long.valueOf( value );
|
||||||
|
}
|
||||||
|
case BIG_INTEGER: {
|
||||||
|
//noinspection unchecked
|
||||||
|
return (N) new BigInteger( value );
|
||||||
|
}
|
||||||
|
case DOUBLE: {
|
||||||
|
//noinspection unchecked
|
||||||
|
return (N) Double.valueOf( value );
|
||||||
|
}
|
||||||
|
case FLOAT: {
|
||||||
|
//noinspection unchecked
|
||||||
|
return (N) Float.valueOf( value );
|
||||||
|
}
|
||||||
|
case BIG_DECIMAL: {
|
||||||
|
//noinspection unchecked
|
||||||
|
return (N) new BigDecimal( value );
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
String.format(
|
||||||
|
Locale.ROOT,
|
||||||
|
"Unable to parse numeric literal value `%s` - %s",
|
||||||
|
value,
|
||||||
|
name()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,165 @@
|
||||||
|
/*
|
||||||
|
* 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.query.sqm.tree.expression;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import org.hibernate.HibernateException;
|
||||||
|
import org.hibernate.metamodel.model.domain.BasicDomainType;
|
||||||
|
import org.hibernate.query.sqm.NodeBuilder;
|
||||||
|
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||||
|
import org.hibernate.query.sqm.SqmExpressible;
|
||||||
|
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||||
|
import org.hibernate.type.descriptor.java.JavaType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to model numeric literals found in HQL queries.
|
||||||
|
* <p/>
|
||||||
|
* Used instead of {@link SqmLiteral} which would require parsing the
|
||||||
|
* literal value to the specified number type to avoid loss of precision
|
||||||
|
* due to Float and Double being non-exact types.
|
||||||
|
*
|
||||||
|
* @apiNote Only used for HQL literals because we do not have this problem
|
||||||
|
* with criteria queries where the value given us by user would already be
|
||||||
|
* typed.
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class SqmHqlNumericLiteral<N extends Number> extends AbstractSqmExpression<N> {
|
||||||
|
private final String literalValue;
|
||||||
|
private final NumericTypeCategory typeCategory;
|
||||||
|
|
||||||
|
public SqmHqlNumericLiteral(
|
||||||
|
String literalValue,
|
||||||
|
BasicDomainType<N> type,
|
||||||
|
NodeBuilder criteriaBuilder) {
|
||||||
|
this( literalValue, interpretCategory( literalValue, type ), type, criteriaBuilder );
|
||||||
|
}
|
||||||
|
|
||||||
|
public SqmHqlNumericLiteral(
|
||||||
|
String literalValue,
|
||||||
|
NumericTypeCategory typeCategory,
|
||||||
|
BasicDomainType<N> type,
|
||||||
|
NodeBuilder criteriaBuilder) {
|
||||||
|
super( type, criteriaBuilder );
|
||||||
|
this.literalValue = literalValue;
|
||||||
|
this.typeCategory = typeCategory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLiteralValue() {
|
||||||
|
return literalValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NumericTypeCategory getTypeCategory() {
|
||||||
|
return typeCategory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BasicDomainType<N> getNodeType() {
|
||||||
|
return (BasicDomainType<N>) super.getNodeType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BasicDomainType<N> getExpressible() {
|
||||||
|
return getNodeType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <X> X accept(SemanticQueryWalker<X> walker) {
|
||||||
|
return walker.visitHqlNumericLiteral( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void appendHqlString(StringBuilder sb) {
|
||||||
|
sb.append( literalValue );
|
||||||
|
|
||||||
|
switch ( typeCategory ) {
|
||||||
|
case BIG_DECIMAL: {
|
||||||
|
sb.append( "bd" );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FLOAT: {
|
||||||
|
sb.append( "f" );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case BIG_INTEGER: {
|
||||||
|
sb.append( "bi" );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LONG: {
|
||||||
|
sb.append( "l" );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
// nothing to do for double/integer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String asLoggableText() {
|
||||||
|
final StringBuilder stringBuilder = new StringBuilder();
|
||||||
|
appendHqlString( stringBuilder );
|
||||||
|
return stringBuilder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqmHqlNumericLiteral<N> copy(SqmCopyContext context) {
|
||||||
|
return new SqmHqlNumericLiteral<>( literalValue, typeCategory, getExpressible(), nodeBuilder() );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <N extends Number> NumericTypeCategory interpretCategory(String literalValue, SqmExpressible<N> type) {
|
||||||
|
assert type != null;
|
||||||
|
|
||||||
|
final JavaType<N> javaTypeDescriptor = type.getExpressibleJavaType();
|
||||||
|
assert javaTypeDescriptor != null;
|
||||||
|
|
||||||
|
final Class<N> javaTypeClass = javaTypeDescriptor.getJavaTypeClass();
|
||||||
|
|
||||||
|
if ( BigDecimal.class.equals( javaTypeClass ) ) {
|
||||||
|
return NumericTypeCategory.BIG_DECIMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( Double.class.equals( javaTypeClass ) ) {
|
||||||
|
return NumericTypeCategory.DOUBLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( Float.class.equals( javaTypeClass ) ) {
|
||||||
|
return NumericTypeCategory.FLOAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( BigInteger.class.equals( javaTypeClass ) ) {
|
||||||
|
return NumericTypeCategory.BIG_INTEGER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( Long.class.equals( javaTypeClass ) ) {
|
||||||
|
return NumericTypeCategory.LONG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( Short.class.equals( javaTypeClass )
|
||||||
|
|| Integer.class.equals( javaTypeClass ) ) {
|
||||||
|
return NumericTypeCategory.INTEGER;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new TypeException( literalValue, javaTypeClass );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class TypeException extends HibernateException {
|
||||||
|
public TypeException(String literalValue, Class<?> javaType) {
|
||||||
|
super(
|
||||||
|
String.format(
|
||||||
|
Locale.ROOT,
|
||||||
|
"Unexpected Java type [%s] for numeric literal - %s",
|
||||||
|
javaType.getTypeName(),
|
||||||
|
literalValue
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -39,6 +39,7 @@ import org.hibernate.sql.ast.tree.expression.Star;
|
||||||
import org.hibernate.sql.ast.tree.expression.Summarization;
|
import org.hibernate.sql.ast.tree.expression.Summarization;
|
||||||
import org.hibernate.sql.ast.tree.expression.TrimSpecification;
|
import org.hibernate.sql.ast.tree.expression.TrimSpecification;
|
||||||
import org.hibernate.sql.ast.tree.expression.UnaryOperation;
|
import org.hibernate.sql.ast.tree.expression.UnaryOperation;
|
||||||
|
import org.hibernate.sql.ast.tree.expression.UnparsedNumericLiteral;
|
||||||
import org.hibernate.sql.ast.tree.from.FromClause;
|
import org.hibernate.sql.ast.tree.from.FromClause;
|
||||||
import org.hibernate.sql.ast.tree.from.FunctionTableReference;
|
import org.hibernate.sql.ast.tree.from.FunctionTableReference;
|
||||||
import org.hibernate.sql.ast.tree.from.NamedTableReference;
|
import org.hibernate.sql.ast.tree.from.NamedTableReference;
|
||||||
|
@ -173,6 +174,8 @@ public interface SqlAstWalker {
|
||||||
|
|
||||||
void visitQueryLiteral(QueryLiteral<?> queryLiteral);
|
void visitQueryLiteral(QueryLiteral<?> queryLiteral);
|
||||||
|
|
||||||
|
<N extends Number> void visitUnparsedNumericLiteral(UnparsedNumericLiteral<N> literal);
|
||||||
|
|
||||||
void visitUnaryOperationExpression(UnaryOperation unaryOperationExpression);
|
void visitUnaryOperationExpression(UnaryOperation unaryOperationExpression);
|
||||||
|
|
||||||
void visitModifiedSubQueryExpression(ModifiedSubQueryExpression expression);
|
void visitModifiedSubQueryExpression(ModifiedSubQueryExpression expression);
|
||||||
|
|
|
@ -133,6 +133,7 @@ import org.hibernate.sql.ast.tree.expression.Star;
|
||||||
import org.hibernate.sql.ast.tree.expression.Summarization;
|
import org.hibernate.sql.ast.tree.expression.Summarization;
|
||||||
import org.hibernate.sql.ast.tree.expression.TrimSpecification;
|
import org.hibernate.sql.ast.tree.expression.TrimSpecification;
|
||||||
import org.hibernate.sql.ast.tree.expression.UnaryOperation;
|
import org.hibernate.sql.ast.tree.expression.UnaryOperation;
|
||||||
|
import org.hibernate.sql.ast.tree.expression.UnparsedNumericLiteral;
|
||||||
import org.hibernate.sql.ast.tree.from.DerivedTableReference;
|
import org.hibernate.sql.ast.tree.from.DerivedTableReference;
|
||||||
import org.hibernate.sql.ast.tree.from.FromClause;
|
import org.hibernate.sql.ast.tree.from.FromClause;
|
||||||
import org.hibernate.sql.ast.tree.from.FunctionTableReference;
|
import org.hibernate.sql.ast.tree.from.FunctionTableReference;
|
||||||
|
@ -6675,6 +6676,11 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
||||||
visitLiteral( queryLiteral );
|
visitLiteral( queryLiteral );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <N extends Number> void visitUnparsedNumericLiteral(UnparsedNumericLiteral<N> literal) {
|
||||||
|
appendSql( literal.getLiteralValue() );
|
||||||
|
}
|
||||||
|
|
||||||
private void visitLiteral(Literal literal) {
|
private void visitLiteral(Literal literal) {
|
||||||
if ( literal.getLiteralValue() == null ) {
|
if ( literal.getLiteralValue() == null ) {
|
||||||
renderNull( literal );
|
renderNull( literal );
|
||||||
|
|
|
@ -45,6 +45,7 @@ import org.hibernate.sql.ast.tree.expression.Star;
|
||||||
import org.hibernate.sql.ast.tree.expression.Summarization;
|
import org.hibernate.sql.ast.tree.expression.Summarization;
|
||||||
import org.hibernate.sql.ast.tree.expression.TrimSpecification;
|
import org.hibernate.sql.ast.tree.expression.TrimSpecification;
|
||||||
import org.hibernate.sql.ast.tree.expression.UnaryOperation;
|
import org.hibernate.sql.ast.tree.expression.UnaryOperation;
|
||||||
|
import org.hibernate.sql.ast.tree.expression.UnparsedNumericLiteral;
|
||||||
import org.hibernate.sql.ast.tree.from.FromClause;
|
import org.hibernate.sql.ast.tree.from.FromClause;
|
||||||
import org.hibernate.sql.ast.tree.from.FunctionTableReference;
|
import org.hibernate.sql.ast.tree.from.FunctionTableReference;
|
||||||
import org.hibernate.sql.ast.tree.from.NamedTableReference;
|
import org.hibernate.sql.ast.tree.from.NamedTableReference;
|
||||||
|
@ -515,6 +516,10 @@ public class AbstractSqlAstWalker implements SqlAstWalker {
|
||||||
public void visitQueryLiteral(QueryLiteral<?> queryLiteral) {
|
public void visitQueryLiteral(QueryLiteral<?> queryLiteral) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <N extends Number> void visitUnparsedNumericLiteral(UnparsedNumericLiteral<N> literal) {
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitEntityTypeLiteral(EntityTypeLiteral expression) {
|
public void visitEntityTypeLiteral(EntityTypeLiteral expression) {
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,7 @@ import org.hibernate.sql.ast.tree.expression.Star;
|
||||||
import org.hibernate.sql.ast.tree.expression.Summarization;
|
import org.hibernate.sql.ast.tree.expression.Summarization;
|
||||||
import org.hibernate.sql.ast.tree.expression.TrimSpecification;
|
import org.hibernate.sql.ast.tree.expression.TrimSpecification;
|
||||||
import org.hibernate.sql.ast.tree.expression.UnaryOperation;
|
import org.hibernate.sql.ast.tree.expression.UnaryOperation;
|
||||||
|
import org.hibernate.sql.ast.tree.expression.UnparsedNumericLiteral;
|
||||||
import org.hibernate.sql.ast.tree.from.FromClause;
|
import org.hibernate.sql.ast.tree.from.FromClause;
|
||||||
import org.hibernate.sql.ast.tree.from.FunctionTableReference;
|
import org.hibernate.sql.ast.tree.from.FunctionTableReference;
|
||||||
import org.hibernate.sql.ast.tree.from.NamedTableReference;
|
import org.hibernate.sql.ast.tree.from.NamedTableReference;
|
||||||
|
@ -233,6 +234,11 @@ public class ExpressionReplacementWalker implements SqlAstWalker {
|
||||||
doReplaceExpression( queryLiteral );
|
doReplaceExpression( queryLiteral );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <N extends Number> void visitUnparsedNumericLiteral(UnparsedNumericLiteral<N> literal) {
|
||||||
|
doReplaceExpression( literal );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitUnaryOperationExpression(UnaryOperation unaryOperationExpression) {
|
public void visitUnaryOperationExpression(UnaryOperation unaryOperationExpression) {
|
||||||
doReplaceExpression( unaryOperationExpression );
|
doReplaceExpression( unaryOperationExpression );
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
/*
|
||||||
|
* 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.sql.ast.tree.expression;
|
||||||
|
|
||||||
|
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||||
|
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
|
||||||
|
import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
|
||||||
|
import org.hibernate.sql.ast.SqlAstWalker;
|
||||||
|
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
||||||
|
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||||
|
import org.hibernate.sql.results.graph.DomainResult;
|
||||||
|
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||||
|
import org.hibernate.sql.results.graph.basic.BasicResult;
|
||||||
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A numeric literal coming from an HQL query, which needs special handling
|
||||||
|
*
|
||||||
|
* @see org.hibernate.query.sqm.tree.expression.SqmHqlNumericLiteral
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class UnparsedNumericLiteral<N extends Number> implements Expression, DomainResultProducer<N> {
|
||||||
|
private final String literalValue;
|
||||||
|
private final JdbcMapping jdbcMapping;
|
||||||
|
|
||||||
|
public UnparsedNumericLiteral(String literalValue, JdbcMapping jdbcMapping) {
|
||||||
|
this.literalValue = literalValue;
|
||||||
|
this.jdbcMapping = jdbcMapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLiteralValue() {
|
||||||
|
return literalValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JdbcMapping getJdbcMapping() {
|
||||||
|
return jdbcMapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JdbcMappingContainer getExpressionType() {
|
||||||
|
return getJdbcMapping();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DomainResult<N> createDomainResult(String resultVariable, DomainResultCreationState creationState) {
|
||||||
|
final SqlExpressionResolver sqlExpressionResolver = creationState.getSqlAstCreationState().getSqlExpressionResolver();
|
||||||
|
final TypeConfiguration typeConfiguration = creationState.getSqlAstCreationState().getCreationContext().getSessionFactory().getTypeConfiguration();
|
||||||
|
|
||||||
|
final SqlSelection sqlSelection = sqlExpressionResolver.resolveSqlSelection(
|
||||||
|
this,
|
||||||
|
getJdbcMapping().getJdbcJavaType(),
|
||||||
|
null,
|
||||||
|
typeConfiguration
|
||||||
|
);
|
||||||
|
|
||||||
|
return new BasicResult<>(
|
||||||
|
sqlSelection.getValuesArrayPosition(),
|
||||||
|
resultVariable,
|
||||||
|
jdbcMapping
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void applySqlSelections(DomainResultCreationState creationState) {
|
||||||
|
creationState.getSqlAstCreationState().getSqlExpressionResolver().resolveSqlSelection(
|
||||||
|
this,
|
||||||
|
jdbcMapping.getJdbcJavaType(),
|
||||||
|
null,
|
||||||
|
creationState.getSqlAstCreationState().getCreationContext().getMappingMetamodel().getTypeConfiguration()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(SqlAstWalker sqlTreeWalker) {
|
||||||
|
sqlTreeWalker.visitUnparsedNumericLiteral( this );
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,52 +0,0 @@
|
||||||
package org.hibernate.orm.test.query;
|
|
||||||
|
|
||||||
import jakarta.persistence.Entity;
|
|
||||||
import jakarta.persistence.Id;
|
|
||||||
|
|
||||||
import org.hibernate.orm.test.jpa.BaseEntityManagerFunctionalTestCase;
|
|
||||||
|
|
||||||
import org.hibernate.testing.TestForIssue;
|
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Andrias Sundskar
|
|
||||||
* @author Nathan Xu
|
|
||||||
*/
|
|
||||||
@TestForIssue( jiraKey = "HHH-14213" )
|
|
||||||
public class IntegerRepresentationLiteralParsingExceptionTest extends BaseEntityManagerFunctionalTestCase {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<?>[] getAnnotatedClasses() {
|
|
||||||
return new Class<?>[] { ExampleEntity.class };
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testAppropriateExceptionMessageGenerated() {
|
|
||||||
try {
|
|
||||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
|
||||||
// 9223372036854775808 is beyond Long range, so an Exception will be thrown
|
|
||||||
entityManager.createQuery( "select count(*) from ExampleEntity where counter = 9223372036854775808L" )
|
|
||||||
.getSingleResult();
|
|
||||||
} );
|
|
||||||
Assert.fail( "Exception should be thrown" );
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
// without fixing HHH-14213, the following exception would be thrown:
|
|
||||||
// "Could not parse literal [9223372036854775808L] as integer"
|
|
||||||
// which is confusing and misleading
|
|
||||||
Assert.assertTrue( e.getMessage().endsWith( " to Long" ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Entity(name = "ExampleEntity")
|
|
||||||
static class ExampleEntity {
|
|
||||||
|
|
||||||
@Id
|
|
||||||
int id;
|
|
||||||
|
|
||||||
long counter;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -12,6 +12,7 @@ import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmCaseSearched;
|
import org.hibernate.query.sqm.tree.expression.SqmCaseSearched;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmCaseSimple;
|
import org.hibernate.query.sqm.tree.expression.SqmCaseSimple;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmFunction;
|
import org.hibernate.query.sqm.tree.expression.SqmFunction;
|
||||||
|
import org.hibernate.query.sqm.tree.expression.SqmHqlNumericLiteral;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmLiteral;
|
import org.hibernate.query.sqm.tree.expression.SqmLiteral;
|
||||||
import org.hibernate.query.sqm.tree.predicate.SqmComparisonPredicate;
|
import org.hibernate.query.sqm.tree.predicate.SqmComparisonPredicate;
|
||||||
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
|
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
|
||||||
|
@ -57,7 +58,7 @@ public class CaseExpressionsTest extends BaseSqmUnitTest {
|
||||||
assertThat( caseStatement.getFixture(), instanceOf( SqmPath.class ) );
|
assertThat( caseStatement.getFixture(), instanceOf( SqmPath.class ) );
|
||||||
|
|
||||||
assertThat( caseStatement.getOtherwise(), notNullValue() );
|
assertThat( caseStatement.getOtherwise(), notNullValue() );
|
||||||
assertThat( caseStatement.getOtherwise(), instanceOf( SqmLiteral.class ) );
|
assertThat( caseStatement.getOtherwise(), instanceOf( SqmHqlNumericLiteral.class ) );
|
||||||
|
|
||||||
assertThat( caseStatement.getWhenFragments().size(), is(1) );
|
assertThat( caseStatement.getWhenFragments().size(), is(1) );
|
||||||
}
|
}
|
||||||
|
@ -79,7 +80,7 @@ public class CaseExpressionsTest extends BaseSqmUnitTest {
|
||||||
);
|
);
|
||||||
|
|
||||||
assertThat( caseStatement.getOtherwise(), notNullValue() );
|
assertThat( caseStatement.getOtherwise(), notNullValue() );
|
||||||
assertThat( caseStatement.getOtherwise(), instanceOf( SqmLiteral.class ) );
|
assertThat( caseStatement.getOtherwise(), instanceOf( SqmHqlNumericLiteral.class ) );
|
||||||
|
|
||||||
assertThat( caseStatement.getWhenFragments().size(), is(1) );
|
assertThat( caseStatement.getWhenFragments().size(), is(1) );
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import org.hibernate.orm.test.query.sqm.domain.Person;
|
||||||
import org.hibernate.query.sqm.ComparisonOperator;
|
import org.hibernate.query.sqm.ComparisonOperator;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmCollectionSize;
|
import org.hibernate.query.sqm.tree.expression.SqmCollectionSize;
|
||||||
|
import org.hibernate.query.sqm.tree.expression.SqmHqlNumericLiteral;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmLiteral;
|
import org.hibernate.query.sqm.tree.expression.SqmLiteral;
|
||||||
import org.hibernate.query.sqm.tree.predicate.SqmNullnessPredicate;
|
import org.hibernate.query.sqm.tree.predicate.SqmNullnessPredicate;
|
||||||
import org.hibernate.query.sqm.tree.predicate.SqmComparisonPredicate;
|
import org.hibernate.query.sqm.tree.predicate.SqmComparisonPredicate;
|
||||||
|
@ -80,8 +81,8 @@ public class WhereClauseTests extends BaseSqmUnitTest {
|
||||||
|
|
||||||
assertThat( relationalPredicate.getSqmOperator(), is( ComparisonOperator.EQUAL ) );
|
assertThat( relationalPredicate.getSqmOperator(), is( ComparisonOperator.EQUAL ) );
|
||||||
|
|
||||||
assertThat( relationalPredicate.getRightHandExpression(), instanceOf( SqmLiteral.class ) );
|
assertThat( relationalPredicate.getRightHandExpression(), instanceOf( SqmHqlNumericLiteral.class ) );
|
||||||
assertThat( ( (SqmLiteral<?>) relationalPredicate.getRightHandExpression() ).getLiteralValue(), is( 311 ) );
|
assertThat( ( (SqmHqlNumericLiteral<?>) relationalPredicate.getRightHandExpression() ).getLiteralValue(), is( "311" ) );
|
||||||
|
|
||||||
assertThat( relationalPredicate.getLeftHandExpression(), instanceOf( SqmCollectionSize.class ) );
|
assertThat( relationalPredicate.getLeftHandExpression(), instanceOf( SqmCollectionSize.class ) );
|
||||||
|
|
||||||
|
@ -100,8 +101,8 @@ public class WhereClauseTests extends BaseSqmUnitTest {
|
||||||
|
|
||||||
assertThat( relationalPredicate.getSqmOperator(), is( ComparisonOperator.GREATER_THAN ) );
|
assertThat( relationalPredicate.getSqmOperator(), is( ComparisonOperator.GREATER_THAN ) );
|
||||||
|
|
||||||
assertThat( relationalPredicate.getRightHandExpression(), instanceOf( SqmLiteral.class ) );
|
assertThat( relationalPredicate.getRightHandExpression(), instanceOf( SqmHqlNumericLiteral.class ) );
|
||||||
assertThat( ( (SqmLiteral<?>) relationalPredicate.getRightHandExpression() ).getLiteralValue(), is( 2 ) );
|
assertThat( ( (SqmHqlNumericLiteral<?>) relationalPredicate.getRightHandExpression() ).getLiteralValue(), is( "2" ) );
|
||||||
|
|
||||||
assertThat( relationalPredicate.getLeftHandExpression(), instanceOf( SqmPath.class ) );
|
assertThat( relationalPredicate.getLeftHandExpression(), instanceOf( SqmPath.class ) );
|
||||||
final SqmPath<?> indexPath = (SqmPath<?>) relationalPredicate.getLeftHandExpression();
|
final SqmPath<?> indexPath = (SqmPath<?>) relationalPredicate.getLeftHandExpression();
|
||||||
|
|
|
@ -22,7 +22,7 @@ import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolv
|
||||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||||
import org.hibernate.sql.ast.spi.SqlAppender;
|
import org.hibernate.sql.ast.spi.SqlAppender;
|
||||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||||
import org.hibernate.sql.ast.tree.expression.QueryLiteral;
|
import org.hibernate.sql.ast.tree.expression.UnparsedNumericLiteral;
|
||||||
|
|
||||||
import org.hibernate.testing.orm.junit.BaseSessionFactoryFunctionalTest;
|
import org.hibernate.testing.orm.junit.BaseSessionFactoryFunctionalTest;
|
||||||
import org.hibernate.testing.orm.junit.RequiresDialect;
|
import org.hibernate.testing.orm.junit.RequiresDialect;
|
||||||
|
@ -61,7 +61,7 @@ public class SubqueryTest extends BaseSessionFactoryFunctionalTest {
|
||||||
public void render(
|
public void render(
|
||||||
SqlAppender sqlAppender, List<? extends SqlAstNode> sqlAstArguments, SqlAstTranslator<?> walker) {
|
SqlAppender sqlAppender, List<? extends SqlAstNode> sqlAstArguments, SqlAstTranslator<?> walker) {
|
||||||
sqlAstArguments.get( 0 ).accept( walker );
|
sqlAstArguments.get( 0 ).accept( walker );
|
||||||
sqlAppender.appendSql( " limit " + ( (QueryLiteral<?>) sqlAstArguments.get( 1 ) ).getLiteralValue() );
|
sqlAppender.appendSql( " limit " + ( (UnparsedNumericLiteral<?>) sqlAstArguments.get( 1 ) ).getLiteralValue() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,26 @@ earlier versions, see any other pertinent migration guides as well.
|
||||||
* link:{docsBase}/6.1/migration-guide/migration-guide.html[6.1 Migration guide]
|
* link:{docsBase}/6.1/migration-guide/migration-guide.html[6.1 Migration guide]
|
||||||
* link:{docsBase}/6.0/migration-guide/migration-guide.html[6.0 Migration guide]
|
* link:{docsBase}/6.0/migration-guide/migration-guide.html[6.0 Migration guide]
|
||||||
|
|
||||||
|
[[hql-numeric-literal-types]]
|
||||||
|
== HQL Numeric Literal Types
|
||||||
|
|
||||||
|
Version 3.2 of the Jakarta Persistence specification
|
||||||
|
https://github.com/jakartaee/persistence/issues/423[clarifies] the interpretation of
|
||||||
|
numeric literals with regard to type, explicitly aligning with the Java specification (as well
|
||||||
|
as adopting Hibernate's long-standing `BigInteger` and `BigDecimal` suffixes).
|
||||||
|
HQL and JPQL are domain/object-level queries, so that makes perfect sense.
|
||||||
|
|
||||||
|
* `Integer` - 123
|
||||||
|
* `Long` - 123l, 123L
|
||||||
|
* `BigInteger` - 123bi, 123BI
|
||||||
|
* `Double` - 123.4
|
||||||
|
* `Float` - 123.4f, 123.4F
|
||||||
|
* `BigDecimal` - 123.4bd, 123.4BD
|
||||||
|
|
||||||
|
Hibernate 6.3 aligns with those interpretations, which may lead to different behavior
|
||||||
|
from prior versions.
|
||||||
|
|
||||||
|
|
||||||
[[batch-fetching-changes]]
|
[[batch-fetching-changes]]
|
||||||
== Batch Fetching and LockMode
|
== Batch Fetching and LockMode
|
||||||
|
|
||||||
|
@ -22,8 +42,9 @@ This because the lock mode is different from the one of the proxies in the batch
|
||||||
|
|
||||||
E.g.
|
E.g.
|
||||||
|
|
||||||
`
|
```java
|
||||||
MyEntity proxy = session.getReference( MyEntity.class, 1 );
|
MyEntity proxy = session.getReference( MyEntity.class, 1 );
|
||||||
MyEntity myEntity = session.find(MyEntity.class, 2, LockMode.WRITE);
|
MyEntity myEntity = session.find(MyEntity.class, 2, LockMode.WRITE);
|
||||||
`
|
```
|
||||||
|
|
||||||
only the entity with id equals to 2 will be loaded but the proxy will not be initialized.
|
only the entity with id equals to 2 will be loaded but the proxy will not be initialized.
|
||||||
|
|
Loading…
Reference in New Issue