HHH-17117 allow @TenantId to form part of composite key
Signed-off-by: Gavin King <gavin@hibernate.org>
This commit is contained in:
parent
77a34e6312
commit
d90807f9e4
|
@ -26,6 +26,7 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
|||
* @author Gavin King
|
||||
*/
|
||||
@ValueGenerationType(generatedBy = TenantIdGeneration.class)
|
||||
@IdGeneratorType(TenantIdGeneration.class)
|
||||
@AttributeBinderType(binder = TenantIdBinder.class)
|
||||
@Target({METHOD, FIELD})
|
||||
@Retention(RUNTIME)
|
||||
|
|
|
@ -1358,24 +1358,6 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector,
|
|||
}
|
||||
}
|
||||
|
||||
private static AnnotatedClassType getAnnotatedClassType2(ClassDetails classDetails) {
|
||||
if ( classDetails.hasDirectAnnotationUsage( Entity.class ) ) {
|
||||
return AnnotatedClassType.ENTITY;
|
||||
}
|
||||
else if ( classDetails.hasDirectAnnotationUsage( Embeddable.class ) ) {
|
||||
return AnnotatedClassType.EMBEDDABLE;
|
||||
}
|
||||
else if ( classDetails.hasDirectAnnotationUsage( jakarta.persistence.MappedSuperclass.class ) ) {
|
||||
return AnnotatedClassType.MAPPED_SUPERCLASS;
|
||||
}
|
||||
else if ( classDetails.hasDirectAnnotationUsage( Imported.class ) ) {
|
||||
return AnnotatedClassType.IMPORTED;
|
||||
}
|
||||
else {
|
||||
return AnnotatedClassType.NONE;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addMappedSuperclass(Class<?> type, MappedSuperclass mappedSuperclass) {
|
||||
if ( mappedSuperClasses == null ) {
|
||||
|
@ -2022,10 +2004,10 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector,
|
|||
}
|
||||
}
|
||||
}
|
||||
stopProcess = failingSecondPasses.size() == 0 || failingSecondPasses.size() == endOfQueueFkSecondPasses.size();
|
||||
stopProcess = failingSecondPasses.isEmpty() || failingSecondPasses.size() == endOfQueueFkSecondPasses.size();
|
||||
endOfQueueFkSecondPasses = failingSecondPasses;
|
||||
}
|
||||
if ( endOfQueueFkSecondPasses.size() > 0 ) {
|
||||
if ( !endOfQueueFkSecondPasses.isEmpty() ) {
|
||||
throw originalException;
|
||||
}
|
||||
}
|
||||
|
@ -2212,7 +2194,8 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector,
|
|||
handleIdentifierValueBinding(
|
||||
entityBinding.getIdentifier(),
|
||||
dialect,
|
||||
(RootClass) entityBinding
|
||||
(RootClass) entityBinding,
|
||||
entityBinding.getIdentifierProperty()
|
||||
);
|
||||
|
||||
}
|
||||
|
@ -2225,22 +2208,20 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector,
|
|||
handleIdentifierValueBinding(
|
||||
( (IdentifierCollection) collection ).getIdentifier(),
|
||||
dialect,
|
||||
null,
|
||||
null
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleIdentifierValueBinding(
|
||||
KeyValue identifierValueBinding,
|
||||
Dialect dialect,
|
||||
RootClass entityBinding) {
|
||||
KeyValue identifierValueBinding, Dialect dialect, RootClass entityBinding, Property identifierProperty) {
|
||||
// todo : store this result (back into the entity or into the KeyValue, maybe?)
|
||||
// This process of instantiating the id-generator is called multiple times.
|
||||
// It was done this way in the old code too, so no "regression" here; but
|
||||
// it could be done better
|
||||
try {
|
||||
final Generator generator = identifierValueBinding.createGenerator( dialect, entityBinding );
|
||||
|
||||
final Generator generator = identifierValueBinding.createGenerator( dialect, entityBinding, identifierProperty );
|
||||
if ( generator instanceof ExportableProducer ) {
|
||||
( (ExportableProducer) generator ).registerExportables( getDatabase() );
|
||||
}
|
||||
|
|
|
@ -25,7 +25,6 @@ import org.hibernate.engine.spi.SelfDirtinessTracker;
|
|||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.engine.spi.Status;
|
||||
import org.hibernate.event.spi.EventSource;
|
||||
import org.hibernate.id.Assigned;
|
||||
import org.hibernate.id.CompositeNestedGeneratedValueGenerator;
|
||||
import org.hibernate.id.IdentifierGenerationException;
|
||||
import org.hibernate.internal.CoreLogging;
|
||||
|
|
|
@ -51,26 +51,28 @@ public class TenantIdGeneration implements BeforeExecutionGenerator {
|
|||
@Override
|
||||
public Object generate(SharedSessionContractImplementor session, Object owner, Object currentValue, EventType eventType) {
|
||||
final SessionFactoryImplementor sessionFactory = session.getSessionFactory();
|
||||
final JavaType<Object> tenantIdentifierJavaType = sessionFactory.getTenantIdentifierJavaType();
|
||||
|
||||
final Object tenantId = session.getTenantIdentifierValue();
|
||||
if ( currentValue != null ) {
|
||||
final CurrentTenantIdentifierResolver<Object> resolver = sessionFactory.getCurrentTenantIdentifierResolver();
|
||||
final CurrentTenantIdentifierResolver<Object> resolver =
|
||||
sessionFactory.getCurrentTenantIdentifierResolver();
|
||||
if ( resolver != null && resolver.isRoot( tenantId ) ) {
|
||||
// the "root" tenant is allowed to set the tenant id explicitly
|
||||
return currentValue;
|
||||
}
|
||||
if ( !tenantIdentifierJavaType.areEqual( currentValue, tenantId ) ) {
|
||||
else {
|
||||
final JavaType<Object> tenantIdJavaType = sessionFactory.getTenantIdentifierJavaType();
|
||||
if ( !tenantIdJavaType.areEqual( currentValue, tenantId ) ) {
|
||||
throw new PropertyValueException(
|
||||
"assigned tenant id differs from current tenant id: " +
|
||||
tenantIdentifierJavaType.toString( currentValue ) +
|
||||
"!=" +
|
||||
tenantIdentifierJavaType.toString( tenantId ),
|
||||
"assigned tenant id differs from current tenant id ["
|
||||
+ tenantIdJavaType.toString( currentValue )
|
||||
+ " != "
|
||||
+ tenantIdJavaType.toString( tenantId ) + "]",
|
||||
entityName,
|
||||
propertyName
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
return tenantId;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -103,15 +103,16 @@ public class FilterImpl implements Filter, Serializable {
|
|||
* of the passed value did not match the configured type.
|
||||
*/
|
||||
public Filter setParameter(String name, Object value) throws IllegalArgumentException {
|
||||
Object argument = definition.processArgument(value);
|
||||
final Object argument = definition.processArgument( value );
|
||||
|
||||
// Make sure this is a defined parameter and check the incoming value type
|
||||
JdbcMapping type = definition.getParameterJdbcMapping( name );
|
||||
final JdbcMapping type = definition.getParameterJdbcMapping( name );
|
||||
if ( type == null ) {
|
||||
throw new IllegalArgumentException( "Undefined filter parameter [" + name + "]" );
|
||||
throw new IllegalArgumentException( "Undefined filter parameter '" + name + "'" );
|
||||
}
|
||||
if ( argument != null && !type.getJavaTypeDescriptor().isInstance( argument ) ) {
|
||||
throw new IllegalArgumentException( "Incorrect type for parameter [" + name + "]" );
|
||||
throw new IllegalArgumentException( "Argument assigned to filter parameter '" + name
|
||||
+ "' is not of type '" + type.getJavaTypeDescriptor().getTypeName() + "'" );
|
||||
}
|
||||
if ( parameters == null ) {
|
||||
parameters = new TreeMap<>();
|
||||
|
@ -133,14 +134,15 @@ public class FilterImpl implements Filter, Serializable {
|
|||
if ( values == null ) {
|
||||
throw new IllegalArgumentException( "Collection must be not null" );
|
||||
}
|
||||
JdbcMapping type = definition.getParameterJdbcMapping( name );
|
||||
final JdbcMapping type = definition.getParameterJdbcMapping( name );
|
||||
if ( type == null ) {
|
||||
throw new HibernateException( "Undefined filter parameter [" + name + "]" );
|
||||
throw new HibernateException( "Undefined filter parameter '" + name + "'" );
|
||||
}
|
||||
if ( !values.isEmpty() ) {
|
||||
final Object element = values.iterator().next();
|
||||
if ( !type.getJavaTypeDescriptor().isInstance( element ) ) {
|
||||
throw new HibernateException( "Incorrect type for parameter [" + name + "]" );
|
||||
throw new IllegalArgumentException( "Argument assigned to filter parameter '" + name
|
||||
+ "' is not of type '" + type.getJavaTypeDescriptor().getTypeName() + "'" );
|
||||
}
|
||||
}
|
||||
if ( parameters == null ) {
|
||||
|
|
|
@ -457,7 +457,7 @@ public class SessionFactoryImpl extends QueryParameterBindingTypeResolverImpl im
|
|||
for ( PersistentClass model : bootMetamodel.getEntityBindings() ) {
|
||||
if ( !model.isInherited() ) {
|
||||
final KeyValue id = model.getIdentifier();
|
||||
final Generator generator = id.createGenerator( dialect, (RootClass) model );
|
||||
final Generator generator = id.createGenerator( dialect, (RootClass) model, model.getIdentifierProperty() );
|
||||
if ( generator instanceof Configurable ) {
|
||||
final Configurable identifierGenerator = (Configurable) generator;
|
||||
identifierGenerator.initialize( sqlStringGenerationContext );
|
||||
|
|
|
@ -11,7 +11,6 @@ import java.util.ArrayList;
|
|||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
@ -546,10 +545,6 @@ public class Component extends SimpleValue implements MetaAttributable, Sortable
|
|||
this.isKey = isKey;
|
||||
}
|
||||
|
||||
public boolean hasPojoRepresentation() {
|
||||
return componentClassName!=null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link Property} at the specified position in this {@link Component}.
|
||||
*
|
||||
|
@ -661,37 +656,33 @@ public class Component extends SimpleValue implements MetaAttributable, Sortable
|
|||
}
|
||||
|
||||
@Override
|
||||
public Generator createGenerator(Dialect dialect, RootClass rootClass) throws MappingException {
|
||||
public Generator createGenerator(Dialect dialect, RootClass rootClass, Property property) {
|
||||
if ( builtIdentifierGenerator == null ) {
|
||||
builtIdentifierGenerator = buildIdentifierGenerator( dialect, rootClass );
|
||||
builtIdentifierGenerator =
|
||||
getCustomIdGeneratorCreator().isAssigned()
|
||||
? buildIdentifierGenerator( dialect, rootClass )
|
||||
: super.createGenerator( dialect, rootClass, property );
|
||||
}
|
||||
return builtIdentifierGenerator;
|
||||
}
|
||||
|
||||
private Generator buildIdentifierGenerator( Dialect dialect, RootClass rootClass) throws MappingException {
|
||||
if ( !getCustomIdGeneratorCreator().isAssigned() ) {
|
||||
return super.createGenerator( dialect, rootClass );
|
||||
}
|
||||
|
||||
final Class<?> entityClass = rootClass.getMappedClass();
|
||||
final Class<?> attributeDeclarer = getAttributeDeclarer( rootClass, entityClass );
|
||||
|
||||
final CompositeNestedGeneratedValueGenerator.GenerationContextLocator locator =
|
||||
new StandardGenerationContextLocator( rootClass.getEntityName() );
|
||||
private Generator buildIdentifierGenerator(Dialect dialect, RootClass rootClass) {
|
||||
final CompositeNestedGeneratedValueGenerator generator =
|
||||
new CompositeNestedGeneratedValueGenerator( locator, getType() );
|
||||
|
||||
new CompositeNestedGeneratedValueGenerator(
|
||||
new StandardGenerationContextLocator( rootClass.getEntityName() ),
|
||||
getType()
|
||||
);
|
||||
final List<Property> properties = getProperties();
|
||||
for ( int i = 0; i < properties.size(); i++ ) {
|
||||
final Property property = properties.get( i );
|
||||
if ( property.getValue().isSimpleValue() ) {
|
||||
final SimpleValue value = (SimpleValue) property.getValue();
|
||||
if ( !value.getCustomIdGeneratorCreator().isAssigned() ) {
|
||||
// skip any 'assigned' generators, they would have been handled by
|
||||
// the StandardGenerationContextLocator
|
||||
// skip any 'assigned' generators, they would have been
|
||||
// handled by the StandardGenerationContextLocator
|
||||
generator.addGeneratedValuePlan( new ValueGenerationPlan(
|
||||
value.createGenerator( dialect, rootClass ),
|
||||
getType().isMutable() ? injector( property, attributeDeclarer ) : null,
|
||||
value.createGenerator( dialect, rootClass, property ),
|
||||
getType().isMutable() ? injector( property, getAttributeDeclarer( rootClass ) ) : null,
|
||||
i
|
||||
) );
|
||||
}
|
||||
|
@ -700,23 +691,27 @@ public class Component extends SimpleValue implements MetaAttributable, Sortable
|
|||
return generator;
|
||||
}
|
||||
|
||||
private Class<?> getAttributeDeclarer(RootClass rootClass, Class<?> entityClass) {
|
||||
final Class<?> attributeDeclarer; // what class is the declarer of the composite pk attributes
|
||||
// IMPL NOTE : See the javadoc discussion on CompositeNestedGeneratedValueGenerator wrt the
|
||||
// various scenarios for which we need to account here
|
||||
/**
|
||||
* Return the class that declares the composite pk attributes,
|
||||
* which might be an {@code @IdClass}, an {@code @EmbeddedId},
|
||||
* of the entity class itself.
|
||||
*/
|
||||
private Class<?> getAttributeDeclarer(RootClass rootClass) {
|
||||
// See the javadoc discussion on CompositeNestedGeneratedValueGenerator
|
||||
// for the various scenarios we need to account for here
|
||||
if ( rootClass.getIdentifierMapper() != null ) {
|
||||
// we have the @IdClass / <composite-id mapped="true"/> case
|
||||
attributeDeclarer = resolveComponentClass();
|
||||
return resolveComponentClass();
|
||||
}
|
||||
else if ( rootClass.getIdentifierProperty() != null ) {
|
||||
// we have the "@EmbeddedId" / <composite-id name="idName"/> case
|
||||
attributeDeclarer = resolveComponentClass();
|
||||
return resolveComponentClass();
|
||||
}
|
||||
else {
|
||||
// we have the "straight up" embedded (again the Hibernate term) component identifier
|
||||
attributeDeclarer = entityClass;
|
||||
// we have the "straight up" embedded (again the Hibernate term)
|
||||
// component identifier: the entity class itself is the id class
|
||||
return rootClass.getMappedClass();
|
||||
}
|
||||
return attributeDeclarer;
|
||||
}
|
||||
|
||||
private Setter injector(Property property, Class<?> attributeDeclarer) {
|
||||
|
|
|
@ -27,6 +27,11 @@ public interface KeyValue extends Value {
|
|||
|
||||
boolean isUpdateable();
|
||||
|
||||
Generator createGenerator(Dialect dialect, RootClass rootClass);
|
||||
@Deprecated(since = "7.0")
|
||||
default Generator createGenerator(Dialect dialect, RootClass rootClass) {
|
||||
return createGenerator( dialect, rootClass, null );
|
||||
}
|
||||
|
||||
Generator createGenerator(Dialect dialect, RootClass rootClass, Property property);
|
||||
|
||||
}
|
||||
|
|
|
@ -375,10 +375,10 @@ public abstract class SimpleValue implements KeyValue {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Generator createGenerator(Dialect dialect, RootClass rootClass) {
|
||||
public Generator createGenerator(Dialect dialect, RootClass rootClass, Property property) {
|
||||
if ( generator == null ) {
|
||||
if ( customIdGeneratorCreator != null ) {
|
||||
generator = customIdGeneratorCreator.createGenerator( new IdGeneratorCreationContext( rootClass ) );
|
||||
generator = customIdGeneratorCreator.createGenerator( new IdGeneratorCreationContext( rootClass, property ) );
|
||||
}
|
||||
}
|
||||
return generator;
|
||||
|
@ -1011,9 +1011,11 @@ public abstract class SimpleValue implements KeyValue {
|
|||
|
||||
private class IdGeneratorCreationContext implements GeneratorCreationContext {
|
||||
private final RootClass rootClass;
|
||||
private final Property property;
|
||||
|
||||
public IdGeneratorCreationContext(RootClass rootClass) {
|
||||
public IdGeneratorCreationContext(RootClass rootClass, Property property) {
|
||||
this.rootClass = rootClass;
|
||||
this.property = property;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1048,7 +1050,7 @@ public abstract class SimpleValue implements KeyValue {
|
|||
|
||||
@Override
|
||||
public Property getProperty() {
|
||||
return rootClass.getIdentifierProperty();
|
||||
return property;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -598,7 +598,7 @@ public abstract class AbstractCollectionPersister
|
|||
}
|
||||
|
||||
private BeforeExecutionGenerator createGenerator(RuntimeModelCreationContext context, IdentifierCollection collection) {
|
||||
final Generator generator = collection.getIdentifier().createGenerator( context.getDialect(), null );
|
||||
final Generator generator = collection.getIdentifier().createGenerator( context.getDialect(), null, null );
|
||||
if ( generator.generatedOnExecution() ) {
|
||||
throw new MappingException("must be an BeforeExecutionGenerator"); //TODO fix message
|
||||
}
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
package org.hibernate.orm.test.tenantidpk;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import org.hibernate.annotations.TenantId;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@Entity
|
||||
public class Account {
|
||||
|
||||
@Id @GeneratedValue Long id;
|
||||
|
||||
@Id @TenantId UUID tenantId;
|
||||
|
||||
@ManyToOne(optional = false)
|
||||
Client client;
|
||||
|
||||
public Account(Client client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
Account() {}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.orm.test.tenantidpk;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.OneToMany;
|
||||
import org.hibernate.annotations.TenantId;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
@Entity
|
||||
public class Client {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
Long id;
|
||||
|
||||
String name;
|
||||
|
||||
@Id @TenantId
|
||||
UUID tenantId;
|
||||
|
||||
@OneToMany(mappedBy = "client")
|
||||
Set<Account> accounts = new HashSet<>();
|
||||
|
||||
public Client(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
Client() {}
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
|
||||
/*
|
||||
* 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.tenantidpk;
|
||||
|
||||
import org.hibernate.PropertyValueException;
|
||||
import org.hibernate.binder.internal.TenantIdBinder;
|
||||
import org.hibernate.boot.SessionFactoryBuilder;
|
||||
import org.hibernate.boot.spi.MetadataImplementor;
|
||||
import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.ServiceRegistry;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryProducer;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
import org.hibernate.testing.orm.junit.Setting;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.hibernate.cfg.AvailableSettings.JAKARTA_HBM2DDL_DATABASE_ACTION;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
@SessionFactory
|
||||
@DomainModel(annotatedClasses = { Account.class, Client.class })
|
||||
@ServiceRegistry(
|
||||
settings = {
|
||||
@Setting(name = JAKARTA_HBM2DDL_DATABASE_ACTION, value = "create-drop")
|
||||
}
|
||||
)
|
||||
public class TenantPkTest implements SessionFactoryProducer {
|
||||
|
||||
private static final UUID mine = UUID.randomUUID();
|
||||
private static final UUID yours = UUID.randomUUID();
|
||||
|
||||
UUID currentTenant;
|
||||
|
||||
@AfterEach
|
||||
public void cleanup(SessionFactoryScope scope) {
|
||||
scope.inTransaction( session -> {
|
||||
session.createQuery("delete from Account").executeUpdate();
|
||||
session.createQuery("delete from Client").executeUpdate();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public SessionFactoryImplementor produceSessionFactory(MetadataImplementor model) {
|
||||
final SessionFactoryBuilder sessionFactoryBuilder = model.getSessionFactoryBuilder();
|
||||
sessionFactoryBuilder.applyCurrentTenantIdentifierResolver( new CurrentTenantIdentifierResolver<UUID>() {
|
||||
@Override
|
||||
public UUID resolveCurrentTenantIdentifier() {
|
||||
return currentTenant;
|
||||
}
|
||||
@Override
|
||||
public boolean validateExistingCurrentSessions() {
|
||||
return false;
|
||||
}
|
||||
} );
|
||||
return (SessionFactoryImplementor) sessionFactoryBuilder.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test(SessionFactoryScope scope) {
|
||||
currentTenant = mine;
|
||||
Client client = new Client("Gavin");
|
||||
Account acc = new Account(client);
|
||||
scope.inTransaction( session -> {
|
||||
session.persist(client);
|
||||
session.persist(acc);
|
||||
} );
|
||||
scope.inTransaction( session -> {
|
||||
assertNotNull( session.createSelectionQuery("where id=?1", Account.class)
|
||||
.setParameter(1, acc.id)
|
||||
.getSingleResultOrNull() );
|
||||
assertEquals( 1, session.createQuery("from Account").getResultList().size() );
|
||||
} );
|
||||
assertEquals(mine, acc.tenantId);
|
||||
|
||||
currentTenant = yours;
|
||||
scope.inTransaction( session -> {
|
||||
assertNull( session.createSelectionQuery("where id=?1", Account.class)
|
||||
.setParameter(1, acc.id)
|
||||
.getSingleResultOrNull() );
|
||||
assertEquals( 0, session.createQuery("from Account").getResultList().size() );
|
||||
session.disableFilter(TenantIdBinder.FILTER_NAME);
|
||||
assertNotNull( session.createSelectionQuery("where id=?1", Account.class)
|
||||
.setParameter(1, acc.id)
|
||||
.getSingleResultOrNull() );
|
||||
assertEquals( 1, session.createQuery("from Account").getResultList().size() );
|
||||
} );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testErrorOnInsert(SessionFactoryScope scope) {
|
||||
currentTenant = mine;
|
||||
Client client = new Client("Gavin");
|
||||
Account acc = new Account(client);
|
||||
acc.tenantId = yours;
|
||||
scope.inTransaction( session -> {
|
||||
session.persist(client);
|
||||
session.persist(acc);
|
||||
} );
|
||||
assertEquals( mine, acc.tenantId );
|
||||
assertEquals( mine, client.tenantId );
|
||||
}
|
||||
}
|
|
@ -9,7 +9,6 @@ package org.hibernate.processor.util.xml;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import javax.tools.FileObject;
|
||||
|
|
Loading…
Reference in New Issue