initial work on support for discrim-inheritance;
started design doc about SQM model, building and translation; initial work on `#load` support (strange error in BasicFormatterImpl as part of SqlStatementLogger)
This commit is contained in:
parent
26d914f414
commit
31e2423d8a
|
@ -0,0 +1,29 @@
|
|||
== SQM
|
||||
|
||||
The Semantic Query Model (SQM) is Hibernate's representation of an HQL or Criteria query's semantic (meaning). This
|
||||
representation is modeled as an "abstract syntax tree" (AST) - meaning it is a structured tree of nodes where each node
|
||||
represrents an atomic piece of the query. E.g. `SqmSelectClause` represents the query's select clause as you might
|
||||
imagine. That `SqmSelectClause` is ultimately a collection of one or more `SqmSelection` references representing the
|
||||
individual selections to be returned from the query (called the domain results).
|
||||
|
||||
=== The Model
|
||||
|
||||
This SQM model uses the Hibernate domain model, which is Hibernate's extension to the JPA model. This model contains no
|
||||
relational mapping information, it simply describes the domain model in mostly Java terms although it does incorporate
|
||||
"classifications" of the type system. E.g. it understand that `Customer` is an entity, but contains no information
|
||||
about the tables it maps to nor its columns.
|
||||
|
||||
See the `design/type-system-domain.adoc` design doc. For details about this domain model
|
||||
|
||||
|
||||
=== Building an SQM
|
||||
|
||||
|
||||
=== Interpreting an SQM
|
||||
|
||||
Ultimately Hibernate needs to talk with the database to fulfill these query executions. This is currently a 2-step process.
|
||||
|
||||
First we convert the SQM into a new AST called the SQL AST. This is an AST that is more "SQL-y". It's nodes are defined
|
||||
in terms of Hibernate's mapping model which is the model that actually does understand the relational mapping.
|
||||
See `design/type-system-mapping.adoc` for details about this model. Part of this conversion step is to resolving
|
||||
domain model references to mapping model references...
|
|
@ -95,6 +95,8 @@ public class BasicFormatterImpl implements Formatter {
|
|||
String lcToken;
|
||||
|
||||
public FormatProcess(String sql) {
|
||||
assert sql != null : "SQL to format should not be null";
|
||||
|
||||
tokens = new StringTokenizer(
|
||||
sql,
|
||||
"()+*/-=<>'`\"[]," + StringHelper.WHITESPACE,
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
package org.hibernate.loader.internal;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.EnumMap;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
|
@ -14,9 +15,11 @@ import org.hibernate.NotYetImplementedFor6Exception;
|
|||
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.loader.entity.BatchingEntityLoaderBuilder;
|
||||
import org.hibernate.loader.spi.InternalFetchProfile;
|
||||
import org.hibernate.loader.spi.SingleIdEntityLoader;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.entity.OuterJoinLoadable;
|
||||
import org.hibernate.sql.exec.spi.JdbcSelect;
|
||||
|
||||
/**
|
||||
|
@ -45,14 +48,21 @@ public class SingleIdEntityLoaderStandardImpl<T> implements SingleIdEntityLoader
|
|||
|
||||
@Override
|
||||
public T load(Object key, LockOptions lockOptions, SharedSessionContractImplementor session) {
|
||||
// todo (6.0) : TEMPORARY - use the legacy loaders
|
||||
|
||||
//noinspection unchecked
|
||||
return (T) BatchingEntityLoaderBuilder.getBuilder( session.getFactory() )
|
||||
.buildLoader( (OuterJoinLoadable) entityDescriptor, -1, lockOptions.getLockMode(), session.getFactory(), session.getLoadQueryInfluencers() )
|
||||
.load( (Serializable) key, null, session, lockOptions );
|
||||
|
||||
|
||||
// todo (6.0) : see `org.hibernate.loader.internal.StandardSingleIdEntityLoader#load` in "upstream" 6.0 branch
|
||||
// - and integrate as much as possible with the `o.h.loader.plan` stuff leveraging the similarities
|
||||
// between the legacy LoadPlan stuff and DomainResult, Assembler, etc.
|
||||
|
||||
final JdbcSelect jdbcSelect = resolveJdbcSelect( lockOptions, session );
|
||||
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
//
|
||||
// final JdbcSelect jdbcSelect = resolveJdbcSelect( lockOptions, session );
|
||||
//
|
||||
// throw new NotYetImplementedFor6Exception( getClass() );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
*/
|
||||
package org.hibernate.loader.spi;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
||||
|
@ -17,6 +20,7 @@ import org.hibernate.sql.ast.spi.SqlAliasBaseGenerator;
|
|||
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
||||
import org.hibernate.sql.ast.tree.from.RootTableGroupProducer;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
import org.hibernate.sql.ast.tree.predicate.Predicate;
|
||||
|
||||
/**
|
||||
* Contract for things that can be loaded by a Loader.
|
||||
|
@ -40,6 +44,7 @@ public interface Loadable extends ModelPart, RootTableGroupProducer {
|
|||
LockMode lockMode,
|
||||
SqlAliasBaseGenerator aliasBaseGenerator,
|
||||
SqlExpressionResolver sqlExpressionResolver,
|
||||
Supplier<Consumer<Predicate>> additionalPredicateCollectorAccess,
|
||||
SqlAstCreationContext creationContext) {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
}
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* 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.metamodel.mapping;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface EntityDiscriminatorMapping extends VirtualModelPart, BasicValuedModelPart {
|
||||
String ROLE_NAME = "{discriminator}";
|
||||
}
|
|
@ -33,6 +33,10 @@ public interface EntityMappingType extends ManagedMappingType {
|
|||
|
||||
EntityVersionMapping getVersionMapping();
|
||||
|
||||
default EntityDiscriminatorMapping getDiscriminatorMapping() {
|
||||
return null;
|
||||
}
|
||||
|
||||
NaturalIdMapping getNaturalIdMapping();
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* 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.metamodel.mapping;
|
||||
|
||||
/**
|
||||
* Marker interface for parts of the application domain model that are virtual - do not
|
||||
* actually exist in the model classes
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface VirtualModelPart extends ModelPart {
|
||||
}
|
|
@ -121,8 +121,8 @@ public class BasicValuedSingularAttributeMapping extends AbstractSingularAttribu
|
|||
getMappedColumnExpression()
|
||||
),
|
||||
sqlAstProcessingState -> new ColumnReference(
|
||||
getMappedColumnExpression(),
|
||||
tableReference.getIdentificationVariable(),
|
||||
getMappedColumnExpression(),
|
||||
jdbcMapping,
|
||||
creationState.getSqlAstCreationState().getCreationContext().getSessionFactory()
|
||||
)
|
||||
|
@ -149,8 +149,8 @@ public class BasicValuedSingularAttributeMapping extends AbstractSingularAttribu
|
|||
getMappedColumnExpression()
|
||||
),
|
||||
sqlAstProcessingState -> new ColumnReference(
|
||||
getMappedColumnExpression(),
|
||||
tableReference.getIdentificationVariable(),
|
||||
getMappedColumnExpression(),
|
||||
jdbcMapping,
|
||||
creationState.getSqlAstCreationState().getCreationContext().getSessionFactory()
|
||||
)
|
||||
|
|
|
@ -189,8 +189,8 @@ public class EmbeddedAttributeMapping
|
|||
attrColumnExpr
|
||||
),
|
||||
sqlAstProcessingState -> new ColumnReference(
|
||||
attrColumnExpr,
|
||||
tableReference.getIdentificationVariable(),
|
||||
attrColumnExpr,
|
||||
jdbcMapping,
|
||||
sqlAstCreationState.getCreationContext().getSessionFactory()
|
||||
)
|
||||
|
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* 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.metamodel.mapping.internal;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.engine.FetchStrategy;
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
|
||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.metamodel.mapping.MappingType;
|
||||
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.sqm.sql.SqlAstCreationState;
|
||||
import org.hibernate.query.sqm.sql.SqlExpressionResolver;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
import org.hibernate.sql.ast.tree.from.TableReference;
|
||||
import org.hibernate.sql.results.internal.domain.basic.BasicFetch;
|
||||
import org.hibernate.sql.results.spi.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.spi.Fetch;
|
||||
import org.hibernate.sql.results.spi.FetchParent;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class EntityDiscriminatorMappingImpl implements EntityDiscriminatorMapping {
|
||||
private final EntityPersister entityDescriptor;
|
||||
|
||||
private final String tableExpression;
|
||||
private final String mappedColumnExpression;
|
||||
|
||||
private final BasicType mappingType;
|
||||
|
||||
public EntityDiscriminatorMappingImpl(
|
||||
EntityPersister entityDescriptor,
|
||||
String tableExpression,
|
||||
String mappedColumnExpression,
|
||||
BasicType mappingType) {
|
||||
this.entityDescriptor = entityDescriptor;
|
||||
this.tableExpression = tableExpression;
|
||||
this.mappedColumnExpression = mappedColumnExpression;
|
||||
this.mappingType = mappingType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContainingTableExpression() {
|
||||
return tableExpression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMappedColumnExpression() {
|
||||
return mappedColumnExpression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BasicValueConverter getConverter() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFetchableName() {
|
||||
return ROLE_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchStrategy getMappedFetchStrategy() {
|
||||
return FetchStrategy.IMMEDIATE_JOIN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fetch generateFetch(
|
||||
FetchParent fetchParent,
|
||||
NavigablePath fetchablePath,
|
||||
FetchTiming fetchTiming,
|
||||
boolean selected,
|
||||
LockMode lockMode,
|
||||
String resultVariable,
|
||||
DomainResultCreationState creationState) {
|
||||
final SqlAstCreationState sqlAstCreationState = creationState.getSqlAstCreationState();
|
||||
final TableGroup tableGroup = sqlAstCreationState.getFromClauseAccess().getTableGroup(
|
||||
fetchParent.getNavigablePath()
|
||||
);
|
||||
|
||||
assert tableGroup != null;
|
||||
|
||||
final SqlSelection sqlSelection = resolveSqlSelection( tableGroup, creationState );
|
||||
|
||||
return new BasicFetch(
|
||||
sqlSelection.getValuesArrayPosition(),
|
||||
fetchParent,
|
||||
fetchablePath,
|
||||
this,
|
||||
false,
|
||||
getConverter(),
|
||||
fetchTiming,
|
||||
creationState
|
||||
);
|
||||
}
|
||||
private SqlSelection resolveSqlSelection(TableGroup tableGroup, DomainResultCreationState creationState) {
|
||||
final SqlExpressionResolver expressionResolver = creationState.getSqlAstCreationState().getSqlExpressionResolver();
|
||||
|
||||
final TableReference tableReference = tableGroup.resolveTableReference( getContainingTableExpression() );
|
||||
|
||||
return expressionResolver.resolveSqlSelection(
|
||||
expressionResolver.resolveSqlExpression(
|
||||
SqlExpressionResolver.createColumnReferenceKey(
|
||||
tableReference,
|
||||
getMappedColumnExpression()
|
||||
),
|
||||
sqlAstProcessingState -> new ColumnReference(
|
||||
tableReference.getIdentificationVariable(),
|
||||
getMappedColumnExpression(),
|
||||
mappingType.getJdbcMapping(),
|
||||
creationState.getSqlAstCreationState().getCreationContext().getSessionFactory()
|
||||
)
|
||||
),
|
||||
getMappedTypeDescriptor().getMappedJavaTypeDescriptor(),
|
||||
creationState.getSqlAstCreationState().getCreationContext().getDomainModel().getTypeConfiguration()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaTypeDescriptor getJavaTypeDescriptor() {
|
||||
return getMappedTypeDescriptor().getMappedJavaTypeDescriptor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappingType getMappedTypeDescriptor() {
|
||||
return mappingType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JdbcMapping getJdbcMapping() {
|
||||
return mappingType.getJdbcMapping();
|
||||
}
|
||||
}
|
|
@ -135,8 +135,8 @@ public class MappingModelCreationHelper {
|
|||
final Expression expression = expressionResolver.resolveSqlExpression(
|
||||
SqlExpressionResolver.createColumnReferenceKey( rootTableReference, pkColumnName ),
|
||||
sqlAstProcessingState -> new ColumnReference(
|
||||
pkColumnName,
|
||||
rootTableReference.getIdentificationVariable(),
|
||||
pkColumnName,
|
||||
( (BasicValuedMapping) entityPersister.getIdentifierType() ).getJdbcMapping(),
|
||||
creationProcess.getCreationContext().getSessionFactory()
|
||||
)
|
||||
|
@ -167,8 +167,8 @@ public class MappingModelCreationHelper {
|
|||
final Expression expression = expressionResolver.resolveSqlExpression(
|
||||
SqlExpressionResolver.createColumnReferenceKey( rootTableReference, pkColumnName ),
|
||||
sqlAstProcessingState -> new ColumnReference(
|
||||
pkColumnName,
|
||||
rootTable,
|
||||
pkColumnName,
|
||||
( (BasicValuedModelPart) entityPersister.getIdentifierType() ).getJdbcMapping(),
|
||||
creationProcess.getCreationContext().getSessionFactory()
|
||||
)
|
||||
|
|
|
@ -31,6 +31,7 @@ import java.util.TreeSet;
|
|||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.EntityMode;
|
||||
|
@ -104,7 +105,6 @@ import org.hibernate.internal.CoreMessageLogger;
|
|||
import org.hibernate.internal.FilterHelper;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.jdbc.Expectation;
|
||||
import org.hibernate.jdbc.Expectations;
|
||||
import org.hibernate.jdbc.TooManyRowsAffectedException;
|
||||
|
@ -134,6 +134,7 @@ import org.hibernate.metadata.ClassMetadata;
|
|||
import org.hibernate.metamodel.RepresentationMode;
|
||||
import org.hibernate.metamodel.mapping.AttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.AttributeMetadata;
|
||||
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.metamodel.mapping.EntityVersionMapping;
|
||||
|
@ -144,6 +145,7 @@ import org.hibernate.metamodel.mapping.NaturalIdMapping;
|
|||
import org.hibernate.metamodel.mapping.Queryable;
|
||||
import org.hibernate.metamodel.mapping.StateArrayContributorMapping;
|
||||
import org.hibernate.metamodel.mapping.StateArrayContributorMetadata;
|
||||
import org.hibernate.metamodel.mapping.internal.EntityDiscriminatorMappingImpl;
|
||||
import org.hibernate.metamodel.mapping.internal.InFlightEntityMappingType;
|
||||
import org.hibernate.metamodel.mapping.internal.MappingModelCreationHelper;
|
||||
import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess;
|
||||
|
@ -179,6 +181,7 @@ import org.hibernate.sql.ast.spi.SqlAliasStemHelper;
|
|||
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
||||
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.expression.QueryLiteral;
|
||||
import org.hibernate.sql.ast.tree.from.StandardTableGroup;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
import org.hibernate.sql.ast.tree.from.TableReference;
|
||||
|
@ -1180,6 +1183,7 @@ public abstract class AbstractEntityPersister
|
|||
LockMode lockMode,
|
||||
SqlAliasBaseGenerator aliasBaseGenerator,
|
||||
SqlExpressionResolver sqlExpressionResolver,
|
||||
Supplier<Consumer<Predicate>> additionalPredicateCollectorAccess,
|
||||
SqlAstCreationContext creationContext) {
|
||||
final SqlAliasBase sqlAliasBase = aliasBaseGenerator.createSqlAliasBase( getSqlAliasStem() );
|
||||
|
||||
|
@ -1274,8 +1278,8 @@ public abstract class AbstractEntityPersister
|
|||
rootPkColumnName
|
||||
),
|
||||
sqlAstProcessingState -> new ColumnReference(
|
||||
rootPkColumnName,
|
||||
rootTableReference.getIdentificationVariable(),
|
||||
rootPkColumnName,
|
||||
jdbcMapping,
|
||||
getFactory()
|
||||
)
|
||||
|
@ -1288,8 +1292,8 @@ public abstract class AbstractEntityPersister
|
|||
fkColumnName
|
||||
),
|
||||
sqlAstProcessingState -> new ColumnReference(
|
||||
fkColumnName,
|
||||
joinedTableReference.getIdentificationVariable(),
|
||||
fkColumnName,
|
||||
jdbcMapping,
|
||||
getFactory()
|
||||
)
|
||||
|
@ -5404,18 +5408,22 @@ public abstract class AbstractEntityPersister
|
|||
return this;
|
||||
}
|
||||
else {
|
||||
final String concreteEntityName = getEntityTuplizer().determineConcreteSubclassEntityName(
|
||||
instance,
|
||||
factory
|
||||
);
|
||||
if ( concreteEntityName == null || getEntityName().equals( concreteEntityName ) ) {
|
||||
// the contract of EntityTuplizer.determineConcreteSubclassEntityName says that returning null
|
||||
// is an indication that the specified entity-name (this.getEntityName) should be used.
|
||||
// todo (6.0) : this previously used `org.hibernate.tuple.entity.EntityTuplizer#determineConcreteSubclassEntityName`
|
||||
// - we may need something similar here...
|
||||
|
||||
if ( getRepresentationStrategy().getInstantiator().isInstance( instance, factory ) ) {
|
||||
return this;
|
||||
}
|
||||
else {
|
||||
return factory.getEntityPersister( concreteEntityName );
|
||||
|
||||
if ( hasSubclasses() ) {
|
||||
for ( EntityMappingType sub : subclassMappingTypes.values() ) {
|
||||
if ( sub.getEntityPersister().getRepresentationStrategy().getInstantiator().isInstance( instance, factory ) ) {
|
||||
return sub.getEntityPersister();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6048,6 +6056,7 @@ public abstract class AbstractEntityPersister
|
|||
private EntityIdentifierMapping identifierMapping;
|
||||
private NaturalIdMapping naturalIdMapping;
|
||||
private EntityVersionMapping versionMapping;
|
||||
private EntityDiscriminatorMapping discriminatorMapping;
|
||||
|
||||
private SortedMap<String, AttributeMapping> declaredAttributeMappings = new TreeMap<>();
|
||||
private Collection<AttributeMapping> attributeMappings;
|
||||
|
@ -6088,6 +6097,18 @@ public abstract class AbstractEntityPersister
|
|||
);
|
||||
}
|
||||
|
||||
if ( getDiscriminatorType() == null ) {
|
||||
discriminatorMapping = null;
|
||||
}
|
||||
else {
|
||||
discriminatorMapping = new EntityDiscriminatorMappingImpl(
|
||||
this,
|
||||
getRootTableName(),
|
||||
getDiscriminatorColumnName(),
|
||||
(BasicType) getDiscriminatorType()
|
||||
);
|
||||
}
|
||||
|
||||
final EntityMetamodel currentEntityMetamodel = this.getEntityMetamodel();
|
||||
|
||||
int stateArrayPosition = superMappingType == null ? 0 : superMappingType.getNumberOfAttributeMappings();
|
||||
|
@ -6285,6 +6306,11 @@ public abstract class AbstractEntityPersister
|
|||
return versionMapping;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityDiscriminatorMapping getDiscriminatorMapping() {
|
||||
return discriminatorMapping;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<AttributeMapping> getAttributeMappings() {
|
||||
if ( attributeMappings == null ) {
|
||||
|
|
|
@ -14,8 +14,11 @@ import java.util.Iterator;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.boot.model.relational.Database;
|
||||
import org.hibernate.cache.spi.access.EntityDataAccess;
|
||||
|
@ -37,10 +40,23 @@ import org.hibernate.mapping.Subclass;
|
|||
import org.hibernate.mapping.Table;
|
||||
import org.hibernate.mapping.Value;
|
||||
import org.hibernate.persister.spi.PersisterCreationContext;
|
||||
import org.hibernate.query.ComparisonOperator;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.sqm.sql.SqlExpressionResolver;
|
||||
import org.hibernate.sql.InFragment;
|
||||
import org.hibernate.sql.Insert;
|
||||
import org.hibernate.sql.SelectFragment;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
import org.hibernate.sql.ast.JoinType;
|
||||
import org.hibernate.sql.ast.spi.SqlAliasBaseGenerator;
|
||||
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
||||
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
||||
import org.hibernate.sql.ast.tree.expression.QueryLiteral;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
import org.hibernate.sql.ast.tree.predicate.ComparisonPredicate;
|
||||
import org.hibernate.sql.ast.tree.predicate.Predicate;
|
||||
import org.hibernate.type.AssociationType;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.DiscriminatorType;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
|
@ -847,4 +863,60 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
public FilterAliasGenerator getFilterAliasGenerator(String rootAlias) {
|
||||
return new DynamicFilterAliasGenerator( qualifiedTableNames, rootAlias );
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableGroup createRootTableGroup(
|
||||
NavigablePath navigablePath,
|
||||
String explicitSourceAlias,
|
||||
JoinType tableReferenceJoinType,
|
||||
LockMode lockMode,
|
||||
SqlAliasBaseGenerator aliasBaseGenerator,
|
||||
SqlExpressionResolver sqlExpressionResolver,
|
||||
Supplier<Consumer<Predicate>> additionalPredicateCollectorAccess,
|
||||
SqlAstCreationContext creationContext) {
|
||||
final TableGroup tableGroup = super.createRootTableGroup(
|
||||
navigablePath,
|
||||
explicitSourceAlias,
|
||||
tableReferenceJoinType,
|
||||
lockMode,
|
||||
aliasBaseGenerator,
|
||||
sqlExpressionResolver,
|
||||
additionalPredicateCollectorAccess,
|
||||
creationContext
|
||||
);
|
||||
|
||||
if ( needsDiscriminator() ) {
|
||||
final Predicate discriminatorPredicate = createDiscriminatorPredicate(
|
||||
tableGroup,
|
||||
sqlExpressionResolver,
|
||||
creationContext
|
||||
);
|
||||
additionalPredicateCollectorAccess.get().accept( discriminatorPredicate );
|
||||
}
|
||||
|
||||
return tableGroup;
|
||||
}
|
||||
|
||||
private Predicate createDiscriminatorPredicate(
|
||||
TableGroup tableGroup,
|
||||
SqlExpressionResolver sqlExpressionResolver,
|
||||
SqlAstCreationContext creationContext) {
|
||||
return new ComparisonPredicate(
|
||||
sqlExpressionResolver.resolveSqlExpression(
|
||||
SqlExpressionResolver.createColumnReferenceKey( tableGroup.getPrimaryTableReference(), getDiscriminatorColumnName() ),
|
||||
sqlAstProcessingState -> new ColumnReference(
|
||||
tableGroup.getPrimaryTableReference().getIdentificationVariable(),
|
||||
getDiscriminatorColumnName(),
|
||||
( (BasicType) getDiscriminatorType() ).getJdbcMapping(),
|
||||
getFactory()
|
||||
)
|
||||
),
|
||||
ComparisonOperator.EQUAL,
|
||||
new QueryLiteral<>(
|
||||
getDiscriminatorValue(),
|
||||
( (BasicType) getDiscriminatorType() ),
|
||||
Clause.WHERE
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ public final class PersisterFactoryImpl implements PersisterFactory, ServiceRegi
|
|||
/**
|
||||
* The constructor signature for {@link EntityPersister} implementations
|
||||
*/
|
||||
@SuppressWarnings({"WeakerAccess", "deprecation"})
|
||||
public static final Class[] ENTITY_PERSISTER_CONSTRUCTOR_ARGS = new Class[] {
|
||||
PersistentClass.class,
|
||||
EntityDataAccess.class,
|
||||
|
@ -47,6 +48,7 @@ public final class PersisterFactoryImpl implements PersisterFactory, ServiceRegi
|
|||
/**
|
||||
* The constructor signature for {@link CollectionPersister} implementations
|
||||
*/
|
||||
@SuppressWarnings({"WeakerAccess", "deprecation"})
|
||||
public static final Class[] COLLECTION_PERSISTER_CONSTRUCTOR_ARGS = new Class[] {
|
||||
Collection.class,
|
||||
CollectionDataAccess.class,
|
||||
|
@ -66,7 +68,7 @@ public final class PersisterFactoryImpl implements PersisterFactory, ServiceRegi
|
|||
PersistentClass entityBinding,
|
||||
EntityDataAccess entityCacheAccessStrategy,
|
||||
NaturalIdDataAccess naturalIdCacheAccessStrategy,
|
||||
PersisterCreationContext creationContext) throws HibernateException {
|
||||
@SuppressWarnings("deprecation") PersisterCreationContext creationContext) throws HibernateException {
|
||||
// If the metadata for the entity specified an explicit persister class, use it...
|
||||
Class<? extends EntityPersister> persisterClass = entityBinding.getEntityPersisterClass();
|
||||
if ( persisterClass == null ) {
|
||||
|
@ -83,13 +85,12 @@ public final class PersisterFactoryImpl implements PersisterFactory, ServiceRegi
|
|||
);
|
||||
}
|
||||
|
||||
@SuppressWarnings( {"unchecked"})
|
||||
private EntityPersister createEntityPersister(
|
||||
Class<? extends EntityPersister> persisterClass,
|
||||
PersistentClass entityBinding,
|
||||
EntityDataAccess entityCacheAccessStrategy,
|
||||
NaturalIdDataAccess naturalIdCacheAccessStrategy,
|
||||
PersisterCreationContext creationContext) {
|
||||
@SuppressWarnings("deprecation") PersisterCreationContext creationContext) {
|
||||
try {
|
||||
final Constructor<? extends EntityPersister> constructor = persisterClass.getConstructor( ENTITY_PERSISTER_CONSTRUCTOR_ARGS );
|
||||
try {
|
||||
|
@ -116,7 +117,7 @@ public final class PersisterFactoryImpl implements PersisterFactory, ServiceRegi
|
|||
throw new MappingException( "Could not instantiate persister " + persisterClass.getName(), e );
|
||||
}
|
||||
}
|
||||
catch (MappingException e) {
|
||||
catch (HibernateException e) {
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e) {
|
||||
|
@ -129,7 +130,7 @@ public final class PersisterFactoryImpl implements PersisterFactory, ServiceRegi
|
|||
public CollectionPersister createCollectionPersister(
|
||||
Collection collectionBinding,
|
||||
CollectionDataAccess cacheAccessStrategy,
|
||||
PersisterCreationContext creationContext) throws HibernateException {
|
||||
@SuppressWarnings("deprecation") PersisterCreationContext creationContext) throws HibernateException {
|
||||
// If the metadata for the collection specified an explicit persister class, use it
|
||||
Class<? extends CollectionPersister> persisterClass = collectionBinding.getCollectionPersisterClass();
|
||||
if ( persisterClass == null ) {
|
||||
|
@ -140,12 +141,11 @@ public final class PersisterFactoryImpl implements PersisterFactory, ServiceRegi
|
|||
return createCollectionPersister( persisterClass, collectionBinding, cacheAccessStrategy, creationContext );
|
||||
}
|
||||
|
||||
@SuppressWarnings( {"unchecked"})
|
||||
private CollectionPersister createCollectionPersister(
|
||||
Class<? extends CollectionPersister> persisterClass,
|
||||
Collection collectionBinding,
|
||||
CollectionDataAccess cacheAccessStrategy,
|
||||
PersisterCreationContext creationContext) {
|
||||
@SuppressWarnings("deprecation") PersisterCreationContext creationContext) {
|
||||
try {
|
||||
Constructor<? extends CollectionPersister> constructor = persisterClass.getConstructor( COLLECTION_PERSISTER_CONSTRUCTOR_ARGS );
|
||||
try {
|
||||
|
|
|
@ -96,6 +96,7 @@ import org.hibernate.sql.ast.JoinType;
|
|||
import org.hibernate.sql.ast.spi.FromClauseAccess;
|
||||
import org.hibernate.sql.ast.spi.SqlAliasBaseGenerator;
|
||||
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
||||
import org.hibernate.sql.ast.spi.SqlAstTreeHelper;
|
||||
import org.hibernate.sql.ast.tree.expression.BinaryArithmeticExpression;
|
||||
import org.hibernate.sql.ast.tree.expression.CaseSearchedExpression;
|
||||
import org.hibernate.sql.ast.tree.expression.CaseSimpleExpression;
|
||||
|
@ -278,6 +279,8 @@ public abstract class BaseSqmToSqlAstConverter
|
|||
public QuerySpec visitQuerySpec(SqmQuerySpec sqmQuerySpec) {
|
||||
final QuerySpec sqlQuerySpec = new QuerySpec( processingStateStack.isEmpty(), sqmQuerySpec.getFromClause().getNumberOfRoots() );
|
||||
|
||||
additionalRestrictions = null;
|
||||
|
||||
processingStateStack.push(
|
||||
new SqlAstQuerySpecProcessingStateImpl(
|
||||
sqlQuerySpec,
|
||||
|
@ -308,6 +311,10 @@ public abstract class BaseSqmToSqlAstConverter
|
|||
}
|
||||
}
|
||||
|
||||
if ( additionalRestrictions != null ) {
|
||||
sqlQuerySpec.applyPredicate( additionalRestrictions );
|
||||
}
|
||||
|
||||
// todo : group-by
|
||||
// todo : having
|
||||
|
||||
|
@ -412,6 +419,8 @@ public abstract class BaseSqmToSqlAstConverter
|
|||
return null;
|
||||
}
|
||||
|
||||
Predicate additionalRestrictions;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
protected void consumeFromClauseRoot(SqmRoot<?> sqmRoot) {
|
||||
log.tracef( "Resolving SqmRoot [%s] to TableGroup", sqmRoot );
|
||||
|
@ -427,6 +436,7 @@ public abstract class BaseSqmToSqlAstConverter
|
|||
LockMode.NONE,
|
||||
sqlAliasBaseManager,
|
||||
getSqlExpressionResolver(),
|
||||
() -> predicate -> additionalRestrictions = SqlAstTreeHelper.combinePredicates( additionalRestrictions, predicate ),
|
||||
creationContext
|
||||
);
|
||||
|
||||
|
@ -512,6 +522,7 @@ public abstract class BaseSqmToSqlAstConverter
|
|||
determineLockMode( sqmJoin.getExplicitAlias() ),
|
||||
sqlAliasBaseManager,
|
||||
getSqlExpressionResolver(),
|
||||
() -> predicate -> additionalRestrictions = SqlAstTreeHelper.combinePredicates( additionalRestrictions, predicate ),
|
||||
getCreationContext()
|
||||
);
|
||||
|
||||
|
@ -539,6 +550,7 @@ public abstract class BaseSqmToSqlAstConverter
|
|||
determineLockMode( sqmJoin.getExplicitAlias() ),
|
||||
sqlAliasBaseManager,
|
||||
getSqlExpressionResolver(),
|
||||
() -> predicate -> additionalRestrictions = SqlAstTreeHelper.combinePredicates( additionalRestrictions, predicate ),
|
||||
getCreationContext()
|
||||
);
|
||||
fromClauseIndex.register( sqmJoin, tableGroup );
|
||||
|
|
|
@ -52,8 +52,8 @@ public class BasicValuedPathInterpretation<T> implements AssignableSqmPathInterp
|
|||
mapping.getMappedColumnExpression()
|
||||
),
|
||||
sacs -> new ColumnReference(
|
||||
mapping.getMappedColumnExpression(),
|
||||
tableReference.getIdentificationVariable(),
|
||||
mapping.getMappedColumnExpression(),
|
||||
mapping.getJdbcMapping(),
|
||||
sqlAstCreationState.getCreationContext().getSessionFactory()
|
||||
)
|
||||
|
|
|
@ -29,8 +29,8 @@ public class ColumnReference implements Expression {
|
|||
private final JdbcMapping jdbcMapping;
|
||||
|
||||
public ColumnReference(
|
||||
String columnExpression,
|
||||
String qualifier,
|
||||
String columnExpression,
|
||||
JdbcMapping jdbcMapping,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
this(
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
*/
|
||||
package org.hibernate.sql.ast.tree.from;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.metamodel.mapping.ModelPartContainer;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
|
@ -13,6 +16,7 @@ import org.hibernate.query.sqm.sql.SqlExpressionResolver;
|
|||
import org.hibernate.sql.ast.JoinType;
|
||||
import org.hibernate.sql.ast.spi.SqlAliasBaseGenerator;
|
||||
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
||||
import org.hibernate.sql.ast.tree.predicate.Predicate;
|
||||
|
||||
/**
|
||||
* Contract for things that can produce the {@link TableGroup} that is the root of a
|
||||
|
@ -31,5 +35,6 @@ public interface RootTableGroupProducer extends TableGroupProducer, ModelPartCon
|
|||
LockMode lockMode,
|
||||
SqlAliasBaseGenerator aliasBaseGenerator,
|
||||
SqlExpressionResolver sqlExpressionResolver,
|
||||
Supplier<Consumer<Predicate>> additionalPredicateCollectorAccess,
|
||||
SqlAstCreationContext creationContext);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,238 @@
|
|||
/*
|
||||
* 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.orm.test.metamodel.mapping;
|
||||
|
||||
import java.util.List;
|
||||
import javax.persistence.DiscriminatorColumn;
|
||||
import javax.persistence.DiscriminatorValue;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Inheritance;
|
||||
import javax.persistence.InheritanceType;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.FailureExpected;
|
||||
import org.hibernate.testing.orm.junit.ServiceRegistry;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.hamcrest.CoreMatchers;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
@DomainModel(
|
||||
annotatedClasses = {
|
||||
InheritanceTests.Customer.class,
|
||||
InheritanceTests.DomesticCustomer.class,
|
||||
InheritanceTests.ForeignCustomer.class
|
||||
}
|
||||
)
|
||||
@ServiceRegistry
|
||||
@SessionFactory
|
||||
public class InheritanceTests {
|
||||
@Test
|
||||
public void basicTest(SessionFactoryScope scope) {
|
||||
final EntityPersister customerDescriptor = scope.getSessionFactory()
|
||||
.getMetamodel()
|
||||
.findEntityDescriptor( Customer.class );
|
||||
final EntityPersister domesticCustomerDescriptor = scope.getSessionFactory()
|
||||
.getMetamodel()
|
||||
.findEntityDescriptor( DomesticCustomer.class );
|
||||
final EntityPersister foreignCustomerDescriptor = scope.getSessionFactory()
|
||||
.getMetamodel()
|
||||
.findEntityDescriptor( ForeignCustomer.class );
|
||||
|
||||
assert customerDescriptor.isTypeOrSuperType( customerDescriptor );
|
||||
assert ! customerDescriptor.isTypeOrSuperType( domesticCustomerDescriptor );
|
||||
assert ! customerDescriptor.isTypeOrSuperType( foreignCustomerDescriptor );
|
||||
|
||||
assert domesticCustomerDescriptor.isTypeOrSuperType( customerDescriptor );
|
||||
assert domesticCustomerDescriptor.isTypeOrSuperType( domesticCustomerDescriptor );
|
||||
assert ! domesticCustomerDescriptor.isTypeOrSuperType( foreignCustomerDescriptor );
|
||||
|
||||
assert foreignCustomerDescriptor.isTypeOrSuperType( customerDescriptor );
|
||||
assert ! foreignCustomerDescriptor.isTypeOrSuperType( domesticCustomerDescriptor );
|
||||
assert foreignCustomerDescriptor.isTypeOrSuperType( foreignCustomerDescriptor );
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
public void createTestData(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
session.persist( new DomesticCustomer( 1, "domestic", "123" ) );
|
||||
session.persist( new ForeignCustomer( 2, "foreign", "987" ) );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void cleanupTestData(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
session.createQuery( "from DomesticCustomer", DomesticCustomer.class ).list().forEach(
|
||||
cust -> session.delete( cust )
|
||||
);
|
||||
session.createQuery( "from ForeignCustomer", ForeignCustomer.class ).list().forEach(
|
||||
cust -> session.delete( cust )
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
@FailureExpected
|
||||
public void rootQueryExecutionTest(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
{
|
||||
final List<Customer> results = session.createQuery(
|
||||
"select c from Customer c",
|
||||
Customer.class
|
||||
).list();
|
||||
|
||||
assertThat( results.size(), is( 2 ) );
|
||||
|
||||
for ( Customer result : results ) {
|
||||
if ( result.getId() == 1 ) {
|
||||
assertThat( result, instanceOf( DomesticCustomer.class ) );
|
||||
assertThat( ( (DomesticCustomer) result ).getTaxId(), is( "123" ) );
|
||||
}
|
||||
else {
|
||||
assertThat( result.getId(), is( 2 ) );
|
||||
assertThat( ( (ForeignCustomer) result ).getVat(), is( "987" ) );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subclassQueryExecutionTest(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
{
|
||||
final DomesticCustomer result = session.createQuery(
|
||||
"select c from DomesticCustomer c",
|
||||
DomesticCustomer.class
|
||||
).uniqueResult();
|
||||
|
||||
assertThat( result, notNullValue() );
|
||||
assertThat( result.getId(), is( 1 ) );
|
||||
assertThat( result.getName(), is( "domestic" ) );
|
||||
assertThat( result.getTaxId(), is( "123" ) );
|
||||
}
|
||||
|
||||
{
|
||||
final ForeignCustomer result = session.createQuery(
|
||||
"select c from ForeignCustomer c",
|
||||
ForeignCustomer.class
|
||||
).uniqueResult();
|
||||
|
||||
assertThat( result, notNullValue() );
|
||||
assertThat( result.getId(), is( 2 ) );
|
||||
assertThat( result.getName(), is( "foreign" ) );
|
||||
assertThat( result.getVat(), is( "987" ) );
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Entity( name = "Customer" )
|
||||
@Inheritance( strategy = InheritanceType.SINGLE_TABLE )
|
||||
@Table( name = "customer" )
|
||||
@DiscriminatorColumn( name = "cust_type" )
|
||||
public static abstract class Customer {
|
||||
private Integer id;
|
||||
private String name;
|
||||
|
||||
public Customer() {
|
||||
}
|
||||
|
||||
public Customer(Integer id, String name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Id
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity( name = "DomesticCustomer" )
|
||||
@DiscriminatorValue( "dc" )
|
||||
public static class DomesticCustomer extends Customer {
|
||||
private String taxId;
|
||||
|
||||
public DomesticCustomer() {
|
||||
}
|
||||
|
||||
public DomesticCustomer(Integer id, String name, String taxId) {
|
||||
super( id, name );
|
||||
this.taxId = taxId;
|
||||
}
|
||||
|
||||
public String getTaxId() {
|
||||
return taxId;
|
||||
}
|
||||
|
||||
public void setTaxId(String taxId) {
|
||||
this.taxId = taxId;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity( name = "ForeignCustomer" )
|
||||
@DiscriminatorValue( "fc" )
|
||||
public static class ForeignCustomer extends Customer {
|
||||
private String vat;
|
||||
|
||||
public ForeignCustomer() {
|
||||
}
|
||||
|
||||
public ForeignCustomer(Integer id, String name, String vat) {
|
||||
super( id, name );
|
||||
this.vat = vat;
|
||||
}
|
||||
|
||||
public String getVat() {
|
||||
return vat;
|
||||
}
|
||||
|
||||
public void setVat(String vat) {
|
||||
this.vat = vat;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -25,5 +25,3 @@ javax.persistence.validation.mode=NONE
|
|||
hibernate.service.allow_crawling=false
|
||||
hibernate.session.events.log=true
|
||||
hibernate.hql.bulk_id_strategy.global_temporary.drop_tables=true
|
||||
|
||||
hibernate.bytecode.use_reflection_optimizer=true
|
Loading…
Reference in New Issue