implement @Formula

This commit is contained in:
Nathan Xu 2020-04-25 16:32:15 -04:00 committed by Steve Ebersole
parent e10992e4fc
commit 40575125f1
55 changed files with 812 additions and 462 deletions

View File

@ -99,7 +99,7 @@ class DatabaseSnapshotExecutor {
final List<DomainResult> domainResults = new ArrayList<>();
entityDescriptor.getIdentifierMapping().visitColumns(
(tab, col, jdbcMapping) -> {
(tab, col, isColFormula, jdbcMapping) -> {
final TableReference tableReference = rootTableGroup.resolveTableReference( tab );
final JdbcParameter jdbcParameter = new JdbcParameterImpl( jdbcMapping );
@ -111,6 +111,7 @@ class DatabaseSnapshotExecutor {
s -> new ColumnReference(
tableReference,
col,
isColFormula,
jdbcMapping,
sessionFactory
)
@ -145,7 +146,7 @@ class DatabaseSnapshotExecutor {
contributorMapping -> {
rootPath.append( contributorMapping.getAttributeName() );
contributorMapping.visitColumns(
(containingTableExpression, columnExpression, jdbcMapping) -> {
(containingTableExpression, columnExpression, isColumnExpressionFormula, jdbcMapping) -> {
final TableReference tableReference = rootTableGroup.resolveTableReference(
containingTableExpression );
@ -158,6 +159,7 @@ class DatabaseSnapshotExecutor {
s -> new ColumnReference(
tableReference,
columnExpression,
isColumnExpressionFormula,
jdbcMapping,
sessionFactory
)

View File

@ -327,6 +327,7 @@ public class LoaderSelectBuilder {
p -> new ColumnReference(
tableReference,
columnExpression,
false,
jdbcMapping,
creationContext.getSessionFactory()
)
@ -356,7 +357,7 @@ public class LoaderSelectBuilder {
final List<ColumnReference> columnReferences = new ArrayList<>( numberOfKeyColumns );
keyPart.visitColumns(
(containingTableExpression, columnExpression, jdbcMapping) -> {
(containingTableExpression, columnExpression, isColumnExpressionFormula, jdbcMapping) -> {
final TableReference tableReference = rootTableGroup.resolveTableReference( containingTableExpression );
columnReferences.add(
(ColumnReference) sqlExpressionResolver.resolveSqlExpression(
@ -364,6 +365,7 @@ public class LoaderSelectBuilder {
p -> new ColumnReference(
tableReference,
columnExpression,
isColumnExpressionFormula,
jdbcMapping,
creationContext.getSessionFactory()
)
@ -683,6 +685,7 @@ public class LoaderSelectBuilder {
sqlAstProcessingState -> new ColumnReference(
rootTableGroup.resolveTableReference( simpleFkDescriptor.getContainingTableExpression() ),
simpleFkDescriptor.getMappedColumnExpression(),
false,
simpleFkDescriptor.getJdbcMapping(),
this.creationContext.getSessionFactory()
)
@ -691,13 +694,14 @@ public class LoaderSelectBuilder {
else {
final List<ColumnReference> columnReferences = new ArrayList<>( jdbcTypeCount );
fkDescriptor.visitColumns(
(containingTableExpression, columnExpression, jdbcMapping) ->
(containingTableExpression, columnExpression, isColumnExpressionFormula, jdbcMapping) ->
columnReferences.add(
(ColumnReference) sqlAstCreationState.getSqlExpressionResolver().resolveSqlExpression(
createColumnReferenceKey( containingTableExpression, columnExpression ),
sqlAstProcessingState -> new ColumnReference(
rootTableGroup.resolveTableReference( containingTableExpression ),
columnExpression,
isColumnExpressionFormula,
jdbcMapping,
this.creationContext.getSessionFactory()
)
@ -747,7 +751,7 @@ public class LoaderSelectBuilder {
final MutableInteger count = new MutableInteger();
fkDescriptor.visitTargetColumns(
(containingTableExpression, columnExpression, jdbcMapping) -> {
(containingTableExpression, columnExpression, isColumnExpressionFormula, jdbcMapping) -> {
// for each column, resolve a SqlSelection and add it to the sub-query select-clause
final TableReference tableReference = ownerTableGroup.resolveTableReference( containingTableExpression );
final Expression expression = sqlExpressionResolver.resolveSqlExpression(
@ -755,6 +759,7 @@ public class LoaderSelectBuilder {
sqlAstProcessingState -> new ColumnReference(
tableReference,
columnExpression,
isColumnExpressionFormula,
jdbcMapping,
sessionFactory
)

View File

@ -24,6 +24,10 @@ public interface BasicValuedModelPart extends BasicValuedMapping, ModelPart, Fet
*/
String getMappedColumnExpression();
default boolean isMappedColumnExpressionFormula() {
return false;
}
@Override
default MappingType getPartMappingType() {
return this::getJavaTypeDescriptor;

View File

@ -15,5 +15,6 @@ public interface ColumnConsumer {
void accept(
String containingTableExpression,
String columnExpression,
boolean isColumnExpressionFormula,
JdbcMapping jdbcMapping);
}

View File

@ -177,6 +177,7 @@ public class EmbeddableMappingType implements ManagedMappingType {
(BasicType) subtype,
containingTableExpression,
mappedColumnExpressions.get( columnPosition++ ),
false,
representationStrategy.resolvePropertyAccess( bootPropertyDescriptor ),
compositeType.getCascadeStyle( attributeIndex ),
creationProcess

View File

@ -34,6 +34,7 @@ public class MappingModelHelper {
return new ColumnReference(
basicPart.getContainingTableExpression(),
basicPart.getMappedColumnExpression(),
basicPart.isMappedColumnExpressionFormula(),
basicPart.getJdbcMapping(),
sessionFactory
);
@ -44,6 +45,7 @@ public class MappingModelHelper {
sqlAstProcessingState -> new ColumnReference(
basicPart.getContainingTableExpression(),
basicPart.getMappedColumnExpression(),
basicPart.isMappedColumnExpressionFormula(),
basicPart.getJdbcMapping(),
sessionFactory
)
@ -53,12 +55,13 @@ public class MappingModelHelper {
else {
final List<ColumnReference> columnReferences = new ArrayList<>( jdbcTypeCount );
modelPart.visitColumns(
(containingTableExpression, columnExpression, jdbcMapping) -> {
(containingTableExpression, columnExpression, isColumnExpressionFormula, jdbcMapping) -> {
final ColumnReference colRef;
if ( sqlExpressionResolver == null ) {
colRef = new ColumnReference(
containingTableExpression,
columnExpression,
isColumnExpressionFormula,
jdbcMapping,
sessionFactory
);
@ -69,6 +72,7 @@ public class MappingModelHelper {
sqlAstProcessingState -> new ColumnReference(
containingTableExpression,
columnExpression,
isColumnExpressionFormula,
jdbcMapping,
sessionFactory
)

View File

@ -125,7 +125,7 @@ public class BasicEntityIdentifierMappingImpl implements BasicEntityIdentifierMa
@Override
public void visitColumns(ColumnConsumer consumer) {
consumer.accept( getContainingTableExpression(), getMappedColumnExpression(), getJdbcMapping() );
consumer.accept( getContainingTableExpression(), getMappedColumnExpression(), false, getJdbcMapping() );
}
@Override
@ -190,6 +190,7 @@ public class BasicEntityIdentifierMappingImpl implements BasicEntityIdentifierMa
sqlAstProcessingState -> new ColumnReference(
rootTableReference.getIdentificationVariable(),
pkColumnName,
false,
( (BasicValuedMapping) entityPersister.getIdentifierType() ).getJdbcMapping(),
sessionFactory
)
@ -224,6 +225,7 @@ public class BasicEntityIdentifierMappingImpl implements BasicEntityIdentifierMa
sqlAstProcessingState -> new ColumnReference(
rootTable,
pkColumnName,
false,
( (BasicValuedModelPart) entityPersister.getIdentifierType() ).getJdbcMapping(),
sessionFactory
)

View File

@ -131,6 +131,7 @@ public class BasicValuedCollectionPart
sqlAstProcessingState -> new ColumnReference(
tableGroup.getPrimaryTableReference().getIdentificationVariable(),
columnExpression,
false,
mapper,
creationState.getSqlAstCreationState().getCreationContext().getSessionFactory()
)

View File

@ -9,9 +9,11 @@ package org.hibernate.metamodel.mapping.internal;
import java.util.function.Consumer;
import org.hibernate.LockMode;
import org.hibernate.MappingException;
import org.hibernate.engine.FetchStrategy;
import org.hibernate.engine.FetchTiming;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
import org.hibernate.metamodel.mapping.ColumnConsumer;
import org.hibernate.metamodel.mapping.ConvertibleModelPart;
@ -24,6 +26,7 @@ import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
import org.hibernate.metamodel.model.domain.NavigableRole;
import org.hibernate.property.access.spi.PropertyAccess;
import org.hibernate.query.NavigablePath;
import org.hibernate.sql.Template;
import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.spi.SqlAstCreationState;
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
@ -50,6 +53,7 @@ public class BasicValuedSingularAttributeMapping
private final NavigableRole navigableRole;
private final String tableExpression;
private final String mappedColumnExpression;
private final boolean isMappedColumnExpressionFormula;
private final JdbcMapping jdbcMapping;
private final BasicValueConverter valueConverter;
@ -65,6 +69,7 @@ public class BasicValuedSingularAttributeMapping
FetchStrategy mappedFetchStrategy,
String tableExpression,
String mappedColumnExpression,
boolean isMappedColumnExpressionFormula,
BasicValueConverter valueConverter,
JdbcMapping jdbcMapping,
ManagedMappingType declaringType,
@ -73,6 +78,7 @@ public class BasicValuedSingularAttributeMapping
this.navigableRole = navigableRole;
this.tableExpression = tableExpression;
this.mappedColumnExpression = mappedColumnExpression;
this.isMappedColumnExpressionFormula = isMappedColumnExpressionFormula;
this.valueConverter = valueConverter;
this.jdbcMapping = jdbcMapping;
@ -104,6 +110,11 @@ public class BasicValuedSingularAttributeMapping
return mappedColumnExpression;
}
@Override
public boolean isMappedColumnExpressionFormula() {
return isMappedColumnExpressionFormula;
}
@Override
public String getContainingTableExpression() {
return tableExpression;
@ -142,15 +153,18 @@ public class BasicValuedSingularAttributeMapping
final TableReference tableReference = tableGroup.resolveTableReference( getContainingTableExpression() );
final String tableAlias = tableReference.getIdentificationVariable();
final String columnExpression = getMappedColumnExpression();
return expressionResolver.resolveSqlSelection(
expressionResolver.resolveSqlExpression(
SqlExpressionResolver.createColumnReferenceKey(
tableReference,
getMappedColumnExpression()
columnExpression
),
sqlAstProcessingState -> new ColumnReference(
tableReference.getIdentificationVariable(),
getMappedColumnExpression(),
tableAlias,
columnExpression,
isMappedColumnExpressionFormula(),
jdbcMapping,
creationState.getSqlAstCreationState().getCreationContext().getSessionFactory()
)
@ -179,6 +193,7 @@ public class BasicValuedSingularAttributeMapping
sqlAstProcessingState -> new ColumnReference(
tableReference.getIdentificationVariable(),
getMappedColumnExpression(),
isMappedColumnExpressionFormula(),
jdbcMapping,
creationState.getSqlAstCreationState().getCreationContext().getSessionFactory()
)
@ -246,6 +261,6 @@ public class BasicValuedSingularAttributeMapping
@Override
public void visitColumns(ColumnConsumer consumer) {
consumer.accept( tableExpression, mappedColumnExpression, jdbcMapping );
consumer.accept( tableExpression, mappedColumnExpression, isMappedColumnExpressionFormula, jdbcMapping );
}
}

View File

@ -138,6 +138,7 @@ public class CollectionIdentifierDescriptorImpl implements CollectionIdentifierD
p -> new ColumnReference(
tableGroup.getPrimaryTableReference().getIdentificationVariable(),
columnName,
false,
type,
sessionFactory
)
@ -176,6 +177,7 @@ public class CollectionIdentifierDescriptorImpl implements CollectionIdentifierD
p -> new ColumnReference(
tableGroup.getPrimaryTableReference().getIdentificationVariable(),
columnName,
false,
type,
sessionFactory
)

View File

@ -217,6 +217,7 @@ public class EmbeddedAttributeMapping
sqlAstProcessingState -> new ColumnReference(
tableReference.getIdentificationVariable(),
attrColumnExpr,
false,
jdbcMapping,
sqlAstCreationState.getCreationContext().getSessionFactory()
)

View File

@ -177,7 +177,7 @@ public class EmbeddedCollectionPart implements CollectionPart, EmbeddableValuedF
final List<Expression> expressions = new ArrayList<>();
getEmbeddableTypeDescriptor().visitColumns(
(tableExpression, columnExpression, jdbcMapping) ->{
(tableExpression, columnExpression, isColumnExpressionFormula, jdbcMapping) ->{
assert containingTableExpression.equals( tableExpression );
assert columnExpressions.contains( columnExpression );
expressions.add(
@ -186,6 +186,7 @@ public class EmbeddedCollectionPart implements CollectionPart, EmbeddableValuedF
sqlAstProcessingState -> new ColumnReference(
tableGroup.resolveTableReference( tableExpression ),
columnExpression,
isColumnExpressionFormula,
jdbcMapping,
sqlAstCreationState.getCreationContext().getSessionFactory()
)

View File

@ -118,6 +118,7 @@ public class EmbeddedForeignKeyDescriptor implements ForeignKeyDescriptor, Model
new ColumnReference(
identificationVariable,
columnExpression,
false,
jdbcMapping,
creationState.getSqlAstCreationState()
.getCreationContext()
@ -169,6 +170,7 @@ public class EmbeddedForeignKeyDescriptor implements ForeignKeyDescriptor, Model
new ColumnReference(
identificationVariable,
columnExpression,
false,
jdbcMapping,
creationState.getSqlAstCreationState()
.getCreationContext()
@ -260,6 +262,7 @@ public class EmbeddedForeignKeyDescriptor implements ForeignKeyDescriptor, Model
new ColumnReference(
lhs,
lhsExpressions.get( i ),
false,
jdbcMapping,
creationContext.getSessionFactory()
),
@ -267,6 +270,7 @@ public class EmbeddedForeignKeyDescriptor implements ForeignKeyDescriptor, Model
new ColumnReference(
rhs,
rhsColumnExpressions.get( i ),
false,
jdbcMapping,
creationContext.getSessionFactory()
)
@ -312,14 +316,14 @@ public class EmbeddedForeignKeyDescriptor implements ForeignKeyDescriptor, Model
@Override
public void visitReferringColumns(ColumnConsumer consumer) {
for ( int i = 0; i < keyColumnExpressions.size(); i++ ) {
consumer.accept( keyColumnContainingTable, keyColumnExpressions.get( i ), jdbcMappings.get( i ) );
consumer.accept( keyColumnContainingTable, keyColumnExpressions.get( i ), false, jdbcMappings.get( i ) );
}
}
@Override
public void visitTargetColumns(ColumnConsumer consumer) {
for ( int i = 0; i < keyColumnExpressions.size(); i++ ) {
consumer.accept( targetColumnContainingTable, targetColumnExpressions.get( i ), jdbcMappings.get( i ) );
consumer.accept( targetColumnContainingTable, targetColumnExpressions.get( i ), false, jdbcMappings.get( i ) );
}
}

View File

@ -227,6 +227,7 @@ public class EmbeddedIdentifierMappingImpl
sqlAstProcessingState -> new ColumnReference(
tableReference.getIdentificationVariable(),
attrColumnExpr,
false,
jdbcMapping,
sqlAstCreationState.getCreationContext().getSessionFactory()
)

View File

@ -49,6 +49,7 @@ public class EntityDiscriminatorMappingImpl extends AbstractEntityDiscriminatorM
sqlAstProcessingState -> new ColumnReference(
tableReference.getIdentificationVariable(),
getMappedColumnExpression(),
false,
getJdbcMapping(),
creationState.getSqlAstCreationState().getCreationContext().getSessionFactory()
)

View File

@ -87,6 +87,7 @@ public class EntityRowIdMappingImpl implements EntityRowIdMapping {
sqlAstProcessingState -> new ColumnReference(
columnTableReference,
rowIdName,
false,
JavaObjectType.INSTANCE,
sqlAstCreationState.getCreationContext().getSessionFactory()
)

View File

@ -142,6 +142,7 @@ public class EntityVersionMappingImpl implements EntityVersionMapping, FetchOpti
sqlAstProcessingState -> new ColumnReference(
columnTableReference,
columnExpression,
false,
versionBasicType,
sqlAstCreationState.getCreationContext().getSessionFactory()
)
@ -179,6 +180,7 @@ public class EntityVersionMappingImpl implements EntityVersionMapping, FetchOpti
sqlAstProcessingState -> new ColumnReference(
columnTableReference,
columnExpression,
false,
versionBasicType,
sqlAstCreationState.getCreationContext().getSessionFactory()
)

View File

@ -204,6 +204,7 @@ public class MappingModelCreationHelper {
(BasicType) idSubPropertyType,
rootTableName,
rootTableKeyColumnNames[columnsConsumedSoFar],
false,
entityPersister.getRepresentationStrategy().resolvePropertyAccess( bootIdSubProperty ),
CascadeStyles.ALL,
creationProcess
@ -272,6 +273,7 @@ public class MappingModelCreationHelper {
BasicType attrType,
String tableExpression,
String attrColumnName,
boolean isAttrFormula,
PropertyAccess propertyAccess,
CascadeStyle cascadeStyle,
MappingModelCreationProcess creationProcess) {
@ -333,6 +335,15 @@ public class MappingModelCreationHelper {
: FetchStrategy.IMMEDIATE_JOIN;
if ( valueConverter != null ) {
if ( isAttrFormula ) {
throw new MappingException( String.format(
"Value converter should not be set for column [%s] annotated with @Formula [%s]",
attrName,
attrColumnName
) );
}
// we want to "decompose" the "type" into its various pieces as expected by the mapping
assert valueConverter.getRelationalJavaDescriptor() == resolution.getRelationalJavaDescriptor();
@ -354,6 +365,7 @@ public class MappingModelCreationHelper {
fetchStrategy,
tableExpression,
attrColumnName,
false,
valueConverter,
mappingBasicType.getJdbcMapping(),
declaringType,
@ -369,6 +381,7 @@ public class MappingModelCreationHelper {
fetchStrategy,
tableExpression,
attrColumnName,
isAttrFormula,
null,
attrType,
declaringType,

View File

@ -89,6 +89,7 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa
new ColumnReference(
identificationVariable,
targetColumnExpression,
false,
jdbcMapping,
creationState.getSqlAstCreationState()
.getCreationContext()
@ -139,6 +140,7 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa
new ColumnReference(
identificationVariable,
keyColumnExpression,
false,
jdbcMapping,
creationState.getSqlAstCreationState().getCreationContext().getSessionFactory()
)
@ -167,6 +169,7 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa
new ColumnReference(
lhs,
keyColumnExpression,
false,
jdbcMapping,
creationContext.getSessionFactory()
),
@ -174,6 +177,7 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa
new ColumnReference(
rhs,
targetColumnExpression,
false,
jdbcMapping,
creationContext.getSessionFactory()
)
@ -184,6 +188,7 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa
new ColumnReference(
lhs,
targetColumnExpression,
false,
jdbcMapping,
creationContext.getSessionFactory()
),
@ -191,6 +196,7 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa
new ColumnReference(
rhs,
keyColumnExpression,
false,
jdbcMapping,
creationContext.getSessionFactory()
)
@ -285,12 +291,12 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa
@Override
public void visitReferringColumns(ColumnConsumer consumer) {
consumer.accept( keyColumnContainingTable, keyColumnExpression, jdbcMapping );
consumer.accept( keyColumnContainingTable, keyColumnExpression, false, jdbcMapping );
}
@Override
public void visitTargetColumns(ColumnConsumer consumer) {
consumer.accept( targetColumnContainingTable, targetColumnExpression, jdbcMapping );
consumer.accept( targetColumnContainingTable, targetColumnExpression, false, jdbcMapping );
}
@Override

View File

@ -26,10 +26,12 @@ import org.hibernate.sql.ast.tree.select.SortSpecification;
*/
public class ColumnReference implements OrderingExpression, SequencePart {
private final String columnExpression;
private final boolean isColumnExpressionFormula;
private final NavigablePath rootPath;
public ColumnReference(String columnExpression, NavigablePath rootPath) {
public ColumnReference(String columnExpression, boolean isColumnExpressionFormula, NavigablePath rootPath) {
this.columnExpression = columnExpression;
this.isColumnExpressionFormula = isColumnExpressionFormula;
this.rootPath = rootPath;
}
@ -37,6 +39,10 @@ public class ColumnReference implements OrderingExpression, SequencePart {
return columnExpression;
}
public boolean isColumnExpressionFormula() {
return isColumnExpressionFormula;
}
@Override
public SequencePart resolvePathPart(
String name,
@ -63,6 +69,7 @@ public class ColumnReference implements OrderingExpression, SequencePart {
sqlAstProcessingState -> new org.hibernate.sql.ast.tree.expression.ColumnReference(
tableGroup.getPrimaryTableReference(),
columnExpression,
isColumnExpressionFormula,
// because these ordering fragments are only ever part of the order-by clause, there
// is no need for the JdbcMapping
null,

View File

@ -58,6 +58,7 @@ public interface DomainPath extends OrderingExpression, SequencePart {
new ColumnReference(
tableReference,
basicValuedPart.getMappedColumnExpression(),
basicValuedPart.isMappedColumnExpressionFormula(),
basicValuedPart.getJdbcMapping(),
creationState.getCreationContext().getSessionFactory()
),
@ -68,7 +69,7 @@ public interface DomainPath extends OrderingExpression, SequencePart {
}
else {
getReferenceModelPart().visitColumns(
(tableExpression, columnExpression, jdbcMapping) -> {
(tableExpression, columnExpression, isColumnExpressionFormula, jdbcMapping) -> {
final TableReference tableReference = tableGroup.resolveTableReference( tableExpression );
ast.addSortSpecification(
new SortSpecification(
@ -80,6 +81,7 @@ public interface DomainPath extends OrderingExpression, SequencePart {
sqlAstProcessingState -> new ColumnReference(
tableReference,
columnExpression,
isColumnExpressionFormula,
jdbcMapping,
sessionFactory
)

View File

@ -37,7 +37,7 @@ public class RootSequencePart implements SequencePart {
if ( isTerminal ) {
// assume a column-reference
return new ColumnReference( name, pluralAttributePath.getNavigablePath() );
return new ColumnReference( name, false, pluralAttributePath.getNavigablePath() );
}
throw new PathResolutionException(

View File

@ -122,7 +122,6 @@ import org.hibernate.loader.entity.CacheEntityLoaderHelper;
import org.hibernate.mapping.BasicValue;
import org.hibernate.mapping.Column;
import org.hibernate.mapping.Component;
import org.hibernate.mapping.Formula;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.mapping.RootClass;
@ -824,7 +823,8 @@ public abstract class AbstractEntityPersister
colAliases[k] = thing.getAlias( dialect, prop.getValue().getTable() );
if ( thing.isFormula() ) {
foundFormula = true;
( (Formula) thing ).setFormula( substituteBrackets( ( (Formula) thing ).getFormula() ) );
// ( (Formula) thing ).setFormula( substituteBrackets( ( (Formula) thing ).getFormula() ) );
// TODO: uncomment the above statement when this#substituteBrackets(String) is implemented
formulaTemplates[k] = thing.getTemplate( dialect, factory.getQueryEngine().getSqmFunctionRegistry() );
}
else {
@ -1406,6 +1406,7 @@ public abstract class AbstractEntityPersister
sqlAstProcessingState -> new ColumnReference(
rootTableReference.getIdentificationVariable(),
rootPkColumnName,
false,
jdbcMapping,
getFactory()
)
@ -1420,6 +1421,7 @@ public abstract class AbstractEntityPersister
sqlAstProcessingState -> new ColumnReference(
joinedTableReference.getIdentificationVariable(),
fkColumnName,
false,
jdbcMapping,
getFactory()
)
@ -6143,6 +6145,7 @@ public abstract class AbstractEntityPersister
(BasicType) attrType,
tableExpression,
attrColumnNames[0],
false,
propertyAccess,
tupleAttrDefinition.getCascadeStyle(),
creationProcess
@ -6150,6 +6153,17 @@ public abstract class AbstractEntityPersister
}
if ( attrType instanceof BasicType ) {
final String attrColumnExpression;
final boolean isAttrColumnExpressionFormula;
if ( attrColumnNames[0] != null ) {
attrColumnExpression = attrColumnNames[0];
isAttrColumnExpressionFormula = false;
}
else {
final String[] attrColumnFormulaTemplate = propertyColumnFormulaTemplates[ propertyIndex ];
attrColumnExpression = attrColumnFormulaTemplate[0];
isAttrColumnExpressionFormula = true;
}
return MappingModelCreationHelper.buildBasicAttributeMapping(
attrName,
getNavigableRole().append( bootProperty.getName() ),
@ -6158,7 +6172,8 @@ public abstract class AbstractEntityPersister
this,
(BasicType) attrType,
tableExpression,
attrColumnNames[0],
attrColumnExpression,
isAttrColumnExpressionFormula,
propertyAccess,
tupleAttrDefinition.getCascadeStyle(),
creationProcess

View File

@ -33,6 +33,7 @@ import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.DynamicFilterAliasGenerator;
import org.hibernate.internal.FilterAliasGenerator;
import org.hibernate.internal.TableGroupFilterAliasGenerator;
import org.hibernate.internal.util.MarkerObject;
import org.hibernate.internal.util.MutableInteger;
import org.hibernate.internal.util.StringHelper;
@ -1272,7 +1273,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
() -> columnConsumer -> {
final String[] keyColumnNames = constraintOrderedKeyColumnNames[tablePosition];
for ( String column : keyColumnNames ) {
columnConsumer.accept( tableName, column, null );
columnConsumer.accept( tableName, column, false, null );
}
}
);
@ -1343,6 +1344,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
return new ColumnReference(
tableReference.getIdentificationVariable(),
discriminatorColumnNameByTableName.get( tableReference.getTableExpression() ),
false,
jdbcMappings.get( 0 ),
getFactory()
);

View File

@ -928,6 +928,7 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
sqlAstProcessingState -> new ColumnReference(
tableGroup.getPrimaryTableReference().getIdentificationVariable(),
getDiscriminatorColumnName(),
false,
( (BasicType) getDiscriminatorType() ).getJdbcMapping(),
getFactory()
)
@ -952,7 +953,7 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
() -> columnConsumer -> {
final String[] keyColumnNames = constraintOrderedKeyColumnNames[tablePosition];
for ( String column : keyColumnNames ) {
columnConsumer.accept( tableName, column, null );
columnConsumer.accept( tableName, column, false,null );
}
}
);

View File

@ -389,7 +389,7 @@ public class UnionSubclassEntityPersister extends AbstractEntityPersister {
() -> columnConsumer -> {
final String[] keyColumnNames = constraintOrderedKeyColumnNames[tablePosition];
for ( String column : keyColumnNames ) {
columnConsumer.accept( tableName, column, null );
columnConsumer.accept( tableName, column, false, null );
}
}
);

View File

@ -80,7 +80,7 @@ public class MatchingIdSelectionHelper {
final List<DomainResult> domainResults = new ArrayList<>();
final MutableInteger i = new MutableInteger();
targetEntityDescriptor.getIdentifierMapping().visitColumns(
(containingTableExpression, columnExpression, jdbcMapping) -> {
(containingTableExpression, columnExpression, isColumnExpressionFormula, jdbcMapping) -> {
final int position = i.getAndIncrement();
final TableReference tableReference = mutatingTableGroup.resolveTableReference( containingTableExpression );
final Expression expression = sqmConverter.getSqlExpressionResolver().resolveSqlExpression(
@ -88,6 +88,7 @@ public class MatchingIdSelectionHelper {
sqlAstProcessingState -> new ColumnReference(
tableReference,
columnExpression,
isColumnExpressionFormula,
jdbcMapping,
sessionFactory
)
@ -141,7 +142,7 @@ public class MatchingIdSelectionHelper {
final MutableInteger i = new MutableInteger();
targetEntityDescriptor.getIdentifierMapping().visitColumns(
(containingTableExpression, columnExpression, jdbcMapping) -> {
(containingTableExpression, columnExpression, isColumnExpressionFormula, jdbcMapping) -> {
final int position = i.getAndIncrement();
final TableReference tableReference = mutatingTableGroup.resolveTableReference( containingTableExpression );
final Expression expression = sqmConverter.getSqlExpressionResolver().resolveSqlExpression(
@ -149,6 +150,7 @@ public class MatchingIdSelectionHelper {
sqlAstProcessingState -> new ColumnReference(
tableReference,
columnExpression,
isColumnExpressionFormula,
jdbcMapping,
sessionFactory
)

View File

@ -221,10 +221,11 @@ public class CteDeleteHandler extends AbstractCteMutationHandler implements Dele
final List<ColumnReference> columnsToMatchReferences = new ArrayList<>();
columnsToMatchVisitationSupplier.get().accept(
(containingTableExpression, columnExpression, jdbcMapping) -> columnsToMatchReferences.add(
(containingTableExpression, columnExpression, isColumnExpressionFormula, jdbcMapping) -> columnsToMatchReferences.add(
new ColumnReference(
targetTableReference,
columnExpression,
isColumnExpressionFormula,
jdbcMapping,
sessionFactory
)

View File

@ -76,7 +76,7 @@ public final class ExecuteWithIdTableHelper {
for ( int i = 0; i < idTable.getIdTableColumns().size(); i++ ) {
final IdTableColumn column = idTable.getIdTableColumns().get( i );
idTableInsert.addTargetColumnReferences(
new ColumnReference( idTableReference, column.getColumnName(), column.getJdbcMapping(), factory )
new ColumnReference( idTableReference, column.getColumnName(), false, column.getJdbcMapping(), factory )
);
}
@ -88,7 +88,7 @@ public final class ExecuteWithIdTableHelper {
final MutableInteger positionWrapper = new MutableInteger();
mutatingEntityDescriptor.getIdentifierMapping().visitColumns(
(containingTableExpression, columnExpression, jdbcMapping) -> {
(containingTableExpression, columnExpression, isColumnExpressionFormula, jdbcMapping) -> {
final int jdbcPosition = positionWrapper.getAndIncrement();
final TableReference tableReference = mutatingTableGroup.resolveTableReference( containingTableExpression );
matchingIdSelection.getSelectClause().addSqlSelection(
@ -100,6 +100,7 @@ public final class ExecuteWithIdTableHelper {
sqlAstProcessingState -> new ColumnReference(
tableReference,
columnExpression,
isColumnExpressionFormula,
jdbcMapping,
factory
)
@ -190,6 +191,7 @@ public final class ExecuteWithIdTableHelper {
new ColumnReference(
tableReference,
idTableColumn.getColumnName(),
false,
idTableColumn.getJdbcMapping(),
executionContext.getSession().getFactory()
)
@ -211,6 +213,7 @@ public final class ExecuteWithIdTableHelper {
new ColumnReference(
idTableReference,
idTable.getSessionUidColumn().getColumnName(),
false,
idTable.getSessionUidColumn().getJdbcMapping(),
executionContext.getSession().getFactory()
),

View File

@ -53,12 +53,13 @@ public final class ExecuteWithoutIdTableHelper {
matchingIdSelect.getFromClause().addRoot( matchingIdSelectTableGroup );
rootEntityPersister.getIdentifierMapping().visitColumns(
(containingTableExpression, columnExpression, jdbcMapping) -> {
(containingTableExpression, columnExpression, isColumnExpressionFormula, jdbcMapping) -> {
final ColumnReference columnReference = (ColumnReference) sqlExpressionResolver.resolveSqlExpression(
SqlExpressionResolver.createColumnReferenceKey( rootTableReference, columnExpression ),
sqlAstProcessingState -> new ColumnReference(
rootTableReference,
columnExpression,
isColumnExpressionFormula,
jdbcMapping,
sessionFactory
)

View File

@ -34,7 +34,7 @@ public class IdTable implements Exportable {
);
entityDescriptor.getIdentifierMapping().visitColumns(
(containingTableExpression, columnExpression, jdbcMapping) -> columns.add(
(containingTableExpression, columnExpression, isColumnExpressionFormula, jdbcMapping) -> columns.add(
new IdTableColumn(
this,
columnExpression,

View File

@ -285,7 +285,7 @@ public class RestrictedDeleteExecutionDelegate implements TableBasedDeleteHandle
*/
final List<ColumnReference> deletingTableColumnRefs = new ArrayList<>();
tableKeyColumnVisitationSupplier.get().accept(
(containingTableExpression, columnExpression, jdbcMapping) -> {
(containingTableExpression, columnExpression, isColumnExpressionFormula, jdbcMapping) -> {
assert targetTableReference.getTableExpression().equals( containingTableExpression );
final Expression expression = sqlExpressionResolver.resolveSqlExpression(
@ -293,6 +293,7 @@ public class RestrictedDeleteExecutionDelegate implements TableBasedDeleteHandle
sqlAstProcessingState -> new ColumnReference(
rootTableGroup.getPrimaryTableReference(),
columnExpression,
isColumnExpressionFormula,
jdbcMapping,
sessionFactory
)
@ -456,12 +457,13 @@ public class RestrictedDeleteExecutionDelegate implements TableBasedDeleteHandle
final TableKeyExpressionCollector keyColumnCollector = new TableKeyExpressionCollector( entityDescriptor );
tableKeyColumnVisitationSupplier.get().accept(
(containingTableExpression, columnExpression, jdbcMapping) -> {
(containingTableExpression, columnExpression, isColumnExpressionFormula, jdbcMapping) -> {
assert containingTableExpression.equals( tableExpression );
keyColumnCollector.apply(
new ColumnReference(
(String) null,
columnExpression,
isColumnExpressionFormula,
jdbcMapping,
factory
)

View File

@ -236,12 +236,13 @@ public class UpdateExecutionDelegate implements TableBasedUpdateHandler.Executio
final TableKeyExpressionCollector keyColumnCollector = new TableKeyExpressionCollector( entityDescriptor );
tableKeyColumnVisitationSupplier.get().accept(
(containingTableExpression, columnExpression, jdbcMapping) -> {
(containingTableExpression, columnExpression, isColumnExpressionFormula, jdbcMapping) -> {
assert containingTableExpression.equals( tableExpression );
keyColumnCollector.apply(
new ColumnReference(
(String) null,
columnExpression,
isColumnExpressionFormula,
jdbcMapping,
sessionFactory
)

View File

@ -67,6 +67,7 @@ public class DisjunctionRestrictionProducer implements MatchingIdRestrictionProd
final ColumnReference idColumnReference = new ColumnReference(
mutatingTableReference,
idColumn,
false,
basicIdMapping.getJdbcMapping(),
sessionFactory
);
@ -88,8 +89,8 @@ public class DisjunctionRestrictionProducer implements MatchingIdRestrictionProd
final List<ColumnReference> columnReferences = new ArrayList<>( idColumnCount );
final List<JdbcMapping> jdbcMappings = new ArrayList<>( idColumnCount );
identifierMapping.visitColumns(
(containingTableExpression, columnExpression, jdbcMapping) -> {
columnReferences.add( new ColumnReference( mutatingTableReference, columnExpression, jdbcMapping, sessionFactory ) );
(containingTableExpression, columnExpression, isColumnExpressionFormula, jdbcMapping) -> {
columnReferences.add( new ColumnReference( mutatingTableReference, columnExpression, isColumnExpressionFormula, jdbcMapping, sessionFactory ) );
jdbcMappings.add( jdbcMapping );
}
);

View File

@ -69,6 +69,7 @@ public class InPredicateRestrictionProducer implements MatchingIdRestrictionProd
final Expression inFixture = new ColumnReference(
mutatingTableReference,
idColumn,
false,
basicIdMapping.getJdbcMapping(),
sessionFactory
);
@ -83,8 +84,8 @@ public class InPredicateRestrictionProducer implements MatchingIdRestrictionProd
final List<ColumnReference> columnReferences = new ArrayList<>( idColumnCount );
final List<JdbcMapping> jdbcMappings = new ArrayList<>( idColumnCount );
identifierMapping.visitColumns(
(containingTableExpression, columnExpression, jdbcMapping) -> {
columnReferences.add( new ColumnReference( mutatingTableReference, columnExpression, jdbcMapping, sessionFactory ) );
(containingTableExpression, columnExpression, isColumnExpressionFormula, jdbcMapping) -> {
columnReferences.add( new ColumnReference( mutatingTableReference, columnExpression, isColumnExpressionFormula, jdbcMapping, sessionFactory ) );
jdbcMappings.add( jdbcMapping );
}
);

View File

@ -62,6 +62,7 @@ public class BasicValuedPathInterpretation<T> implements AssignableSqmPathInterp
sacs -> new ColumnReference(
tableReference.getIdentificationVariable(),
mapping.getMappedColumnExpression(),
mapping.isMappedColumnExpressionFormula(),
mapping.getJdbcMapping(),
sqlAstCreationState.getCreationContext().getSessionFactory()
)

View File

@ -237,7 +237,7 @@ public class StandardSqmUpdateTranslator
// create one JdbcParameter for each column in the assigned path
assignedPathInterpretation.getExpressionType().visitColumns(
(containingTableExpression, columnExpression, jdbcMapping) -> {
(containingTableExpression, columnExpression, isColumnExpressionFormula, jdbcMapping) -> {
final JdbcParameter jdbcParameter = new JdbcParameterImpl( jdbcMapping );
jdbcParametersForSqm.add( jdbcParameter );
assignments.add(
@ -246,6 +246,7 @@ public class StandardSqmUpdateTranslator
// we do not want a qualifier (table alias) here
(String) null,
columnExpression,
isColumnExpressionFormula,
jdbcMapping,
getCreationContext().getSessionFactory()
),

View File

@ -277,6 +277,9 @@ public class SqmSelectStatement<T> extends AbstractSqmSelectQuery<T> implements
@Override
public SqmSelectStatement<T> orderBy(Order... orders) {
if ( getQuerySpec().getOrderByClause() == null ) {
getQuerySpec().setOrderByClause( new SqmOrderByClause() );
}
for ( Order order : orders ) {
getQuerySpec().getOrderByClause().addSortSpecification( (SqmSortSpecification) order );
}
@ -285,6 +288,9 @@ public class SqmSelectStatement<T> extends AbstractSqmSelectQuery<T> implements
@Override
public SqmSelectStatement<T> orderBy(List<Order> orders) {
if ( getQuerySpec().getOrderByClause() == null ) {
getQuerySpec().setOrderByClause( new SqmOrderByClause() );
}
for ( Order order : orders ) {
getQuerySpec().getOrderByClause().addSortSpecification( (SqmSortSpecification) order );
}

View File

@ -492,11 +492,7 @@ public abstract class AbstractSqlAstWalker
@Override
public void visitColumnReference(ColumnReference columnReference) {
if ( columnReference.getQualifier() != null ) {
appendSql( columnReference.getQualifier() );
appendSql( "." );
}
appendSql( columnReference.getColumnExpression() );
appendSql( columnReference.getExpressionText() );
}
@Override

View File

@ -46,7 +46,7 @@ public class CteTable {
final int numberOfColumns = entityDescriptor.getIdentifierMapping().getJdbcTypeCount( sessionFactory.getTypeConfiguration() );
cteColumns = new ArrayList<>( numberOfColumns );
entityDescriptor.getIdentifierMapping().visitColumns(
(containingTableExpression, columnExpression, jdbcMapping) -> cteColumns.add(
(containingTableExpression, columnExpression, isColumnExpressionFormula, jdbcMapping) -> cteColumns.add(
new CteColumn(
"cte_" + columnExpression,
jdbcMapping
@ -183,6 +183,7 @@ public class CteTable {
new ColumnReference(
tableReference,
cteColumn.getColumnExpression(),
false,
cteColumn.getJdbcMapping(),
sessionFactory
)

View File

@ -4,19 +4,18 @@
* 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 java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.function.Consumer;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.MappingModelExpressable;
import org.hibernate.sql.Template;
import org.hibernate.sql.ast.SqlAstWalker;
import org.hibernate.sql.ast.tree.from.TableReference;
import org.hibernate.sql.ast.tree.update.Assignable;
@ -25,32 +24,43 @@ import org.hibernate.sql.ast.tree.update.Assignable;
* Models a reference to a Column in a SQL AST
*
* @author Steve Ebersole
* @author Nathan Xu
*/
public class ColumnReference implements Expression, Assignable {
private final String qualifier;
private final String columnExpression;
private final boolean isColumnExpressionFormula;
private final String referenceExpression;
private final JdbcMapping jdbcMapping;
public ColumnReference(
String qualifier,
String columnExpression,
boolean isColumnExpressionFormula,
JdbcMapping jdbcMapping,
SessionFactoryImplementor sessionFactory) {
this.qualifier = StringHelper.nullIfEmpty( qualifier );
this.columnExpression = columnExpression;
this.referenceExpression = this.qualifier == null
? columnExpression
: this.qualifier + "." + columnExpression;
if ( isColumnExpressionFormula ) {
assert qualifier != null;
this.columnExpression = StringHelper.replace( columnExpression, Template.TEMPLATE, qualifier );
}
else {
this.columnExpression = columnExpression;
}
this.isColumnExpressionFormula = isColumnExpressionFormula;
this.referenceExpression = this.qualifier == null || isColumnExpressionFormula
? this.columnExpression
: this.qualifier + "." + this.columnExpression;
this.jdbcMapping = jdbcMapping;
}
public ColumnReference(
TableReference tableReference,
String columnExpression,
boolean isColumnExpressionFormula,
JdbcMapping jdbcMapping,
SessionFactoryImplementor sessionFactory) {
this( tableReference.getIdentificationVariable(), columnExpression, jdbcMapping, sessionFactory );
this( tableReference.getIdentificationVariable(), columnExpression, isColumnExpressionFormula, jdbcMapping, sessionFactory );
}
public String getQualifier() {
@ -61,6 +71,10 @@ public class ColumnReference implements Expression, Assignable {
return columnExpression;
}
public boolean isColumnExpressionFormula() {
return isColumnExpressionFormula;
}
public String getExpressionText() {
return referenceExpression;
}
@ -103,7 +117,7 @@ public class ColumnReference implements Expression, Assignable {
}
final ColumnReference that = (ColumnReference) o;
return Objects.equals( referenceExpression, that.referenceExpression );
return referenceExpression.equals( that.referenceExpression );
}
@Override

View File

@ -0,0 +1,131 @@
/*
* 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.formula;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import org.hibernate.annotations.Formula;
import org.hibernate.testing.orm.junit.DomainModel;
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 static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
/**
* @author Nathan Xu
*/
@DomainModel(
annotatedClasses = {
FormulaBasicsTest.Account.class
}
)
@SessionFactory
public class FormulaBasicsTest {
@BeforeEach
void setUp(SessionFactoryScope scope) {
scope.inTransaction( session -> {
final Account account = new Account( );
account.setId( 1L );
account.setCredit( 5000d );
account.setRate( 1.25 / 100 );
session.persist( account );
} );
}
@Test
void testLoader(SessionFactoryScope scope) {
scope.inTransaction( session -> {
final Account account = session.find( Account.class, 1L );
assertThat( account.getInterest(), is( 62.5d ));
} );
}
@Test
void testHQL(SessionFactoryScope scope) {
scope.inTransaction( session -> {
final Account account = session.createQuery( "select a from Account a where a.id = :id", Account.class )
.setParameter( "id", 1L ).uniqueResult();
assertThat( account.getInterest(), is( 62.5d ));
} );
}
@Test
void testCriteria(SessionFactoryScope scope) {
scope.inTransaction( session -> {
final CriteriaBuilder criteriaBuilder = scope.getSessionFactory().getCriteriaBuilder();
final CriteriaQuery<Account> criteria = criteriaBuilder.createQuery( Account.class );
final Root<Account> root = criteria.from( Account.class );
criteria.select( root );
criteria.where( criteriaBuilder.equal( root.get( "id" ), criteriaBuilder.literal( 1L ) ) );
final Account account = session.createQuery( criteria ).uniqueResult();
assertThat( account.getInterest(), is( 62.5d ));
} );
}
@AfterEach
void tearDown(SessionFactoryScope scope) {
scope.inTransaction( session -> {
session.createQuery( "delete from Account" ).executeUpdate();
} );
}
@Entity(name = "Account")
public static class Account {
@Id
private Long id;
private Double credit;
private Double rate;
@Formula(value = "credit * rate")
private Double interest;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Double getCredit() {
return credit;
}
public void setCredit(Double credit) {
this.credit = credit;
}
public Double getRate() {
return rate;
}
public void setRate(Double rate) {
this.rate = rate;
}
public Double getInterest() {
return interest;
}
public void setInterest(Double interest) {
this.interest = interest;
}
}
}

View File

@ -0,0 +1,122 @@
/*
* 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.formula;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.annotations.Formula;
import org.hibernate.query.Query;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.FailureExpected;
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 static org.hibernate.testing.hamcrest.CollectionMatchers.hasSize;
import static org.junit.Assert.assertThat;
/**
* @author Алексей Макаров
* @author Gail Badner
* @author Nathan Xu
*/
@DomainModel( annotatedClasses = FormulaNativeQueryTest.Foo.class )
@SessionFactory
@TestForIssue(jiraKey = "HHH-7525")
public class FormulaNativeQueryTest {
@BeforeEach
void setUp(SessionFactoryScope scope) {
scope.inTransaction( session -> {
session.persist( new Foo( 1, 1 ) );
session.persist( new Foo( 1, 2 ) );
session.persist( new Foo( 2, 1 ) );
} );
}
@AfterEach
void tearDown(SessionFactoryScope scope) {
scope.inTransaction( session -> session.createQuery( "delete from Foo" ).executeUpdate() );
}
@Test
@FailureExpected( jiraKey = "HHH-7525", reason = "native query not implemented yet")
void testNativeQuery(SessionFactoryScope scope) {
scope.inTransaction( session -> {
final Query<Foo> query = session.createNativeQuery( "SELECT ft.* FROM foo_table ft", Foo.class );
final List<Foo> list = query.getResultList();
assertThat( list, hasSize( 3 ) );
} );
}
@Test
void testHql(SessionFactoryScope scope) {
scope.inTransaction( session -> {
final Query<Foo> query = session.createQuery( "SELECT ft FROM Foo ft", Foo.class );
final List<Foo> list = query.getResultList();
assertThat( list, hasSize( 3 ) );
} );
}
@Entity(name = "Foo")
@Table(name = "foo_table")
public static class Foo {
private int id;
private int locationStart;
private int locationEnd;
private int distance;
public Foo() {
}
public Foo(int locationStart, int locationEnd) {
this.locationStart = locationStart;
this.locationEnd = locationEnd;
}
@Id
@GeneratedValue
public int getId() {
return id;
}
private void setId(int id) {
this.id = id;
}
public int getLocationStart() {
return locationStart;
}
public void setLocationStart(int locationStart) {
this.locationStart = locationStart;
}
public int getLocationEnd() {
return locationEnd;
}
public void setLocationEnd(int locationEnd) {
this.locationEnd = locationEnd;
}
@Formula("abs(locationEnd - locationStart)")
public int getDistance() {
return distance;
}
public void setDistance(int distance) {
this.distance = distance;
}
}
}

View File

@ -4,74 +4,59 @@
* 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.test.annotations.formula;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.junit.Assert.assertEquals;
package org.hibernate.orm.test.formula;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.annotations.Formula;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.query.Query;
import org.hibernate.test.annotations.formula.FormulaWithColumnTypesTest.ExtendedDialect;
import org.hibernate.test.locking.A;
import org.hibernate.testing.RequiresDialect;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.RequiresDialect;
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 static org.junit.Assert.assertEquals;
/**
* @author Yanming Zhou*
* @author Yanming Zhou
* @author Nathan Xu
*/
@DomainModel( annotatedClasses = FormulaWithAliasTest.Customer.class )
@SessionFactory
@RequiresDialect(H2Dialect.class)
public class FormulaWithAliasTest extends BaseCoreFunctionalTestCase {
public class FormulaWithAliasTest {
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class[] { Customer.class };
}
@Override
protected void configure(Configuration configuration) {
configuration.setProperty(
Environment.DIALECT,
ExtendedDialect.class.getName()
);
}
@Test
@TestForIssue(jiraKey = "HHH-12280")
public void testFormulaWithAlias() throws Exception {
doInHibernate( this::sessionFactory, session -> {
Customer company1 = new Customer();
@BeforeEach
void setUp(SessionFactoryScope scope) {
scope.inTransaction( session -> {
final Customer company1 = new Customer();
company1.setBalance(new BigDecimal(100));
company1.setVip(true);
session.persist(company1);
Customer company2 = new Customer();
final Customer company2 = new Customer();
company2.setBalance(new BigDecimal(1000));
company2.setVip(false);
session.persist(company2);
} );
doInHibernate( this::sessionFactory, session -> {
List<Customer> customers = session.createQuery(
"select c " +
"from Customer c ", Customer.class)
.getResultList();
}
@Test
@TestForIssue(jiraKey = "HHH-12280")
void testFormulaWithAlias(SessionFactoryScope scope) {
scope.inTransaction( session -> {
final List<Customer> customers = session.createQuery( "select c from Customer c ", Customer.class ).getResultList();
assertEquals(2, customers.size());
assertEquals(1d, customers.get(0).getPercentage().doubleValue(), 0);
@ -79,6 +64,11 @@ public class FormulaWithAliasTest extends BaseCoreFunctionalTestCase {
} );
}
@AfterEach
void tearDown(SessionFactoryScope scope) {
scope.inTransaction( session -> session.createQuery( "delete from Customer" ).executeUpdate() );
}
@Entity(name = "Customer")
public static class Customer implements Serializable{

View File

@ -4,7 +4,7 @@
* 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.test.annotations.formula;
package org.hibernate.orm.test.formula;
import java.io.Serializable;
import java.util.List;
@ -49,89 +49,89 @@ public class FormulaWithColumnTypesTest extends BaseCoreFunctionalTestCase {
@TestForIssue(jiraKey = "HHH-9951")
public void testFormulaAnnotationWithTypeNames() {
inTransaction(
session -> {
DisplayItem displayItem20 = new DisplayItem();
displayItem20.setDisplayCode( "20" );
inTransaction( session -> {
session.getSessionFactory().getQueryEngine().getInterpretationCache().close();
DisplayItem displayItem03 = new DisplayItem();
displayItem03.setDisplayCode( "03" );
final DisplayItem displayItem20 = new DisplayItem();
displayItem20.setDisplayCode( "20" );
DisplayItem displayItem100 = new DisplayItem();
displayItem100.setDisplayCode( "100" );
final DisplayItem displayItem03 = new DisplayItem();
displayItem03.setDisplayCode( "03" );
session.persist( displayItem20 );
session.persist( displayItem03 );
session.persist( displayItem100 );
}
);
final DisplayItem displayItem100 = new DisplayItem();
displayItem100.setDisplayCode( "100" );
session.persist( displayItem20 );
session.persist( displayItem03 );
session.persist( displayItem100 );
} );
// 1. Default sorting by display code natural ordering (resulting in 3-100-20).
inTransaction(
session -> {
CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
CriteriaQuery<DisplayItem> criteria = criteriaBuilder.createQuery( DisplayItem.class );
Root<DisplayItem> root = criteria.from( DisplayItem.class );
criteria.orderBy( criteriaBuilder.asc( root.get( "displayCode" ) ) );
inTransaction( session -> {
session.getSessionFactory().getQueryEngine().getInterpretationCache().close();
List displayItems = session.createQuery( criteria ).list();
final CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
final CriteriaQuery<DisplayItem> criteria = criteriaBuilder.createQuery( DisplayItem.class );
final Root<DisplayItem> root = criteria.from( DisplayItem.class );
criteria.orderBy( criteriaBuilder.asc( root.get( "displayCode" ) ) );
final List<DisplayItem> displayItems = session.createQuery( criteria ).getResultList();
// List displayItems = session.createCriteria( DisplayItem.class )
// .addOrder( Order.asc( "displayCode" ) )
// .list();
assertNotNull( displayItems );
assertEquals( displayItems.size(), 3 );
assertEquals(
"03",
( (DisplayItem) displayItems.get( 0 ) ).getDisplayCode()
);
assertEquals(
"100",
( (DisplayItem) displayItems.get( 1 ) ).getDisplayCode()
);
assertEquals(
"20",
( (DisplayItem) displayItems.get( 2 ) ).getDisplayCode()
);
}
);
assertNotNull( displayItems );
assertEquals( 3, displayItems.size() );
assertEquals(
"03",
displayItems.get( 0 ).getDisplayCode()
);
assertEquals(
"100",
displayItems.get( 1 ).getDisplayCode()
);
assertEquals(
"20",
displayItems.get( 2 ).getDisplayCode()
);
} );
// 2. Sorting by the casted type (resulting in 3-20-100).
inTransaction(
session -> {
CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
CriteriaQuery<DisplayItem> criteria = criteriaBuilder.createQuery( DisplayItem.class );
Root<DisplayItem> root = criteria.from( DisplayItem.class );
criteria.orderBy( criteriaBuilder.asc( root.get( "displayCodeAsInteger" ) ) );
inTransaction( session -> {
session.getSessionFactory().getQueryEngine().getInterpretationCache().close();
List displayItemsSortedByInteger = session.createQuery( criteria ).list();
final CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
final CriteriaQuery<DisplayItem> criteria = criteriaBuilder.createQuery( DisplayItem.class );
final Root<DisplayItem> root = criteria.from( DisplayItem.class );
criteria.orderBy( criteriaBuilder.asc( root.get( "displayCodeAsInteger" ) ) );
final List<DisplayItem> displayItemsSortedByInteger = session.createQuery( criteria ).getResultList();
// List displayItemsSortedByInteger = session.createCriteria( DisplayItem.class )
// .addOrder( Order.asc( "displayCodeAsInteger" ) )
// .list();
assertNotNull( displayItemsSortedByInteger );
assertEquals( displayItemsSortedByInteger.size(), 3 );
assertEquals(
"03",
( (DisplayItem) displayItemsSortedByInteger.get( 0 ) ).getDisplayCode()
);
assertEquals(
"20",
( (DisplayItem) displayItemsSortedByInteger.get( 1 ) ).getDisplayCode()
);
assertEquals(
"100",
( (DisplayItem) displayItemsSortedByInteger.get( 2 ) ).getDisplayCode()
);
}
);
assertNotNull( displayItemsSortedByInteger );
assertEquals( 3, displayItemsSortedByInteger.size() );
assertEquals(
"03",
displayItemsSortedByInteger.get( 0 ).getDisplayCode()
);
assertEquals(
"20",
displayItemsSortedByInteger.get( 1 ).getDisplayCode()
);
assertEquals(
"100",
displayItemsSortedByInteger.get( 2 ).getDisplayCode()
);
} );
}
@Override
public Class<?>[] getAnnotatedClasses() {
return new Class<?>[] {DisplayItem.class};
return new Class<?>[] { DisplayItem.class };
}
/**
@ -200,8 +200,8 @@ public class FormulaWithColumnTypesTest extends BaseCoreFunctionalTestCase {
public ExtendedDialect() {
super();
registerKeyword( "FLOAT" );
registerKeyword( "INTEGER" );
}
}
}

View File

@ -0,0 +1,130 @@
/*
* 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.formula;
import java.io.Serializable;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import org.hibernate.annotations.Formula;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.orm.junit.DialectFeatureChecks;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.RequiresDialectFeature;
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 static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
/**
* @author Vlad Mihalcea
* @author Nathan Xu
*/
@DomainModel( annotatedClasses = FormulaWithPartitionByTest.DisplayItem.class )
@SessionFactory
@RequiresDialectFeature( jiraKey = "HHH-10754", feature = DialectFeatureChecks.SupportPartitionBy.class )
public class FormulaWithPartitionByTest {
@BeforeEach
void setUp(SessionFactoryScope scope) {
scope.inTransaction( session -> {
final DisplayItem displayItem20_1 = new DisplayItem();
displayItem20_1.setId( 1 );
displayItem20_1.setDiscountCode( "20" );
displayItem20_1.setDiscountValue( 12.34d );
final DisplayItem displayItem20_2 = new DisplayItem();
displayItem20_2.setId( 2 );
displayItem20_2.setDiscountCode( "20" );
displayItem20_2.setDiscountValue( 15.89 );
final DisplayItem displayItem100 = new DisplayItem();
displayItem100.setId( 3 );
displayItem100.setDiscountCode( "100" );
displayItem100.setDiscountValue( 12.5 );
session.persist( displayItem20_1 );
session.persist( displayItem20_2 );
session.persist( displayItem100 );
} );
}
@Test
@TestForIssue( jiraKey = "HHH-10754" )
void testFormulaAnnotationWithPartitionBy(SessionFactoryScope scope) {
scope.inTransaction( session -> {
final List<DisplayItem> displayItems = session.createQuery( "select di from DisplayItem di order by di.id", DisplayItem.class).getResultList();
assertNotNull( displayItems );
assertEquals( 3, displayItems.size() );
assertEquals( 1, displayItems.get( 0 ).getItemsByCode().intValue() );
assertEquals( 2, displayItems.get( 1 ).getItemsByCode().intValue() );
assertEquals( 1, displayItems.get( 2 ).getItemsByCode().intValue() );
} );
}
@AfterEach
void tearDown(SessionFactoryScope scope) {
scope.inTransaction( session -> session.createQuery( "delete from DisplayItem" ).executeUpdate() );
}
@Entity(name = "DisplayItem")
public static class DisplayItem implements Serializable {
@Id
private Integer id;
@Column(name = "DISCOUNT_CODE")
private String discountCode;
@Column(name = "DISCOUNT_VALUE")
private Double discountValue;
@Formula("ROW_NUMBER() OVER( PARTITION BY DISCOUNT_CODE ORDER BY SIGN(DISCOUNT_VALUE) DESC )")
private Integer itemsByCode;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getDiscountCode() {
return discountCode;
}
public void setDiscountCode(String discountCode) {
this.discountCode = discountCode;
}
public Integer getItemsByCode() {
return itemsByCode;
}
public void setItemsByCode(Integer itemsByCode) {
this.itemsByCode = itemsByCode;
}
public Double getDiscountValue() {
return discountValue;
}
public void setDiscountValue(Double discountValue) {
this.discountValue = discountValue;
}
}
}

View File

@ -0,0 +1,133 @@
/*
* 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.formula;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import org.hibernate.annotations.Formula;
import org.hibernate.testing.orm.junit.DomainModel;
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 static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
/**
* @author Nathan Xu
*/
@DomainModel(
annotatedClasses = {
FormulaTests.Account.class
}
)
@SessionFactory
public class FormulaTests {
@BeforeEach
void setUp(SessionFactoryScope scope) {
scope.inTransaction( session -> {
Account account = new Account( );
account.setId( 1L );
account.setCredit( 5000d );
account.setRate( 1.25 / 100 );
session.persist( account );
} );
}
@Test
void testLoader(SessionFactoryScope scope) {
scope.inTransaction( session -> {
Account account = session.find( Account.class, 1L );
assertThat( account.getInterest(), is( 62.5d ));
} );
}
@Test
void testHQL(SessionFactoryScope scope) {
scope.inTransaction( session -> {
Account account = session.createQuery( "select a from Account a where a.id = :id", Account.class )
.setParameter( "id", 1L ).uniqueResult();
assertThat( account.getInterest(), is( 62.5d ));
} );
}
@Test
void testCriteria(SessionFactoryScope scope) {
scope.inTransaction( session -> {
final CriteriaBuilder criteriaBuilder = scope.getSessionFactory().getCriteriaBuilder();
final CriteriaQuery<Account> criteria = criteriaBuilder.createQuery( Account.class );
Root<Account> root = criteria.from( Account.class );
criteria.select( root );
criteria.where( criteriaBuilder.equal( root.get( "id" ), criteriaBuilder.literal( 1L ) ) );
Account account = session.createQuery( criteria ).uniqueResult();
assertThat( account.getInterest(), is( 62.5d ));
} );
}
@AfterEach
void tearDown(SessionFactoryScope scope) {
scope.inTransaction( session -> {
session.createQuery( "delete from Account" ).executeUpdate();
} );
}
@Entity(name = "Account")
public static class Account {
@Id
private Long id;
private Double credit;
private Double rate;
@Formula(value = "credit * rate")
private Double interest;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Double getCredit() {
return credit;
}
public void setCredit(Double credit) {
this.credit = credit;
}
public Double getRate() {
return rate;
}
public void setRate(Double rate) {
this.rate = rate;
}
public Double getInterest() {
return interest;
}
public void setInterest(Double interest) {
this.interest = interest;
}
}
}

View File

@ -56,12 +56,12 @@ public class ManyToOneJoinTableTest {
final ToOneAttributeMapping simpleAttributeMapping = (ToOneAttributeMapping) simpleEntityAssociation;
ForeignKeyDescriptor foreignKeyDescriptor = simpleAttributeMapping.getForeignKeyDescriptor();
foreignKeyDescriptor.visitReferringColumns( (keyTable, keyColumn, jdbcMapping) -> {
foreignKeyDescriptor.visitReferringColumns( (keyTable, keyColumn, isKeyColumnFormula, jdbcMapping) -> {
assertThat( keyTable, is( "other_simple" ) );
assertThat( keyColumn, is( "RHS_ID" ) );
} );
foreignKeyDescriptor.visitTargetColumns( (targetTable, targetColumn, jdbcMapping) -> {
foreignKeyDescriptor.visitTargetColumns( (targetTable, targetColumn, isTargetColumnFormula, jdbcMapping) -> {
assertThat( targetTable, is( "simple_entity" ) );
assertThat( targetColumn, is( "id" ) );
} );
@ -73,12 +73,12 @@ public class ManyToOneJoinTableTest {
final ToOneAttributeMapping anotherAttributeMapping = (ToOneAttributeMapping) anotherEntityAssociation;
foreignKeyDescriptor = anotherAttributeMapping.getForeignKeyDescriptor();
foreignKeyDescriptor.visitReferringColumns( (keyTable, keyColumn, jdbcMapping) -> {
foreignKeyDescriptor.visitReferringColumns( (keyTable, keyColumn, isKeyColumnFormula, jdbcMapping) -> {
assertThat( keyTable, is( "other_another" ) );
assertThat( keyColumn, is( "RHS_ID" ) );
} );
foreignKeyDescriptor.visitTargetColumns( (targetTable, targetColumn, jdbcMapping) -> {
foreignKeyDescriptor.visitTargetColumns( (targetTable, targetColumn, isTargetColumnFormula, jdbcMapping) -> {
assertThat( targetTable, is( "another_entity" ) );
assertThat( targetColumn, is( "id" ) );
} );
@ -95,12 +95,12 @@ public class ManyToOneJoinTableTest {
ToOneAttributeMapping otherAttributeMapping = (ToOneAttributeMapping) otherEntityEntityAssociation;
foreignKeyDescriptor = otherAttributeMapping.getForeignKeyDescriptor();
foreignKeyDescriptor.visitReferringColumns( (keyTable, keyColumn, jdbcMapping) -> {
foreignKeyDescriptor.visitReferringColumns( (keyTable, keyColumn, isKeyColumnFormula, jdbcMapping) -> {
assertThat( keyTable, is( "other_simple" ) );
assertThat( keyColumn, is( "LHS_ID" ) );
} );
foreignKeyDescriptor.visitTargetColumns( (targetTable, targetColumn, jdbcMapping) -> {
foreignKeyDescriptor.visitTargetColumns( (targetTable, targetColumn, isTargetColumnFormula, jdbcMapping) -> {
assertThat( targetTable, is( "other_entity" ) );
assertThat( targetColumn, is( "id" ) );
} );
@ -117,12 +117,12 @@ public class ManyToOneJoinTableTest {
otherAttributeMapping = (ToOneAttributeMapping) otherEntityEntityAssociation;
foreignKeyDescriptor = otherAttributeMapping.getForeignKeyDescriptor();
foreignKeyDescriptor.visitReferringColumns( (keyTable, keyColumn, jdbcMapping) -> {
foreignKeyDescriptor.visitReferringColumns( (keyTable, keyColumn, isKeyColumnFormula, jdbcMapping) -> {
assertThat( keyTable, is( "another_entity" ) );
assertThat( keyColumn, is( "other_id" ) );
} );
foreignKeyDescriptor.visitTargetColumns( (targetTable, targetColumn, jdbcMapping) -> {
foreignKeyDescriptor.visitTargetColumns( (targetTable, targetColumn, isTargetColumnFormula, jdbcMapping) -> {
assertThat( targetTable, is( "other_entity" ) );
assertThat( targetColumn, is( "id" ) );
} );

View File

@ -53,12 +53,12 @@ public class ManyToOneTest {
final ToOneAttributeMapping childAttributeMapping = (ToOneAttributeMapping) simpleEntityAssociation;
ForeignKeyDescriptor foreignKeyDescriptor = childAttributeMapping.getForeignKeyDescriptor();
foreignKeyDescriptor.visitReferringColumns( (keyTable, keyColumn, jdbcMapping) -> {
foreignKeyDescriptor.visitReferringColumns( (keyTable, keyColumn, isKeyColumnFormua, jdbcMapping) -> {
assertThat( keyTable, is( "other_entity" ) );
assertThat( keyColumn, is( "simple_entity_id" ) );
} );
foreignKeyDescriptor.visitTargetColumns( (targetTable, targetColumn, jdbcMapping) -> {
foreignKeyDescriptor.visitTargetColumns( (targetTable, targetColumn, isTargetColumnFormula, jdbcMapping) -> {
assertThat( targetTable, is( "simple_entity" ) );
assertThat( targetColumn, is( "id" ) );
} );

View File

@ -51,12 +51,12 @@ public class EntityWithBidirectionalAssociationTest {
final ToOneAttributeMapping childAttributeMapping = (ToOneAttributeMapping) childAssociation;
ForeignKeyDescriptor foreignKeyDescriptor = childAttributeMapping.getForeignKeyDescriptor();
foreignKeyDescriptor.visitReferringColumns( (keyTable, keyColumn, jdbcMapping) -> {
foreignKeyDescriptor.visitReferringColumns( (keyTable, keyColumn, isKeyColumnFormula, jdbcMapping) -> {
assertThat( keyTable, is( "PARENT" ) );
assertThat( keyColumn, is( "child_id" ) );
} );
foreignKeyDescriptor.visitTargetColumns( (targetTable, targetColumn, jdbcMapping) -> {
foreignKeyDescriptor.visitTargetColumns( (targetTable, targetColumn, isTargetColumnFormula, jdbcMapping) -> {
assertThat( targetTable, is( "CHILD" ) );
assertThat( targetColumn, is( "id" ) );
} );
@ -72,12 +72,12 @@ public class EntityWithBidirectionalAssociationTest {
final ToOneAttributeMapping parentAttributeMapping = (ToOneAttributeMapping) parentAssociation;
foreignKeyDescriptor = parentAttributeMapping.getForeignKeyDescriptor();
foreignKeyDescriptor.visitReferringColumns( (keyTable, keyColumn, jdbcMapping) -> {
foreignKeyDescriptor.visitReferringColumns( (keyTable, keyColumn, isKeyColumnFormula, jdbcMapping) -> {
assertThat( keyTable, is( "PARENT" ) );
assertThat( keyColumn, is( "child_id" ) );
} );
foreignKeyDescriptor.visitTargetColumns( (targetTable, targetColumn, jdbcMapping) -> {
foreignKeyDescriptor.visitTargetColumns( (targetTable, targetColumn, isTargetColumnFormula, jdbcMapping) -> {
assertThat( targetTable, is( "CHILD" ) );
assertThat( targetColumn, is( "id" ) );
} );

View File

@ -53,12 +53,12 @@ public class EntityWithOneBidirectionalJoinTableAssociationTest {
final ToOneAttributeMapping childAttributeMapping = (ToOneAttributeMapping) childAssociation;
ForeignKeyDescriptor foreignKeyDescriptor = childAttributeMapping.getForeignKeyDescriptor();
foreignKeyDescriptor.visitReferringColumns( (keyTable, keyColumn, jdbcMapping) -> {
foreignKeyDescriptor.visitReferringColumns( (keyTable, keyColumn, isKeyColumnFormula, jdbcMapping) -> {
assertThat( keyTable, is( "PARENT_CHILD" ) );
assertThat( keyColumn, is( "child_id" ) );
} );
foreignKeyDescriptor.visitTargetColumns( (targetTable, targetColumn, jdbcMapping) -> {
foreignKeyDescriptor.visitTargetColumns( (targetTable, targetColumn, isTargetColumnFormula, jdbcMapping) -> {
assertThat( targetTable, is( "CHILD" ) );
assertThat( targetColumn, is( "id" ) );
} );
@ -74,12 +74,12 @@ public class EntityWithOneBidirectionalJoinTableAssociationTest {
final ToOneAttributeMapping parentAttributeMapping = (ToOneAttributeMapping) parentAssociation;
foreignKeyDescriptor = parentAttributeMapping.getForeignKeyDescriptor();
foreignKeyDescriptor.visitReferringColumns( (keyTable, keyColumn, jdbcMapping) -> {
foreignKeyDescriptor.visitReferringColumns( (keyTable, keyColumn, isKeyColumnFormula, jdbcMapping) -> {
assertThat( keyTable, is( "PARENT_CHILD" ) );
assertThat( keyColumn, is( "parent_id" ) );
} );
foreignKeyDescriptor.visitTargetColumns( (targetTable, targetColumn, jdbcMapping) -> {
foreignKeyDescriptor.visitTargetColumns( (targetTable, targetColumn, isTargetColumnFormula, jdbcMapping) -> {
assertThat( targetTable, is( "PARENT" ) );
assertThat( targetColumn, is( "id" ) );
} );

View File

@ -47,12 +47,12 @@ public class EntityWithOneToOneJoinTableTest {
final ToOneAttributeMapping otherAttributeMapping = (ToOneAttributeMapping) other;
final ForeignKeyDescriptor foreignKeyDescriptor = otherAttributeMapping.getForeignKeyDescriptor();
foreignKeyDescriptor.visitReferringColumns( (keyTable, keyColumn, jdbcMapping) -> {
foreignKeyDescriptor.visitReferringColumns( (keyTable, keyColumn, isKeyColumnFormula, jdbcMapping) -> {
assertThat( keyTable, is( "Entity_SimpleEntity" ) );
assertThat( keyColumn, is( "other_id" ) );
} );
foreignKeyDescriptor.visitTargetColumns( (targetTable, targetColumn, jdbcMapping) -> {
foreignKeyDescriptor.visitTargetColumns( (targetTable, targetColumn, isTargetColumnFormula, jdbcMapping) -> {
assertThat( targetTable, is( "SIMPLE_ENTITY" ) );
assertThat( targetColumn, is( "id" ) );
} );

View File

@ -48,12 +48,12 @@ public class EntityWithOneToOneSharingPrimaryKeyTest {
final ToOneAttributeMapping otherAttributeMapping = (ToOneAttributeMapping) otherAssociation;
ForeignKeyDescriptor foreignKeyDescriptor = otherAttributeMapping.getForeignKeyDescriptor();
foreignKeyDescriptor.visitReferringColumns( (keyTable, keyColumn, jdbcMapping) -> {
foreignKeyDescriptor.visitReferringColumns( (keyTable, keyColumn, isKeyColumnFormula, jdbcMapping) -> {
assertThat( keyTable, is( "EntityWithOneToOneSharingPrimaryKey" ) );
assertThat( keyColumn, is( "id" ) );
} );
foreignKeyDescriptor.visitTargetColumns( (targetTable, targetColumn, jdbcMapping) -> {
foreignKeyDescriptor.visitTargetColumns( (targetTable, targetColumn, isTargetColumnFormula, jdbcMapping) -> {
assertThat( targetTable, is( "SIMPLE_ENTITY" ) );
assertThat( targetColumn, is( "id" ) );
} );

View File

@ -1,143 +0,0 @@
/*
* 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.test.annotations.formula;
import org.hibernate.annotations.Formula;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.Configuration;
import org.hibernate.testing.FailureExpected;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import javax.persistence.*;
import java.util.List;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.junit.Assert.assertEquals;
/**
* @author Алексей Макаров
* @author Gail Badner
*/
@TestForIssue(jiraKey = "HHH-7525")
public class FormulaNativeQueryTest extends BaseCoreFunctionalTestCase {
// Add your entities here.
@Override
protected Class[] getAnnotatedClasses() {
return new Class[]{
Foo.class
};
}
// Add in any settings that are specific to your test. See resources/hibernate.properties for the defaults.
@Override
protected void configure(Configuration configuration) {
super.configure(configuration);
configuration.setProperty(AvailableSettings.SHOW_SQL, Boolean.TRUE.toString());
configuration.setProperty(AvailableSettings.FORMAT_SQL, Boolean.TRUE.toString());
}
@Before
public void prepare() {
doInHibernate(
this::sessionFactory, session -> {
session.persist( new Foo( 1, 1 ) );
session.persist( new Foo( 1, 2 ) );
session.persist( new Foo( 2, 1 ) );
}
);
}
@After
public void cleanup() {
doInHibernate(
this::sessionFactory, session -> {
session.createQuery( "delete from Foo" ).executeUpdate();
}
);
}
@Test
@FailureExpected( jiraKey = "HHH-7525" )
public void testNativeQuery() throws Exception {
doInHibernate(
this::sessionFactory, session -> {
Query query = session.createNativeQuery( "SELECT ft.* FROM foo_table ft", Foo.class );
List<Foo> list = query.getResultList();
assertEquals( 3, list.size() );
}
);
}
@Test
public void testHql() throws Exception {
// Show that HQL does work
doInHibernate(
this::sessionFactory, session -> {
Query query = session.createQuery( "SELECT ft FROM Foo ft", Foo.class );
List<Foo> list = query.getResultList();
assertEquals(3, list.size());
}
);
}
@Entity(name = "Foo")
@Table(name = "foo_table")
public static class Foo {
private int id;
private int locationStart;
private int locationEnd;
private int distance;
public Foo() {
}
public Foo(int locationStart, int locationEnd) {
this.locationStart = locationStart;
this.locationEnd = locationEnd;
}
@Id
@GeneratedValue
public int getId() {
return id;
}
private void setId(int id) {
this.id = id;
}
public int getLocationStart() {
return locationStart;
}
public void setLocationStart(int locationStart) {
this.locationStart = locationStart;
}
public int getLocationEnd() {
return locationEnd;
}
public void setLocationEnd(int locationEnd) {
this.locationEnd = locationEnd;
}
@Formula("abs(locationEnd - locationStart)")
public int getDistance() {
return distance;
}
public void setDistance(int distance) {
this.distance = distance;
}
}
}

View File

@ -1,138 +0,0 @@
/*
* 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.test.annotations.formula;
import java.io.Serializable;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.annotations.Formula;
import org.hibernate.dialect.Oracle8iDialect;
import org.hibernate.dialect.PostgreSQL91Dialect;
import org.hibernate.dialect.SQLServer2005Dialect;
import org.hibernate.testing.DialectCheck;
import org.hibernate.testing.DialectChecks;
import org.hibernate.testing.RequiresDialect;
import org.hibernate.testing.RequiresDialectFeature;
import org.hibernate.testing.RequiresDialects;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
/**
* @author Vlad Mihalcea
*/
@RequiresDialectFeature( jiraKey = "HHH-10754", value = DialectChecks.SupportPartitionBy.class)
public class FormulaWithPartitionByTest extends BaseCoreFunctionalTestCase {
@Test
@TestForIssue(jiraKey = "HHH-10754")
public void testFormulaAnnotationWithPartitionBy() {
Session session = openSession();
Transaction transaction = session.beginTransaction();
DisplayItem displayItem20_1 = new DisplayItem();
displayItem20_1.setId( 1 );
displayItem20_1.setDiscountCode( "20" );
displayItem20_1.setDiscountValue( 12.34d );
DisplayItem displayItem20_2 = new DisplayItem();
displayItem20_2.setId( 2 );
displayItem20_2.setDiscountCode( "20" );
displayItem20_2.setDiscountValue( 15.89 );
DisplayItem displayItem100 = new DisplayItem();
displayItem100.setId( 3 );
displayItem100.setDiscountCode( "100" );
displayItem100.setDiscountValue( 12.5 );
session.persist( displayItem20_1 );
session.persist( displayItem20_2 );
session.persist( displayItem100 );
transaction.commit();
session.close();
session = openSession();
transaction = session.beginTransaction();
List<DisplayItem> displayItems = session.createQuery( "select di from DisplayItem di order by di.id", DisplayItem.class).getResultList();
assertNotNull( displayItems );
assertEquals( displayItems.size(), 3 );
assertEquals( 1, displayItems.get( 0 ).getItemsByCode().intValue() );
assertEquals( 2, displayItems.get( 1 ).getItemsByCode().intValue() );
assertEquals( 1, displayItems.get( 2 ).getItemsByCode().intValue() );
transaction.commit();
session.close();
}
@Override
public Class<?>[] getAnnotatedClasses() {
return new Class<?>[] {DisplayItem.class};
}
@Entity(name = "DisplayItem")
public static class DisplayItem implements Serializable {
@Id
private Integer id;
@Column(name = "DISCOUNT_CODE")
private String discountCode;
@Column(name = "DISCOUNT_VALUE")
private Double discountValue;
@Formula("ROW_NUMBER() OVER( PARTITION BY DISCOUNT_CODE ORDER BY SIGN(DISCOUNT_VALUE) DESC )")
private Integer itemsByCode;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getDiscountCode() {
return discountCode;
}
public void setDiscountCode(String discountCode) {
this.discountCode = discountCode;
}
public Integer getItemsByCode() {
return itemsByCode;
}
public void setItemsByCode(Integer itemsByCode) {
this.itemsByCode = itemsByCode;
}
public Double getDiscountValue() {
return discountValue;
}
public void setDiscountValue(Double discountValue) {
this.discountValue = discountValue;
}
}
}