implement @where and @whereJoinTable
This commit is contained in:
parent
f919358e0c
commit
9ef62f1fb8
|
@ -975,7 +975,7 @@ public abstract class CollectionBinder {
|
|||
FilterJoinTable simpleFilterJoinTable = property.getAnnotation( FilterJoinTable.class );
|
||||
if ( simpleFilterJoinTable != null ) {
|
||||
if ( hasAssociationTable ) {
|
||||
collection.addManyToManyFilter(simpleFilterJoinTable.name(), simpleFilterJoinTable.condition(),
|
||||
collection.addFilter(simpleFilterJoinTable.name(), simpleFilterJoinTable.condition(),
|
||||
simpleFilterJoinTable.deduceAliasInjectionPoints(),
|
||||
toAliasTableMap(simpleFilterJoinTable.aliases()), toAliasEntityMap(simpleFilterJoinTable.aliases()));
|
||||
}
|
||||
|
@ -990,7 +990,7 @@ public abstract class CollectionBinder {
|
|||
if ( filterJoinTables != null ) {
|
||||
for (FilterJoinTable filter : filterJoinTables.value()) {
|
||||
if ( hasAssociationTable ) {
|
||||
collection.addManyToManyFilter(filter.name(), filter.condition(),
|
||||
collection.addFilter(filter.name(), filter.condition(),
|
||||
filter.deduceAliasInjectionPoints(),
|
||||
toAliasTableMap(filter.aliases()), toAliasEntityMap(filter.aliases()));
|
||||
}
|
||||
|
|
|
@ -19,16 +19,11 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
|
|||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
||||
import org.hibernate.persister.collection.AbstractCollectionPersister;
|
||||
import org.hibernate.persister.entity.AbstractEntityPersister;
|
||||
import org.hibernate.persister.entity.Joinable;
|
||||
import org.hibernate.sql.Template;
|
||||
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
||||
import org.hibernate.sql.ast.tree.predicate.FilterPredicate;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
import static org.hibernate.internal.util.StringHelper.join;
|
||||
import static org.hibernate.internal.util.StringHelper.safeInterning;
|
||||
|
||||
/**
|
||||
|
@ -94,7 +89,7 @@ public class FilterHelper {
|
|||
return aliasTableMap.size() == 1 && aliasTableMap.containsKey( null );
|
||||
}
|
||||
|
||||
public boolean isAffectedBy(Map enabledFilters) {
|
||||
public boolean isAffectedBy(Map<String, Filter> enabledFilters) {
|
||||
for ( String filterName : filterNames ) {
|
||||
if ( enabledFilters.containsKey( filterName ) ) {
|
||||
return true;
|
||||
|
@ -103,13 +98,13 @@ public class FilterHelper {
|
|||
return false;
|
||||
}
|
||||
|
||||
public String render(FilterAliasGenerator aliasGenerator, Map enabledFilters) {
|
||||
public String render(FilterAliasGenerator aliasGenerator, Map<String, Filter> enabledFilters) {
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
render( buffer, aliasGenerator, enabledFilters );
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
public void render(StringBuilder buffer, FilterAliasGenerator aliasGenerator, Map enabledFilters) {
|
||||
public void render(StringBuilder buffer, FilterAliasGenerator aliasGenerator, Map<String, Filter> enabledFilters) {
|
||||
if ( CollectionHelper.isEmpty( filterNames ) ) {
|
||||
return;
|
||||
}
|
||||
|
@ -137,11 +132,11 @@ public class FilterHelper {
|
|||
);
|
||||
}
|
||||
else if ( isTableFromPersistentClass( aliasTableMap ) ) {
|
||||
return condition.replace( "{alias}", aliasGenerator.getAlias( aliasTableMap.get( null ) ) );
|
||||
return StringHelper.replace( condition, "{alias}", aliasGenerator.getAlias( aliasTableMap.get( null ) ) );
|
||||
}
|
||||
else {
|
||||
for ( Map.Entry<String, String> entry : aliasTableMap.entrySet() ) {
|
||||
condition = condition.replace(
|
||||
condition = StringHelper.replace( condition,
|
||||
"{" + entry.getKey() + "}",
|
||||
aliasGenerator.getAlias( entry.getValue() )
|
||||
);
|
||||
|
@ -151,22 +146,13 @@ public class FilterHelper {
|
|||
}
|
||||
|
||||
public static FilterPredicate createFilterPredicate(LoadQueryInfluencers loadQueryInfluencers, Joinable joinable, String alias) {
|
||||
if ( loadQueryInfluencers.hasEnabledFilters() ) {
|
||||
final String filterFragment;
|
||||
if ( joinable instanceof AbstractCollectionPersister && ( (AbstractCollectionPersister) joinable ).isManyToMany() ) {
|
||||
filterFragment = ( (AbstractCollectionPersister) joinable ).getManyToManyFilterFragment(
|
||||
alias,
|
||||
loadQueryInfluencers.getEnabledFilters()
|
||||
);
|
||||
}
|
||||
else {
|
||||
filterFragment = joinable.filterFragment( alias, loadQueryInfluencers.getEnabledFilters() );
|
||||
}
|
||||
if ( ! StringHelper.isEmptyOrWhiteSpace( filterFragment ) ) {
|
||||
return doCreateFilterPredicate( filterFragment, loadQueryInfluencers.getEnabledFilters() );
|
||||
}
|
||||
final String filterFragment = joinable.filterFragment( alias, loadQueryInfluencers.getEnabledFilters() );
|
||||
if ( StringHelper.isNotEmpty( filterFragment ) ) {
|
||||
return doCreateFilterPredicate( filterFragment, loadQueryInfluencers.getEnabledFilters() );
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static FilterPredicate doCreateFilterPredicate(String filterFragment, Map<String, Filter> enabledFilters) {
|
||||
|
|
|
@ -227,11 +227,6 @@ public class LoaderSelectBuilder {
|
|||
rootQuerySpec.getFromClause().addRoot( rootTableGroup );
|
||||
sqlAstCreationState.getFromClauseAccess().registerTableGroup( rootNavigablePath, rootTableGroup );
|
||||
|
||||
if ( loadable instanceof PluralAttributeMapping ) {
|
||||
applyFiltering( rootQuerySpec, rootTableGroup, (PluralAttributeMapping) loadable );
|
||||
applyOrdering( rootTableGroup, (PluralAttributeMapping) loadable );
|
||||
}
|
||||
|
||||
if ( partsToSelect != null && !partsToSelect.isEmpty() ) {
|
||||
domainResults = new ArrayList<>( partsToSelect.size() );
|
||||
for ( ModelPart part : partsToSelect ) {
|
||||
|
@ -282,6 +277,12 @@ public class LoaderSelectBuilder {
|
|||
sqlAstCreationState
|
||||
);
|
||||
|
||||
if ( loadable instanceof PluralAttributeMapping ) {
|
||||
final PluralAttributeMapping pluralAttributeMapping = (PluralAttributeMapping) loadable;
|
||||
applyFiltering( rootQuerySpec, rootTableGroup, pluralAttributeMapping );
|
||||
applyOrdering( rootTableGroup, pluralAttributeMapping );
|
||||
}
|
||||
|
||||
if ( orderByFragments != null ) {
|
||||
orderByFragments.forEach(
|
||||
(orderByFragment, tableGroup) -> orderByFragment.apply( rootQuerySpec, tableGroup, sqlAstCreationState )
|
||||
|
@ -380,22 +381,20 @@ public class LoaderSelectBuilder {
|
|||
}
|
||||
|
||||
private void applyFiltering(QuerySpec querySpec, TableGroup tableGroup, PluralAttributeMapping pluralAttributeMapping) {
|
||||
if ( loadQueryInfluencers.hasEnabledFilters() ) {
|
||||
final Joinable joinable = pluralAttributeMapping
|
||||
.getCollectionDescriptor()
|
||||
.getCollectionType()
|
||||
.getAssociatedJoinable( creationContext.getSessionFactory() );
|
||||
assert joinable instanceof AbstractCollectionPersister;
|
||||
final String tableExpression = joinable.getTableName();
|
||||
final String tableAlias = tableGroup.resolveTableReference( tableExpression ).getIdentificationVariable();
|
||||
final Predicate filterPredicate = FilterHelper.createFilterPredicate(
|
||||
loadQueryInfluencers,
|
||||
joinable,
|
||||
tableAlias
|
||||
);
|
||||
if ( filterPredicate != null ) {
|
||||
querySpec.applyPredicate( filterPredicate );
|
||||
}
|
||||
final Joinable joinable = pluralAttributeMapping
|
||||
.getCollectionDescriptor()
|
||||
.getCollectionType()
|
||||
.getAssociatedJoinable( creationContext.getSessionFactory() );
|
||||
assert joinable instanceof AbstractCollectionPersister;
|
||||
final String tableExpression = joinable.getTableName();
|
||||
final String tableAlias = tableGroup.resolveTableReference( tableExpression ).getIdentificationVariable();
|
||||
final Predicate filterPredicate = FilterHelper.createFilterPredicate(
|
||||
loadQueryInfluencers,
|
||||
joinable,
|
||||
tableAlias
|
||||
);
|
||||
if ( filterPredicate != null ) {
|
||||
querySpec.applyPredicate( filterPredicate );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -511,15 +510,16 @@ public class LoaderSelectBuilder {
|
|||
fetches.add( fetch );
|
||||
|
||||
if ( fetchable instanceof PluralAttributeMapping && fetchTiming == FetchTiming.IMMEDIATE && joined ) {
|
||||
final PluralAttributeMapping pluralAttributeMapping = (PluralAttributeMapping) fetchable;
|
||||
applyFiltering(
|
||||
querySpec,
|
||||
creationState.getFromClauseAccess().getTableGroup( fetchablePath ),
|
||||
( (PluralAttributeMapping) fetchable )
|
||||
pluralAttributeMapping
|
||||
);
|
||||
applyOrdering(
|
||||
querySpec,
|
||||
fetchablePath,
|
||||
( (PluralAttributeMapping) fetchable ),
|
||||
pluralAttributeMapping,
|
||||
creationState
|
||||
);
|
||||
}
|
||||
|
@ -590,10 +590,6 @@ public class LoaderSelectBuilder {
|
|||
rootQuerySpec.getFromClause().addRoot( rootTableGroup );
|
||||
sqlAstCreationState.getFromClauseAccess().registerTableGroup( rootNavigablePath, rootTableGroup );
|
||||
|
||||
// NOTE : no need to check - we are explicitly processing a plural-attribute
|
||||
applyFiltering( rootQuerySpec, rootTableGroup, attributeMapping );
|
||||
applyOrdering( rootTableGroup, attributeMapping );
|
||||
|
||||
// generate and apply the restriction
|
||||
applySubSelectRestriction(
|
||||
rootQuerySpec,
|
||||
|
@ -603,6 +599,10 @@ public class LoaderSelectBuilder {
|
|||
sqlAstCreationState
|
||||
);
|
||||
|
||||
// NOTE : no need to check - we are explicitly processing a plural-attribute
|
||||
applyFiltering( rootQuerySpec, rootTableGroup, attributeMapping );
|
||||
applyOrdering( rootTableGroup, attributeMapping );
|
||||
|
||||
// register the jdbc-parameters
|
||||
subselect.getLoadingJdbcParameters().forEach( jdbcParameterConsumer );
|
||||
|
||||
|
|
|
@ -16,7 +16,6 @@ import java.util.HashMap;
|
|||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.FetchMode;
|
||||
|
@ -1781,13 +1780,15 @@ public abstract class AbstractCollectionPersister
|
|||
public abstract boolean isManyToMany();
|
||||
|
||||
@Override
|
||||
public String getManyToManyFilterFragment(String alias, Map enabledFilters) {
|
||||
public String getManyToManyFilterFragment(String alias, Map<String, Filter> enabledFilters) {
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
manyToManyFilterHelper.render( buffer, elementPersister.getFilterAliasGenerator(alias), enabledFilters );
|
||||
|
||||
if ( manyToManyWhereString != null ) {
|
||||
buffer.append( " and " )
|
||||
.append( StringHelper.replace( manyToManyWhereTemplate, Template.TEMPLATE, alias ) );
|
||||
if ( buffer.length() > 0 ) {
|
||||
buffer.append( " and " );
|
||||
}
|
||||
buffer.append( StringHelper.replace( manyToManyWhereTemplate, Template.TEMPLATE, alias ) );
|
||||
}
|
||||
|
||||
return buffer.toString();
|
||||
|
@ -1917,15 +1918,15 @@ public abstract class AbstractCollectionPersister
|
|||
}
|
||||
|
||||
protected String filterFragment(String alias) throws MappingException {
|
||||
return hasWhere() ? " and " + getSQLWhereString( alias ) : "";
|
||||
return hasWhere() ? getSQLWhereString( alias ) : "";
|
||||
}
|
||||
|
||||
protected String filterFragment(String alias, Set<String> treatAsDeclarations) throws MappingException {
|
||||
return hasWhere() ? " and " + getSQLWhereString( alias ) : "";
|
||||
return hasWhere() ? getSQLWhereString( alias ) : "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String filterFragment(String alias, Map enabledFilters) throws MappingException {
|
||||
public String filterFragment(String alias, Map<String, Filter> enabledFilters) throws MappingException {
|
||||
StringBuilder sessionFilterFragment = new StringBuilder();
|
||||
filterHelper.render( sessionFilterFragment, getFilterAliasGenerator(alias), enabledFilters );
|
||||
|
||||
|
@ -1935,7 +1936,7 @@ public abstract class AbstractCollectionPersister
|
|||
@Override
|
||||
public String filterFragment(
|
||||
String alias,
|
||||
Map enabledFilters,
|
||||
Map<String, Filter> enabledFilters,
|
||||
Set<String> treatAsDeclarations) {
|
||||
StringBuilder sessionFilterFragment = new StringBuilder();
|
||||
filterHelper.render( sessionFilterFragment, getFilterAliasGenerator(alias), enabledFilters );
|
||||
|
|
|
@ -12,6 +12,7 @@ import java.sql.SQLException;
|
|||
import java.util.Comparator;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.Filter;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
|
@ -169,7 +170,7 @@ public interface CollectionPersister extends CollectionDefinition {
|
|||
*/
|
||||
boolean isManyToMany();
|
||||
|
||||
String getManyToManyFilterFragment(String alias, Map enabledFilters);
|
||||
String getManyToManyFilterFragment(String alias, Map<String, Filter> enabledFilters);
|
||||
|
||||
/**
|
||||
* Is this an "indexed" collection? (list or map)
|
||||
|
|
|
@ -4037,14 +4037,14 @@ public abstract class AbstractEntityPersister
|
|||
}
|
||||
|
||||
@Override
|
||||
public String filterFragment(String alias, Map enabledFilters) throws MappingException {
|
||||
public String filterFragment(String alias, Map<String, Filter> enabledFilters) throws MappingException {
|
||||
final StringBuilder sessionFilterFragment = new StringBuilder();
|
||||
filterHelper.render( sessionFilterFragment, getFilterAliasGenerator( alias ), enabledFilters );
|
||||
return sessionFilterFragment.append( filterFragment( alias ) ).toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String filterFragment(String alias, Map enabledFilters, Set<String> treatAsDeclarations) {
|
||||
public String filterFragment(String alias, Map<String, Filter> enabledFilters, Set<String> treatAsDeclarations) {
|
||||
final StringBuilder sessionFilterFragment = new StringBuilder();
|
||||
filterHelper.render( sessionFilterFragment, getFilterAliasGenerator( alias ), enabledFilters );
|
||||
return sessionFilterFragment.append( filterFragment( alias, treatAsDeclarations ) ).toString();
|
||||
|
|
|
@ -8,6 +8,7 @@ package org.hibernate.persister.entity;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.Filter;
|
||||
import org.hibernate.MappingException;
|
||||
|
||||
/**
|
||||
|
@ -78,12 +79,12 @@ public interface Joinable {
|
|||
/**
|
||||
* Get the where clause filter, given a query alias and considering enabled session filters
|
||||
*/
|
||||
public String filterFragment(String alias, Map enabledFilters) throws MappingException;
|
||||
public String filterFragment(String alias, Map<String, Filter> enabledFilters) throws MappingException;
|
||||
|
||||
/**
|
||||
* Get the where clause filter, given a query alias and considering enabled session filters
|
||||
*/
|
||||
public String filterFragment(String alias, Map enabledFilters, Set<String> treatAsDeclarations) throws MappingException;
|
||||
public String filterFragment(String alias, Map<String, Filter> enabledFilters, Set<String> treatAsDeclarations) throws MappingException;
|
||||
|
||||
public String oneToManyFilterFragment(String alias) throws MappingException;
|
||||
|
||||
|
|
|
@ -982,9 +982,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
|
||||
@Override
|
||||
protected String filterFragment(String alias) {
|
||||
return hasWhere()
|
||||
? " and " + getSQLWhereString( generateFilterConditionAlias( alias ) )
|
||||
: "";
|
||||
return hasWhere() ? getSQLWhereString( generateFilterConditionAlias( alias ) ) : "";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -8,6 +8,7 @@ package org.hibernate.persister.entity;
|
|||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
|
@ -568,11 +569,12 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
|
||||
@Override
|
||||
protected String filterFragment(String alias) throws MappingException {
|
||||
String result = discriminatorFilterFragment( alias );
|
||||
if ( hasWhere() ) {
|
||||
result += " and " + getSQLWhereString( alias );
|
||||
return discriminatorFilterFragment( alias ) + " and " + getSQLWhereString( alias );
|
||||
}
|
||||
else {
|
||||
return "";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private String discriminatorFilterFragment(String alias) throws MappingException {
|
||||
|
@ -594,11 +596,12 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
|
||||
@Override
|
||||
protected String filterFragment(String alias, Set<String> treatAsDeclarations) {
|
||||
String result = discriminatorFilterFragment( alias, treatAsDeclarations );
|
||||
if ( hasWhere() ) {
|
||||
result += " and " + getSQLWhereString( alias );
|
||||
return discriminatorFilterFragment( alias, treatAsDeclarations ) + " and " + getSQLWhereString( alias );
|
||||
}
|
||||
else {
|
||||
return "";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private String discriminatorFilterFragment(String alias, Set<String> treatAsDeclarations) {
|
||||
|
|
|
@ -329,9 +329,7 @@ public class UnionSubclassEntityPersister extends AbstractEntityPersister {
|
|||
|
||||
@Override
|
||||
protected String filterFragment(String name) {
|
||||
return hasWhere()
|
||||
? " and " + getSQLWhereString( name )
|
||||
: "";
|
||||
return hasWhere() ? getSQLWhereString( name ) : "";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,172 @@
|
|||
/*
|
||||
* 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.loading.filter;
|
||||
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.JoinTable;
|
||||
import javax.persistence.ManyToMany;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Root;
|
||||
|
||||
import org.hibernate.annotations.WhereJoinTable;
|
||||
|
||||
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.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* @author Nathan Xu
|
||||
*/
|
||||
@DomainModel(
|
||||
annotatedClasses = {
|
||||
WhereJoinTableTests.Book.class,
|
||||
WhereJoinTableTests.Reader.class
|
||||
}
|
||||
)
|
||||
@SessionFactory
|
||||
public class WhereJoinTableTests {
|
||||
|
||||
@BeforeEach
|
||||
void setUp(SessionFactoryScope scope) {
|
||||
scope.inTransaction( session -> {
|
||||
session.doWork( connection -> {
|
||||
try ( Statement statement = connection.createStatement() ) {
|
||||
statement.executeUpdate(
|
||||
"ALTER TABLE Book_Reader ADD created_on TIMESTAMP DEFAULT CURRENT_TIMESTAMP"
|
||||
);
|
||||
}
|
||||
} );
|
||||
|
||||
final Book book = new Book();
|
||||
book.setId( 1L );
|
||||
book.setTitle( "High-Performance Java Persistence" );
|
||||
book.setAuthor( "Vad Mihalcea" );
|
||||
session.persist( book );
|
||||
|
||||
final Reader reader1 = new Reader();
|
||||
reader1.setId( 1L );
|
||||
reader1.setName( "John Doe" );
|
||||
session.persist( reader1 );
|
||||
|
||||
final Reader reader2 = new Reader();
|
||||
reader2.setId( 2L );
|
||||
reader2.setName( "John Doe Jr." );
|
||||
session.persist( reader2 );
|
||||
} );
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWhereJoinTable(SessionFactoryScope scope) {
|
||||
scope.inTransaction( session -> {
|
||||
session.doWork( connection -> {
|
||||
try ( Statement statement = connection.createStatement() ) {
|
||||
statement.executeUpdate(
|
||||
"INSERT INTO Book_Reader " +
|
||||
" (book_id, reader_id) " +
|
||||
"VALUES " +
|
||||
" (1, 1) "
|
||||
);
|
||||
statement.executeUpdate(
|
||||
"INSERT INTO Book_Reader " +
|
||||
" (book_id, reader_id, created_on) " +
|
||||
"VALUES " +
|
||||
" (1, 2, DATEADD( 'DAY', -10, CURRENT_TIMESTAMP() )) "
|
||||
);
|
||||
}}
|
||||
);
|
||||
|
||||
final Book book = session.find( Book.class, 1L );
|
||||
|
||||
assertThat( book.getCurrentWeekReaders().size(), is( 1 ) );
|
||||
} );
|
||||
}
|
||||
|
||||
@Entity(name = "Book")
|
||||
public static class Book {
|
||||
|
||||
@Id
|
||||
private Long id;
|
||||
|
||||
private String title;
|
||||
|
||||
private String author;
|
||||
|
||||
@ManyToMany
|
||||
@JoinTable(
|
||||
name = "Book_Reader",
|
||||
joinColumns = @JoinColumn(name = "book_id"),
|
||||
inverseJoinColumns = @JoinColumn(name = "reader_id")
|
||||
)
|
||||
@WhereJoinTable( clause = "created_on > DATEADD( 'DAY', -7, CURRENT_TIMESTAMP() )")
|
||||
private List<Reader> currentWeekReaders = new ArrayList<>();
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
public void setAuthor(String author) {
|
||||
this.author = author;
|
||||
}
|
||||
|
||||
public List<Reader> getCurrentWeekReaders() {
|
||||
return currentWeekReaders;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Entity(name = "Reader")
|
||||
public static class Reader {
|
||||
|
||||
@Id
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,210 @@
|
|||
/*
|
||||
* 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.loading.filter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Root;
|
||||
|
||||
import org.hibernate.annotations.Where;
|
||||
|
||||
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.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* @author Nathan Xu
|
||||
*/
|
||||
@DomainModel(
|
||||
annotatedClasses = {
|
||||
WhereTests.Client.class,
|
||||
WhereTests.Account.class
|
||||
}
|
||||
)
|
||||
@SessionFactory
|
||||
public class WhereTests {
|
||||
|
||||
@BeforeEach
|
||||
void setUp(SessionFactoryScope scope) {
|
||||
scope.inTransaction( session -> {
|
||||
|
||||
Client client = new Client();
|
||||
client.setId( 1L );
|
||||
client.setName( "John Doe" );
|
||||
session.persist( client );
|
||||
|
||||
Account account1 = new Account( );
|
||||
account1.setId( 1L );
|
||||
account1.setType( AccountType.CREDIT );
|
||||
account1.setAmount( 5000d );
|
||||
account1.setRate( 1.25 / 100 );
|
||||
account1.setActive( true );
|
||||
account1.setClient( client );
|
||||
client.getCreditAccounts().add( account1 );
|
||||
session.persist( account1 );
|
||||
|
||||
Account account2 = new Account( );
|
||||
account2.setId( 2L );
|
||||
account2.setType( AccountType.DEBIT );
|
||||
account2.setAmount( 0d );
|
||||
account2.setRate( 1.05 / 100 );
|
||||
account2.setActive( false );
|
||||
account2.setClient( client );
|
||||
client.getDebitAccounts().add( account2 );
|
||||
session.persist( account2 );
|
||||
|
||||
Account account3 = new Account( );
|
||||
account3.setType( AccountType.DEBIT );
|
||||
account3.setId( 3L );
|
||||
account3.setAmount( 250d );
|
||||
account3.setRate( 1.05 / 100 );
|
||||
account3.setActive( true );
|
||||
account3.setClient( client );
|
||||
client.getDebitAccounts().add( account3 );
|
||||
session.persist( account3 );
|
||||
} );
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWhere(SessionFactoryScope scope) {
|
||||
scope.inTransaction( session -> {
|
||||
final Client client = session.find( Client.class, 1L );
|
||||
assertThat( client.getCreditAccounts().size(), is( 1 ) );
|
||||
assertThat( client.getDebitAccounts().size(), is( 1 ) );
|
||||
} );
|
||||
}
|
||||
|
||||
public enum AccountType {
|
||||
DEBIT,
|
||||
CREDIT
|
||||
}
|
||||
|
||||
@Entity(name = "Client")
|
||||
public static class Client {
|
||||
|
||||
@Id
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
@Where( clause = "account_type = 'DEBIT'")
|
||||
@OneToMany(mappedBy = "client")
|
||||
private List<Account> debitAccounts = new ArrayList<>();
|
||||
|
||||
@Where( clause = "account_type = 'CREDIT'")
|
||||
@OneToMany(mappedBy = "client")
|
||||
private List<Account> creditAccounts = new ArrayList<>();
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public List<Account> getDebitAccounts() {
|
||||
return debitAccounts;
|
||||
}
|
||||
|
||||
public List<Account> getCreditAccounts() {
|
||||
return creditAccounts;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Entity(name = "Account")
|
||||
@Where( clause = "active = true" )
|
||||
public static class Account {
|
||||
|
||||
@Id
|
||||
private Long id;
|
||||
|
||||
@ManyToOne
|
||||
private Client client;
|
||||
|
||||
@Column(name = "account_type")
|
||||
@Enumerated(EnumType.STRING)
|
||||
private AccountType type;
|
||||
|
||||
private Double amount;
|
||||
|
||||
private Double rate;
|
||||
|
||||
private boolean active;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Client getClient() {
|
||||
return client;
|
||||
}
|
||||
|
||||
public void setClient(Client client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
public AccountType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(AccountType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public Double getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
public void setAmount(Double amount) {
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
public Double getRate() {
|
||||
return rate;
|
||||
}
|
||||
|
||||
public void setRate(Double rate) {
|
||||
this.rate = rate;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
public void setActive(boolean active) {
|
||||
this.active = active;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -104,7 +104,7 @@ public class FilterBasicsTests implements SessionFactoryScopeAware {
|
|||
|
||||
@ParameterizedTest
|
||||
@ValueSource( strings = { "true", "false" } )
|
||||
void testLoadFilterOnEntity(boolean enableFilter) {
|
||||
void testFilterOnEntity(boolean enableFilter) {
|
||||
scope.inTransaction( session -> {
|
||||
if ( enableFilter ) {
|
||||
session.enableFilter( "activeAccount" ).setParameter( "active", true );
|
||||
|
@ -123,7 +123,7 @@ public class FilterBasicsTests implements SessionFactoryScopeAware {
|
|||
|
||||
@ParameterizedTest
|
||||
@ValueSource( strings = { "true", "false" } )
|
||||
void testLoadFilterOnCollectionField(boolean enableFilter) {
|
||||
void testFilterOnCollectionField(boolean enableFilter) {
|
||||
scope.inTransaction( session -> {
|
||||
if ( enableFilter ) {
|
||||
session.enableFilter( "activeAccount" ).setParameter( "active", true );
|
||||
|
|
|
@ -22,6 +22,7 @@ import javax.persistence.ManyToMany;
|
|||
import javax.persistence.OrderColumn;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.JoinType;
|
||||
import javax.persistence.criteria.Root;
|
||||
|
||||
import org.hibernate.annotations.FilterDef;
|
||||
|
@ -211,6 +212,7 @@ public class FilterJoinTableTests {
|
|||
private static <T> CriteriaQuery<T> createCriteriaQuery(CriteriaBuilder criteriaBuilder, Class<T> entityClass, String idFieldName, Object idValue) {
|
||||
final CriteriaQuery<T> criteria = criteriaBuilder.createQuery( entityClass );
|
||||
Root<T> root = criteria.from( entityClass );
|
||||
root.fetch( "accounts", JoinType.INNER );
|
||||
criteria.select( root );
|
||||
criteria.where( criteriaBuilder.equal( root.get( idFieldName ), criteriaBuilder.literal( idValue ) ) );
|
||||
return criteria;
|
||||
|
|
|
@ -0,0 +1,182 @@
|
|||
/*
|
||||
* 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.query.criteria.filter;
|
||||
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.JoinTable;
|
||||
import javax.persistence.ManyToMany;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Root;
|
||||
|
||||
import org.hibernate.annotations.WhereJoinTable;
|
||||
|
||||
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.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* @author Nathan Xu
|
||||
*/
|
||||
@DomainModel(
|
||||
annotatedClasses = {
|
||||
WhereJoinTableTests.Book.class,
|
||||
WhereJoinTableTests.Reader.class
|
||||
}
|
||||
)
|
||||
@SessionFactory
|
||||
public class WhereJoinTableTests {
|
||||
|
||||
@BeforeEach
|
||||
void setUp(SessionFactoryScope scope) {
|
||||
scope.inTransaction( session -> {
|
||||
session.doWork( connection -> {
|
||||
try ( Statement statement = connection.createStatement() ) {
|
||||
statement.executeUpdate(
|
||||
"ALTER TABLE Book_Reader ADD created_on TIMESTAMP DEFAULT CURRENT_TIMESTAMP"
|
||||
);
|
||||
}
|
||||
} );
|
||||
|
||||
final Book book = new Book();
|
||||
book.setId( 1L );
|
||||
book.setTitle( "High-Performance Java Persistence" );
|
||||
book.setAuthor( "Vad Mihalcea" );
|
||||
session.persist( book );
|
||||
|
||||
final Reader reader1 = new Reader();
|
||||
reader1.setId( 1L );
|
||||
reader1.setName( "John Doe" );
|
||||
session.persist( reader1 );
|
||||
|
||||
final Reader reader2 = new Reader();
|
||||
reader2.setId( 2L );
|
||||
reader2.setName( "John Doe Jr." );
|
||||
session.persist( reader2 );
|
||||
} );
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWhereJoinTable(SessionFactoryScope scope) {
|
||||
scope.inTransaction( session -> {
|
||||
session.doWork( connection -> {
|
||||
try ( Statement statement = connection.createStatement() ) {
|
||||
statement.executeUpdate(
|
||||
"INSERT INTO Book_Reader " +
|
||||
" (book_id, reader_id) " +
|
||||
"VALUES " +
|
||||
" (1, 1) "
|
||||
);
|
||||
statement.executeUpdate(
|
||||
"INSERT INTO Book_Reader " +
|
||||
" (book_id, reader_id, created_on) " +
|
||||
"VALUES " +
|
||||
" (1, 2, DATEADD( 'DAY', -10, CURRENT_TIMESTAMP() )) "
|
||||
);
|
||||
}}
|
||||
);
|
||||
|
||||
final CriteriaBuilder criteriaBuilder = scope.getSessionFactory().getCriteriaBuilder();
|
||||
final CriteriaQuery<Book> criteriaQuery = createCriteriaQuery( criteriaBuilder, Book.class, "id", 1L );
|
||||
final Book book = session.createQuery( criteriaQuery ).uniqueResult();
|
||||
|
||||
assertThat( book.getCurrentWeekReaders().size(), is( 1 ) );
|
||||
} );
|
||||
}
|
||||
|
||||
@Entity(name = "Book")
|
||||
public static class Book {
|
||||
|
||||
@Id
|
||||
private Long id;
|
||||
|
||||
private String title;
|
||||
|
||||
private String author;
|
||||
|
||||
@ManyToMany
|
||||
@JoinTable(
|
||||
name = "Book_Reader",
|
||||
joinColumns = @JoinColumn(name = "book_id"),
|
||||
inverseJoinColumns = @JoinColumn(name = "reader_id")
|
||||
)
|
||||
@WhereJoinTable( clause = "created_on > DATEADD( 'DAY', -7, CURRENT_TIMESTAMP() )")
|
||||
private List<Reader> currentWeekReaders = new ArrayList<>();
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
public void setAuthor(String author) {
|
||||
this.author = author;
|
||||
}
|
||||
|
||||
public List<Reader> getCurrentWeekReaders() {
|
||||
return currentWeekReaders;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Entity(name = "Reader")
|
||||
public static class Reader {
|
||||
|
||||
@Id
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> CriteriaQuery<T> createCriteriaQuery(CriteriaBuilder criteriaBuilder, Class<T> entityClass, String idFieldName, Object idValue) {
|
||||
final CriteriaQuery<T> criteria = criteriaBuilder.createQuery( entityClass );
|
||||
Root<T> root = criteria.from( entityClass );
|
||||
criteria.select( root );
|
||||
criteria.where( criteriaBuilder.equal( root.get( idFieldName ), criteriaBuilder.literal( idValue ) ) );
|
||||
return criteria;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,221 @@
|
|||
/*
|
||||
* 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.query.criteria.filter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Root;
|
||||
|
||||
import org.hibernate.annotations.Where;
|
||||
|
||||
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.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* @author Nathan Xu
|
||||
*/
|
||||
@DomainModel(
|
||||
annotatedClasses = {
|
||||
WhereTests.Client.class,
|
||||
WhereTests.Account.class
|
||||
}
|
||||
)
|
||||
@SessionFactory
|
||||
public class WhereTests {
|
||||
|
||||
@BeforeEach
|
||||
void setUp(SessionFactoryScope scope) {
|
||||
scope.inTransaction( session -> {
|
||||
|
||||
Client client = new Client();
|
||||
client.setId( 1L );
|
||||
client.setName( "John Doe" );
|
||||
session.persist( client );
|
||||
|
||||
Account account1 = new Account( );
|
||||
account1.setId( 1L );
|
||||
account1.setType( AccountType.CREDIT );
|
||||
account1.setAmount( 5000d );
|
||||
account1.setRate( 1.25 / 100 );
|
||||
account1.setActive( true );
|
||||
account1.setClient( client );
|
||||
client.getCreditAccounts().add( account1 );
|
||||
session.persist( account1 );
|
||||
|
||||
Account account2 = new Account( );
|
||||
account2.setId( 2L );
|
||||
account2.setType( AccountType.DEBIT );
|
||||
account2.setAmount( 0d );
|
||||
account2.setRate( 1.05 / 100 );
|
||||
account2.setActive( false );
|
||||
account2.setClient( client );
|
||||
client.getDebitAccounts().add( account2 );
|
||||
session.persist( account2 );
|
||||
|
||||
Account account3 = new Account( );
|
||||
account3.setType( AccountType.DEBIT );
|
||||
account3.setId( 3L );
|
||||
account3.setAmount( 250d );
|
||||
account3.setRate( 1.05 / 100 );
|
||||
account3.setActive( true );
|
||||
account3.setClient( client );
|
||||
client.getDebitAccounts().add( account3 );
|
||||
session.persist( account3 );
|
||||
} );
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWhere(SessionFactoryScope scope) {
|
||||
scope.inTransaction( session -> {
|
||||
final CriteriaBuilder criteriaBuilder = scope.getSessionFactory().getCriteriaBuilder();
|
||||
final CriteriaQuery<Client> criteriaQuery = createCriteriaQuery( criteriaBuilder, Client.class, "id", 1L );
|
||||
final Client client = session.createQuery( criteriaQuery ).uniqueResult();
|
||||
|
||||
assertThat( client.getCreditAccounts().size(), is( 1 ) );
|
||||
assertThat( client.getDebitAccounts().size(), is( 1 ) );
|
||||
} );
|
||||
}
|
||||
|
||||
public enum AccountType {
|
||||
DEBIT,
|
||||
CREDIT
|
||||
}
|
||||
|
||||
@Entity(name = "Client")
|
||||
public static class Client {
|
||||
|
||||
@Id
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
@Where( clause = "account_type = 'DEBIT'")
|
||||
@OneToMany(mappedBy = "client")
|
||||
private List<Account> debitAccounts = new ArrayList<>();
|
||||
|
||||
@Where( clause = "account_type = 'CREDIT'")
|
||||
@OneToMany(mappedBy = "client")
|
||||
private List<Account> creditAccounts = new ArrayList<>();
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public List<Account> getDebitAccounts() {
|
||||
return debitAccounts;
|
||||
}
|
||||
|
||||
public List<Account> getCreditAccounts() {
|
||||
return creditAccounts;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Entity(name = "Account")
|
||||
@Where( clause = "active = true" )
|
||||
public static class Account {
|
||||
|
||||
@Id
|
||||
private Long id;
|
||||
|
||||
@ManyToOne
|
||||
private Client client;
|
||||
|
||||
@Column(name = "account_type")
|
||||
@Enumerated(EnumType.STRING)
|
||||
private AccountType type;
|
||||
|
||||
private Double amount;
|
||||
|
||||
private Double rate;
|
||||
|
||||
private boolean active;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Client getClient() {
|
||||
return client;
|
||||
}
|
||||
|
||||
public void setClient(Client client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
public AccountType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(AccountType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public Double getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
public void setAmount(Double amount) {
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
public Double getRate() {
|
||||
return rate;
|
||||
}
|
||||
|
||||
public void setRate(Double rate) {
|
||||
this.rate = rate;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
public void setActive(boolean active) {
|
||||
this.active = active;
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> CriteriaQuery<T> createCriteriaQuery(CriteriaBuilder criteriaBuilder, Class<T> entityClass, String idFieldName, Object idValue) {
|
||||
final CriteriaQuery<T> criteria = criteriaBuilder.createQuery( entityClass );
|
||||
Root<T> root = criteria.from( entityClass );
|
||||
criteria.select( root );
|
||||
criteria.where( criteriaBuilder.equal( root.get( idFieldName ), criteriaBuilder.literal( idValue ) ) );
|
||||
return criteria;
|
||||
}
|
||||
}
|
|
@ -100,7 +100,7 @@ public class FilterBasicsTests implements SessionFactoryScopeAware {
|
|||
|
||||
@ParameterizedTest
|
||||
@ValueSource( strings = { "true", "false" } )
|
||||
void testLoadFilterOnEntity(boolean enableFilter) {
|
||||
void testFilterOnEntity(boolean enableFilter) {
|
||||
scope.inTransaction( session -> {
|
||||
if ( enableFilter ) {
|
||||
session.enableFilter( "activeAccount" ).setParameter( "active", true );
|
||||
|
@ -117,7 +117,7 @@ public class FilterBasicsTests implements SessionFactoryScopeAware {
|
|||
|
||||
@ParameterizedTest
|
||||
@ValueSource( strings = { "true", "false" } )
|
||||
void testLoadFilterOnCollectionField(boolean enableFilter) {
|
||||
void testFilterOnCollectionField(boolean enableFilter) {
|
||||
scope.inTransaction( session -> {
|
||||
if ( enableFilter ) {
|
||||
session.enableFilter( "activeAccount" ).setParameter( "active", true );
|
||||
|
|
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
* 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.query.hql.filter;
|
||||
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.JoinTable;
|
||||
import javax.persistence.ManyToMany;
|
||||
|
||||
import org.hibernate.annotations.WhereJoinTable;
|
||||
|
||||
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.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* @author Nathan Xu
|
||||
*/
|
||||
@DomainModel(
|
||||
annotatedClasses = {
|
||||
WhereJoinTableTests.Book.class,
|
||||
WhereJoinTableTests.Reader.class
|
||||
}
|
||||
)
|
||||
@SessionFactory
|
||||
public class WhereJoinTableTests {
|
||||
|
||||
@BeforeEach
|
||||
void setUp(SessionFactoryScope scope) {
|
||||
scope.inTransaction( session -> {
|
||||
session.doWork( connection -> {
|
||||
try ( Statement statement = connection.createStatement() ) {
|
||||
statement.executeUpdate(
|
||||
"ALTER TABLE Book_Reader ADD created_on TIMESTAMP DEFAULT CURRENT_TIMESTAMP"
|
||||
);
|
||||
}
|
||||
} );
|
||||
|
||||
final Book book = new Book();
|
||||
book.setId( 1L );
|
||||
book.setTitle( "High-Performance Java Persistence" );
|
||||
book.setAuthor( "Vad Mihalcea" );
|
||||
session.persist( book );
|
||||
|
||||
final Reader reader1 = new Reader();
|
||||
reader1.setId( 1L );
|
||||
reader1.setName( "John Doe" );
|
||||
session.persist( reader1 );
|
||||
|
||||
final Reader reader2 = new Reader();
|
||||
reader2.setId( 2L );
|
||||
reader2.setName( "John Doe Jr." );
|
||||
session.persist( reader2 );
|
||||
} );
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWhereJoinTable(SessionFactoryScope scope) {
|
||||
scope.inTransaction( session -> {
|
||||
session.doWork( connection -> {
|
||||
try ( Statement statement = connection.createStatement() ) {
|
||||
statement.executeUpdate(
|
||||
"INSERT INTO Book_Reader " +
|
||||
" (book_id, reader_id) " +
|
||||
"VALUES " +
|
||||
" (1, 1) "
|
||||
);
|
||||
statement.executeUpdate(
|
||||
"INSERT INTO Book_Reader " +
|
||||
" (book_id, reader_id, created_on) " +
|
||||
"VALUES " +
|
||||
" (1, 2, DATEADD( 'DAY', -10, CURRENT_TIMESTAMP() )) "
|
||||
);
|
||||
}}
|
||||
);
|
||||
|
||||
final Book book = session.createQuery( "select b from Book b where b.id = :id", Book.class)
|
||||
.setParameter( "id", 1L ).uniqueResult();
|
||||
assertThat( book.getCurrentWeekReaders().size(), is( 1 ) );
|
||||
} );
|
||||
}
|
||||
|
||||
@Entity(name = "Book")
|
||||
public static class Book {
|
||||
|
||||
@Id
|
||||
private Long id;
|
||||
|
||||
private String title;
|
||||
|
||||
private String author;
|
||||
|
||||
@ManyToMany
|
||||
@JoinTable(
|
||||
name = "Book_Reader",
|
||||
joinColumns = @JoinColumn(name = "book_id"),
|
||||
inverseJoinColumns = @JoinColumn(name = "reader_id")
|
||||
)
|
||||
@WhereJoinTable( clause = "created_on > DATEADD( 'DAY', -7, CURRENT_TIMESTAMP() )")
|
||||
private List<Reader> currentWeekReaders = new ArrayList<>();
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
public void setAuthor(String author) {
|
||||
this.author = author;
|
||||
}
|
||||
|
||||
public List<Reader> getCurrentWeekReaders() {
|
||||
return currentWeekReaders;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Entity(name = "Reader")
|
||||
public static class Reader {
|
||||
|
||||
@Id
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,209 @@
|
|||
/*
|
||||
* 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.query.hql.filter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToMany;
|
||||
|
||||
import org.hibernate.annotations.Where;
|
||||
|
||||
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.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* @author Nathan Xu
|
||||
*/
|
||||
@DomainModel(
|
||||
annotatedClasses = {
|
||||
WhereTests.Client.class,
|
||||
WhereTests.Account.class
|
||||
}
|
||||
)
|
||||
@SessionFactory
|
||||
public class WhereTests {
|
||||
|
||||
@BeforeEach
|
||||
void setUp(SessionFactoryScope scope) {
|
||||
scope.inTransaction( session -> {
|
||||
|
||||
Client client = new Client();
|
||||
client.setId( 1L );
|
||||
client.setName( "John Doe" );
|
||||
session.persist( client );
|
||||
|
||||
Account account1 = new Account( );
|
||||
account1.setId( 1L );
|
||||
account1.setType( AccountType.CREDIT );
|
||||
account1.setAmount( 5000d );
|
||||
account1.setRate( 1.25 / 100 );
|
||||
account1.setActive( true );
|
||||
account1.setClient( client );
|
||||
client.getCreditAccounts().add( account1 );
|
||||
session.persist( account1 );
|
||||
|
||||
Account account2 = new Account( );
|
||||
account2.setId( 2L );
|
||||
account2.setType( AccountType.DEBIT );
|
||||
account2.setAmount( 0d );
|
||||
account2.setRate( 1.05 / 100 );
|
||||
account2.setActive( false );
|
||||
account2.setClient( client );
|
||||
client.getDebitAccounts().add( account2 );
|
||||
session.persist( account2 );
|
||||
|
||||
Account account3 = new Account( );
|
||||
account3.setType( AccountType.DEBIT );
|
||||
account3.setId( 3L );
|
||||
account3.setAmount( 250d );
|
||||
account3.setRate( 1.05 / 100 );
|
||||
account3.setActive( true );
|
||||
account3.setClient( client );
|
||||
client.getDebitAccounts().add( account3 );
|
||||
session.persist( account3 );
|
||||
} );
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWhere(SessionFactoryScope scope) {
|
||||
scope.inTransaction( session -> {
|
||||
final String hqlString = "select c from Client c where c.id = :id";
|
||||
final Client client = session.createQuery( hqlString, Client.class ).setParameter( "id", 1L ).uniqueResult();
|
||||
|
||||
assertThat( client.getCreditAccounts().size(), is( 1 ) );
|
||||
assertThat( client.getDebitAccounts().size(), is( 1 ) );
|
||||
} );
|
||||
}
|
||||
|
||||
public enum AccountType {
|
||||
DEBIT,
|
||||
CREDIT
|
||||
}
|
||||
|
||||
@Entity(name = "Client")
|
||||
public static class Client {
|
||||
|
||||
@Id
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
@Where( clause = "account_type = 'DEBIT'")
|
||||
@OneToMany(mappedBy = "client")
|
||||
private List<Account> debitAccounts = new ArrayList<>();
|
||||
|
||||
@Where( clause = "account_type = 'CREDIT'")
|
||||
@OneToMany(mappedBy = "client")
|
||||
private List<Account> creditAccounts = new ArrayList<>();
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public List<Account> getDebitAccounts() {
|
||||
return debitAccounts;
|
||||
}
|
||||
|
||||
public List<Account> getCreditAccounts() {
|
||||
return creditAccounts;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Entity(name = "Account")
|
||||
@Where( clause = "active = true" )
|
||||
public static class Account {
|
||||
|
||||
@Id
|
||||
private Long id;
|
||||
|
||||
@ManyToOne
|
||||
private Client client;
|
||||
|
||||
@Column(name = "account_type")
|
||||
@Enumerated(EnumType.STRING)
|
||||
private AccountType type;
|
||||
|
||||
private Double amount;
|
||||
|
||||
private Double rate;
|
||||
|
||||
private boolean active;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Client getClient() {
|
||||
return client;
|
||||
}
|
||||
|
||||
public void setClient(Client client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
public AccountType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(AccountType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public Double getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
public void setAmount(Double amount) {
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
public Double getRate() {
|
||||
return rate;
|
||||
}
|
||||
|
||||
public void setRate(Double rate) {
|
||||
this.rate = rate;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
public void setActive(boolean active) {
|
||||
this.active = active;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,6 +16,7 @@ import java.util.Map;
|
|||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.EntityMode;
|
||||
import org.hibernate.Filter;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.LockOptions;
|
||||
|
@ -806,7 +807,7 @@ public class GoofyPersisterClassProvider implements PersisterClassResolver {
|
|||
return false; //To change body of implemented methods use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
public String getManyToManyFilterFragment(String alias, Map enabledFilters) {
|
||||
public String getManyToManyFilterFragment(String alias, Map<String, Filter> enabledFilters) {
|
||||
return null; //To change body of implemented methods use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue