diff --git a/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryBuilderImpl.java b/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryBuilderImpl.java
index 7a05b22437..cdda6708f9 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryBuilderImpl.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryBuilderImpl.java
@@ -583,6 +583,8 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
private boolean jpaProxyComplianceEnabled;
private ImmutableEntityUpdateQueryHandlingMode immutableEntityUpdateQueryHandlingMode;
+ private boolean inClauseParameterPaddingEnabled;
+
public SessionFactoryOptionsStateStandardImpl(StandardServiceRegistry serviceRegistry) {
this.serviceRegistry = serviceRegistry;
@@ -829,6 +831,12 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
this.immutableEntityUpdateQueryHandlingMode = ImmutableEntityUpdateQueryHandlingMode.interpret(
configurationSettings.get( IMMUTABLE_ENTITY_UPDATE_QUERY_HANDLING_MODE )
);
+
+ this.inClauseParameterPaddingEnabled = ConfigurationHelper.getBoolean(
+ IN_CLAUSE_PARAMETER_PADDING,
+ configurationSettings,
+ false
+ );
}
private static Interceptor determineInterceptor(Map configurationSettings, StrategySelector strategySelector) {
@@ -1297,6 +1305,11 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
public ImmutableEntityUpdateQueryHandlingMode getImmutableEntityUpdateQueryHandlingMode() {
return immutableEntityUpdateQueryHandlingMode;
}
+
+ @Override
+ public boolean inClauseParameterPaddingEnabled() {
+ return this.inClauseParameterPaddingEnabled;
+ }
}
private static Supplier extends Interceptor> interceptorSupplier(Class extends Interceptor> clazz) {
@@ -1661,4 +1674,9 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
public ImmutableEntityUpdateQueryHandlingMode getImmutableEntityUpdateQueryHandlingMode() {
return options.getImmutableEntityUpdateQueryHandlingMode();
}
+
+ @Override
+ public boolean inClauseParameterPaddingEnabled() {
+ return options.inClauseParameterPaddingEnabled();
+ }
}
diff --git a/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsImpl.java b/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsImpl.java
index d07d6f9e3c..64ff7860ef 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsImpl.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsImpl.java
@@ -137,6 +137,7 @@ public class SessionFactoryOptionsImpl implements SessionFactoryOptions {
private final boolean failOnPaginationOverCollectionFetchEnabled;
private final boolean jpaProxyComplianceEnabled;
private ImmutableEntityUpdateQueryHandlingMode immutableEntityUpdateQueryHandlingMode;
+ private boolean inClauseParameterPaddingEnabled;
public SessionFactoryOptionsImpl(SessionFactoryOptionsState state) {
this.serviceRegistry = state.getServiceRegistry();
@@ -225,6 +226,8 @@ public class SessionFactoryOptionsImpl implements SessionFactoryOptions {
this.jpaProxyComplianceEnabled = state.isJpaProxyComplianceEnabled();
this.immutableEntityUpdateQueryHandlingMode = state.getImmutableEntityUpdateQueryHandlingMode();
+
+ this.inClauseParameterPaddingEnabled = state.inClauseParameterPaddingEnabled();
}
@Override
@@ -585,4 +588,9 @@ public class SessionFactoryOptionsImpl implements SessionFactoryOptions {
public ImmutableEntityUpdateQueryHandlingMode getImmutableEntityUpdateQueryHandlingMode() {
return immutableEntityUpdateQueryHandlingMode;
}
+
+ @Override
+ public boolean inClauseParameterPaddingEnabled() {
+ return inClauseParameterPaddingEnabled;
+ }
}
diff --git a/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsState.java b/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsState.java
index f6836c9ccf..89b7ec353b 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsState.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsState.java
@@ -216,4 +216,8 @@ public interface SessionFactoryOptionsState {
default ImmutableEntityUpdateQueryHandlingMode getImmutableEntityUpdateQueryHandlingMode() {
return ImmutableEntityUpdateQueryHandlingMode.WARNING;
}
+
+ default boolean inClauseParameterPaddingEnabled() {
+ return false;
+ }
}
diff --git a/hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingSessionFactoryOptions.java b/hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingSessionFactoryOptions.java
index f196ec00dc..ca30ec7498 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingSessionFactoryOptions.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingSessionFactoryOptions.java
@@ -411,4 +411,9 @@ public class AbstractDelegatingSessionFactoryOptions implements SessionFactoryOp
public ImmutableEntityUpdateQueryHandlingMode getImmutableEntityUpdateQueryHandlingMode() {
return delegate.getImmutableEntityUpdateQueryHandlingMode();
}
+
+ @Override
+ public boolean inClauseParameterPaddingEnabled() {
+ return delegate.inClauseParameterPaddingEnabled();
+ }
}
diff --git a/hibernate-core/src/main/java/org/hibernate/boot/spi/SessionFactoryOptions.java b/hibernate-core/src/main/java/org/hibernate/boot/spi/SessionFactoryOptions.java
index ae18de2ca5..9805aab36b 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/spi/SessionFactoryOptions.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/spi/SessionFactoryOptions.java
@@ -261,4 +261,8 @@ public interface SessionFactoryOptions {
default ImmutableEntityUpdateQueryHandlingMode getImmutableEntityUpdateQueryHandlingMode() {
return ImmutableEntityUpdateQueryHandlingMode.WARNING;
}
+
+ default boolean inClauseParameterPaddingEnabled() {
+ return false;
+ }
}
diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java b/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java
index 6e758b462d..dd4a38b8e2 100644
--- a/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java
+++ b/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java
@@ -1779,4 +1779,22 @@ public interface AvailableSettings {
* @see org.hibernate.query.ImmutableEntityUpdateQueryHandlingMode
*/
String IMMUTABLE_ENTITY_UPDATE_QUERY_HANDLING_MODE = "hibernate.query.immutable_entity_update_query_handling_mode";
+
+ /**
+ * By default, the IN clause expands to include all bind parameter values.
+ *
+ * However, for database systems supporting execution plan caching,
+ * there's a better chance of hitting the cache if the number of possible IN clause parameters lowers.
+ *
+ * For this reason, we can expand the bind parameters to power-of-two: 4, 8, 16, 32, 64.
+ * This way, an IN clause with 5, 6, or 7 bind parameters will use the 8 IN clause,
+ * therefore reusing its execution plan.
+ *
+ * If you want to activate this feature, you need to set this property to {@code true}.
+ *
+ * The default value is {@code false}.
+ *
+ * @since 5.2.17
+ */
+ String IN_CLAUSE_PARAMETER_PADDING = "hibernate.query.in_clause_parameter_padding";
}
diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/MathHelper.java b/hibernate-core/src/main/java/org/hibernate/internal/util/MathHelper.java
new file mode 100644
index 0000000000..64ef20feed
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/internal/util/MathHelper.java
@@ -0,0 +1,26 @@
+/*
+ * 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 .
+ */
+package org.hibernate.internal.util;
+
+/**
+ * @author Vlad Mihalcea
+ */
+public final class MathHelper {
+
+ private MathHelper() { /* static methods only - hide constructor */
+ }
+
+ /**
+ * Returns the smallest power of two number that is greater than or equal to {@code value}.
+ *
+ * @param value reference number
+ * @return smallest power of two number
+ */
+ public static int ceilingPowerOfTwo(int value) {
+ return 1 << -Integer.numberOfLeadingZeros(value - 1);
+ }
+}
diff --git a/hibernate-core/src/main/java/org/hibernate/query/internal/QueryParameterBindingsImpl.java b/hibernate-core/src/main/java/org/hibernate/query/internal/QueryParameterBindingsImpl.java
index 29983b6237..a17b5f043f 100644
--- a/hibernate-core/src/main/java/org/hibernate/query/internal/QueryParameterBindingsImpl.java
+++ b/hibernate-core/src/main/java/org/hibernate/query/internal/QueryParameterBindingsImpl.java
@@ -28,6 +28,7 @@ import org.hibernate.engine.spi.TypedValue;
import org.hibernate.hql.internal.classic.ParserHelper;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
+import org.hibernate.internal.util.MathHelper;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.query.ParameterMetadata;
import org.hibernate.query.QueryParameter;
@@ -548,8 +549,23 @@ public class QueryParameterBindingsImpl implements QueryParameterBindings {
final NamedParameterDescriptor sourceParam = (NamedParameterDescriptor) entry.getKey();
final Collection bindValues = entry.getValue().getBindValues();
- if ( inExprLimit > 0 && bindValues.size() > inExprLimit ) {
- log.tooManyInExpressions( dialect.getClass().getName(), inExprLimit, sourceParam.getName(), bindValues.size() );
+ int bindValueCount = bindValues.size();
+ int bindValueMaxCount = bindValueCount;
+
+ boolean inClauseParameterPaddingEnabled =
+ session.getFactory().getSessionFactoryOptions().inClauseParameterPaddingEnabled() &&
+ bindValueCount > 2;
+
+ if ( inClauseParameterPaddingEnabled ) {
+ int bindValuePaddingCount = MathHelper.ceilingPowerOfTwo( bindValueCount );
+
+ if ( bindValueCount < bindValuePaddingCount && (inExprLimit == 0 || bindValuePaddingCount < inExprLimit) ) {
+ bindValueMaxCount = bindValuePaddingCount;
+ }
+ }
+
+ if ( inExprLimit > 0 && bindValueCount > inExprLimit ) {
+ log.tooManyInExpressions( dialect.getClass().getName(), inExprLimit, sourceParam.getName(), bindValueCount );
}
final boolean isJpaPositionalParam = sourceParam.isJpaPositionalParameter();
@@ -581,8 +597,15 @@ public class QueryParameterBindingsImpl implements QueryParameterBindings {
StringBuilder expansionList = new StringBuilder();
- int i = 0;
- for ( Object bindValue : entry.getValue().getBindValues() ) {
+ Iterator bindValueIterator = entry.getValue().getBindValues().iterator();
+ Object bindValue = null;
+
+ for ( int i = 0; i < bindValueMaxCount; i++ ) {
+
+ if ( i < bindValueCount ) {
+ bindValue = bindValueIterator.next();
+ }
+
// for each value in the bound list-of-values we:
// 1) create a synthetic named parameter
// 2) expand the queryString to include each synthetic named param in place of the original
@@ -601,7 +624,6 @@ public class QueryParameterBindingsImpl implements QueryParameterBindings {
final QueryParameterBinding syntheticBinding = makeBinding( entry.getValue().getBindType() );
syntheticBinding.setBindValue( bindValue );
parameterBindingMap.put( syntheticParam, syntheticBinding );
- i++;
}
queryString = StringHelper.replace(
diff --git a/hibernate-core/src/test/java/org/hibernate/internal/util/MathHelperTest.java b/hibernate-core/src/test/java/org/hibernate/internal/util/MathHelperTest.java
new file mode 100644
index 0000000000..6f44048b22
--- /dev/null
+++ b/hibernate-core/src/test/java/org/hibernate/internal/util/MathHelperTest.java
@@ -0,0 +1,38 @@
+/*
+ * 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 .
+ */
+package org.hibernate.internal.util;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author Vlad Mihalcea
+ */
+public class MathHelperTest {
+
+ @Test
+ public void ceilingPowerOfTwo() {
+ assertEquals( 1, MathHelper.ceilingPowerOfTwo( 1 ) );
+ assertEquals( 2, MathHelper.ceilingPowerOfTwo( 2 ) );
+ assertEquals( 4, MathHelper.ceilingPowerOfTwo( 3 ) );
+ assertEquals( 4, MathHelper.ceilingPowerOfTwo( 4 ) );
+ assertEquals( 8, MathHelper.ceilingPowerOfTwo( 5 ) );
+ assertEquals( 8, MathHelper.ceilingPowerOfTwo( 6 ) );
+ assertEquals( 8, MathHelper.ceilingPowerOfTwo( 7 ) );
+ assertEquals( 8, MathHelper.ceilingPowerOfTwo( 8 ) );
+ assertEquals( 16, MathHelper.ceilingPowerOfTwo( 9 ) );
+ assertEquals( 16, MathHelper.ceilingPowerOfTwo( 10 ) );
+ assertEquals( 16, MathHelper.ceilingPowerOfTwo( 11 ) );
+ assertEquals( 16, MathHelper.ceilingPowerOfTwo( 12 ) );
+ assertEquals( 16, MathHelper.ceilingPowerOfTwo( 13 ) );
+ assertEquals( 16, MathHelper.ceilingPowerOfTwo( 16 ) );
+ assertEquals( 16, MathHelper.ceilingPowerOfTwo( 14 ) );
+ assertEquals( 16, MathHelper.ceilingPowerOfTwo( 15 ) );
+ }
+
+}
\ No newline at end of file
diff --git a/hibernate-core/src/test/java/org/hibernate/query/InClauseParameterPaddingTest.java b/hibernate-core/src/test/java/org/hibernate/query/InClauseParameterPaddingTest.java
new file mode 100644
index 0000000000..f2bc0a869f
--- /dev/null
+++ b/hibernate-core/src/test/java/org/hibernate/query/InClauseParameterPaddingTest.java
@@ -0,0 +1,129 @@
+/*
+ * 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 .
+ */
+package org.hibernate.query;
+
+import java.util.Arrays;
+import java.util.Map;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+
+import org.hibernate.cfg.AvailableSettings;
+import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
+
+import org.hibernate.testing.TestForIssue;
+import org.hibernate.test.util.jdbc.PreparedStatementSpyConnectionProvider;
+import org.junit.Test;
+
+import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Vlad Mihalcea
+ */
+@TestForIssue( jiraKey = "HHH-12469" )
+public class InClauseParameterPaddingTest extends BaseEntityManagerFunctionalTestCase {
+
+ private PreparedStatementSpyConnectionProvider connectionProvider;
+
+ @Override
+ public void buildEntityManagerFactory() {
+ connectionProvider = new PreparedStatementSpyConnectionProvider();
+ super.buildEntityManagerFactory();
+ }
+
+ @Override
+ public void releaseResources() {
+ super.releaseResources();
+ connectionProvider.stop();
+ }
+
+ @Override
+ public Class[] getAnnotatedClasses() {
+ return new Class[] {
+ Person.class
+ };
+ }
+
+ @Override
+ protected void addConfigOptions(Map options) {
+ options.put( AvailableSettings.IN_CLAUSE_PARAMETER_PADDING, Boolean.TRUE.toString() );
+ options.put(
+ org.hibernate.cfg.AvailableSettings.CONNECTION_PROVIDER,
+ connectionProvider
+ );
+ }
+
+ @Override
+ protected void afterEntityManagerFactoryBuilt() {
+ doInJPA( this::entityManagerFactory, entityManager -> {
+ for ( int i = 1; i < 10; i++ ) {
+ Person person = new Person();
+ person.setId( i );
+ person.setName( String.format( "Person nr %d", i ) );
+
+ entityManager.persist( person );
+ }
+ } );
+ }
+
+ @Test
+ public void testInClauseParameterPadding() {
+ validateInClauseParameterPadding( "in (?)", 1 );
+ validateInClauseParameterPadding( "in (? , ?)", 1, 2 );
+ validateInClauseParameterPadding( "in (? , ? , ? , ?)", 1, 2, 3 );
+ validateInClauseParameterPadding( "in (? , ? , ? , ?)", 1, 2, 3, 4 );
+ validateInClauseParameterPadding( "in (? , ? , ? , ? , ? , ? , ? , ?)", 1, 2, 3, 4, 5 );
+ validateInClauseParameterPadding( "in (? , ? , ? , ? , ? , ? , ? , ?)", 1, 2, 3, 4, 5, 6 );
+ validateInClauseParameterPadding( "in (? , ? , ? , ? , ? , ? , ? , ?)", 1, 2, 3, 4, 5, 6, 7 );
+ validateInClauseParameterPadding( "in (? , ? , ? , ? , ? , ? , ? , ?)", 1, 2, 3, 4, 5, 6, 7, 8 );
+ validateInClauseParameterPadding( "in (? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ?)", 1, 2, 3, 4, 5, 6, 7, 8, 9 );
+ validateInClauseParameterPadding( "in (? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ?)", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 );
+ }
+
+ private void validateInClauseParameterPadding(String expectedInClause, Integer... ids) {
+ connectionProvider.clear();
+
+ doInJPA( this::entityManagerFactory, entityManager -> {
+ return entityManager.createQuery(
+ "select p " +
+ "from Person p " +
+ "where p.id in :ids" )
+ .setParameter( "ids", Arrays.asList(ids) )
+ .getResultList();
+ } );
+
+ assertTrue(connectionProvider.getPreparedSQLStatements().get( 0 ).endsWith( expectedInClause ));
+ }
+
+ @Entity(name = "Person")
+ public static class Person {
+
+ @Id
+ private Integer id;
+
+ private String name;
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+ }
+
+}
diff --git a/hibernate-core/src/test/java/org/hibernate/query/MaxInExpressionParameterPaddingTest.java b/hibernate-core/src/test/java/org/hibernate/query/MaxInExpressionParameterPaddingTest.java
new file mode 100644
index 0000000000..b60e602860
--- /dev/null
+++ b/hibernate-core/src/test/java/org/hibernate/query/MaxInExpressionParameterPaddingTest.java
@@ -0,0 +1,140 @@
+/*
+ * 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 .
+ */
+package org.hibernate.query;
+
+import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+
+import org.hibernate.cfg.AvailableSettings;
+import org.hibernate.dialect.Dialect;
+import org.hibernate.dialect.H2Dialect;
+import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
+
+import org.hibernate.testing.RequiresDialect;
+import org.hibernate.testing.TestForIssue;
+import org.hibernate.test.util.jdbc.PreparedStatementSpyConnectionProvider;
+import org.junit.Test;
+
+import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Vlad Mihalcea
+ */
+@TestForIssue( jiraKey = "HHH-12469" )
+@RequiresDialect(H2Dialect.class)
+public class MaxInExpressionParameterPaddingTest extends BaseEntityManagerFunctionalTestCase {
+
+ private PreparedStatementSpyConnectionProvider connectionProvider;
+
+ public static final int MAX_COUNT = 15;
+
+ @Override
+ public void buildEntityManagerFactory() {
+ connectionProvider = new PreparedStatementSpyConnectionProvider();
+ super.buildEntityManagerFactory();
+ }
+
+ @Override
+ public void releaseResources() {
+ super.releaseResources();
+ connectionProvider.stop();
+ }
+
+ @Override
+ public Class[] getAnnotatedClasses() {
+ return new Class[] {
+ Person.class
+ };
+ }
+
+ @Override
+ protected void addConfigOptions(Map options) {
+ options.put( AvailableSettings.IN_CLAUSE_PARAMETER_PADDING, Boolean.TRUE.toString() );
+ options.put(
+ AvailableSettings.CONNECTION_PROVIDER,
+ connectionProvider
+ );
+ }
+
+ @Override
+ protected Dialect getDialect() {
+ return new MaxCountInExpressionH2Dialect();
+ }
+
+ @Override
+ protected void afterEntityManagerFactoryBuilt() {
+ doInJPA( this::entityManagerFactory, entityManager -> {
+ for ( int i = 0; i < MAX_COUNT; i++ ) {
+ Person person = new Person();
+ person.setId( i );
+ person.setName( String.format( "Person nr %d", i ) );
+
+ entityManager.persist( person );
+ }
+ } );
+ }
+
+ @Test
+ public void testInClauseParameterPadding() {
+ connectionProvider.clear();
+
+ doInJPA( this::entityManagerFactory, entityManager -> {
+ return entityManager.createQuery(
+ "select p " +
+ "from Person p " +
+ "where p.id in :ids" )
+ .setParameter( "ids", IntStream.range( 0, MAX_COUNT ).boxed().collect(Collectors.toList()) )
+ .getResultList();
+ } );
+
+ StringBuilder expectedInClause = new StringBuilder();
+ expectedInClause.append( "in (?" );
+ for ( int i = 1; i < MAX_COUNT; i++ ) {
+ expectedInClause.append( " , ?" );
+ }
+ expectedInClause.append( ")" );
+
+ assertTrue(connectionProvider.getPreparedSQLStatements().get( 0 ).endsWith( expectedInClause.toString() ));
+ }
+
+ @Entity(name = "Person")
+ public static class Person {
+
+ @Id
+ private Integer id;
+
+ private String name;
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+ }
+
+ public static class MaxCountInExpressionH2Dialect extends H2Dialect {
+ @Override
+ public int getInExpressionCountLimit() {
+ return MAX_COUNT;
+ }
+ }
+
+}