mirror of
https://github.com/hibernate/hibernate-orm
synced 2025-02-16 16:15:06 +00:00
HHH-15483 allow @TenantId properties of type UUID, Long, Integer, etc
implementation is a bit nasty but it works
This commit is contained in:
parent
6cf9d2d480
commit
601e82620d
@ -77,4 +77,14 @@ public String getDefaultFilterCondition() {
|
||||
return defaultFilterCondition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called before binding a JDBC parameter
|
||||
*
|
||||
* @param value the argument to the parameter, as set via {@link org.hibernate.Filter#setParameter(String, Object)}
|
||||
* @return the argument that will actually be bound to the parameter
|
||||
*/
|
||||
public Object processArgument(Object value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
import org.hibernate.Filter;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.engine.spi.FilterDefinition;
|
||||
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
@ -167,9 +168,8 @@ private FilterPredicate generateFilterPredicate(FilterAliasGenerator aliasGenera
|
||||
if ( CollectionHelper.isNotEmpty( filterParameterNames ) ) {
|
||||
for ( int paramPos = 0; paramPos < filterParameterNames.size(); paramPos++ ) {
|
||||
final String parameterName = filterParameterNames.get( paramPos );
|
||||
final JdbcMapping jdbcMapping = enabledFilter
|
||||
.getFilterDefinition()
|
||||
.getParameterJdbcMapping( parameterName );
|
||||
final FilterDefinition filterDefinition = enabledFilter.getFilterDefinition();
|
||||
final JdbcMapping jdbcMapping = filterDefinition.getParameterJdbcMapping( parameterName );
|
||||
final Object parameterValue = enabledFilter.getParameter( parameterName );
|
||||
if ( parameterValue == null ) {
|
||||
throw new MappingException( String.format( "unknown parameter [%s] for filter [%s]", parameterName, filterName ) );
|
||||
@ -180,8 +180,8 @@ private FilterPredicate generateFilterPredicate(FilterAliasGenerator aliasGenera
|
||||
&& !jdbcMapping.getJavaTypeDescriptor().isInstance( parameterValue ) ) {
|
||||
final Iterator<?> iterator = ( (Iterable<?>) parameterValue ).iterator();
|
||||
if ( iterator.hasNext() ) {
|
||||
final Object value = iterator.next();
|
||||
final FilterJdbcParameter jdbcParameter = new FilterJdbcParameter( jdbcMapping, value );
|
||||
final Object element = iterator.next();
|
||||
final FilterJdbcParameter jdbcParameter = new FilterJdbcParameter( jdbcMapping, element );
|
||||
filterPredicate.applyParameter( jdbcParameter );
|
||||
|
||||
while ( iterator.hasNext() ) {
|
||||
@ -195,7 +195,8 @@ private FilterPredicate generateFilterPredicate(FilterAliasGenerator aliasGenera
|
||||
}
|
||||
}
|
||||
else {
|
||||
filterPredicate.applyParameter( new FilterJdbcParameter( jdbcMapping, parameterValue ) );
|
||||
final Object argument = filterDefinition.processArgument( parameterValue );
|
||||
filterPredicate.applyParameter( new FilterJdbcParameter( jdbcMapping, argument) );
|
||||
}
|
||||
|
||||
final String marker = ":" + filterNames[ i ] + "." + parameterName;
|
||||
|
@ -73,15 +73,17 @@ public Map<String,?> getParameters() {
|
||||
* of the passed value did not match the configured type.
|
||||
*/
|
||||
public Filter setParameter(String name, Object value) throws IllegalArgumentException {
|
||||
Object argument = definition.processArgument(value);
|
||||
|
||||
// Make sure this is a defined parameter and check the incoming value type
|
||||
JdbcMapping type = definition.getParameterJdbcMapping( name );
|
||||
if ( type == null ) {
|
||||
throw new IllegalArgumentException( "Undefined filter parameter [" + name + "]" );
|
||||
}
|
||||
if ( value != null && !type.getJavaTypeDescriptor().isInstance( value ) ) {
|
||||
if ( argument != null && !type.getJavaTypeDescriptor().isInstance( argument ) ) {
|
||||
throw new IllegalArgumentException( "Incorrect type for parameter [" + name + "]" );
|
||||
}
|
||||
parameters.put( name, value );
|
||||
parameters.put( name, argument );
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,6 @@
|
||||
import org.hibernate.boot.spi.InFlightMetadataCollector;
|
||||
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||
import org.hibernate.engine.spi.FilterDefinition;
|
||||
import org.hibernate.mapping.BasicValue;
|
||||
import org.hibernate.mapping.Column;
|
||||
import org.hibernate.mapping.Formula;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
@ -55,7 +54,23 @@ public void bind(
|
||||
FILTER_NAME,
|
||||
"",
|
||||
singletonMap( PARAMETER_NAME, tenantIdType )
|
||||
)
|
||||
) {
|
||||
// unfortunately the old APIs only accept String for a tenantId, so parse it
|
||||
@Override
|
||||
public Object processArgument(Object value) {
|
||||
if (value==null) {
|
||||
return null;
|
||||
}
|
||||
else if (value instanceof String) {
|
||||
return getParameterJdbcMapping( PARAMETER_NAME )
|
||||
.getJavaTypeDescriptor()
|
||||
.fromString((String) value);
|
||||
}
|
||||
else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
else {
|
||||
|
@ -6,11 +6,13 @@
|
||||
*/
|
||||
package org.hibernate.tuple;
|
||||
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.PropertyValueException;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.annotations.TenantId;
|
||||
import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
|
||||
/**
|
||||
* Value generation implementation for {@link TenantId}.
|
||||
@ -21,11 +23,13 @@ public class TenantIdGeneration implements AnnotationValueGeneration<TenantId>,
|
||||
|
||||
private String entityName;
|
||||
private String propertyName;
|
||||
private Class<?> propertyType;
|
||||
|
||||
@Override
|
||||
public void initialize(TenantId annotation, Class<?> propertyType, String entityName, String propertyName) {
|
||||
this.entityName = entityName;
|
||||
this.propertyName = propertyName;
|
||||
this.propertyType = propertyType;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -45,24 +49,30 @@ public ValueGenerator<?> getValueGenerator() {
|
||||
|
||||
@Override
|
||||
public Object generateValue(Session session, Object owner, Object currentValue) {
|
||||
String identifier = session.getTenantIdentifier();
|
||||
SessionFactoryImplementor sessionFactory = (SessionFactoryImplementor) session.getSessionFactory();
|
||||
JavaType<Object> descriptor = sessionFactory.getTypeConfiguration().getJavaTypeRegistry()
|
||||
.findDescriptor(propertyType);
|
||||
if ( descriptor==null ) {
|
||||
throw new MappingException( "unsupported tenant id property type: " + propertyType.getName() );
|
||||
}
|
||||
|
||||
String tenantId = session.getTenantIdentifier(); //unfortunately this is always a string in old APIs
|
||||
if ( currentValue != null ) {
|
||||
CurrentTenantIdentifierResolver resolver =
|
||||
((SessionFactoryImplementor) session.getSessionFactory())
|
||||
.getCurrentTenantIdentifierResolver();
|
||||
if ( resolver!=null && resolver.isRoot( session.getTenantIdentifier() ) ) {
|
||||
CurrentTenantIdentifierResolver resolver = sessionFactory.getCurrentTenantIdentifierResolver();
|
||||
if ( resolver!=null && resolver.isRoot(tenantId) ) {
|
||||
// the "root" tenant is allowed to set the tenant id explicitly
|
||||
return currentValue;
|
||||
}
|
||||
if ( !currentValue.equals(identifier) ) {
|
||||
String currentTenantId = descriptor.toString(currentValue);
|
||||
if ( !currentTenantId.equals(tenantId) ) {
|
||||
throw new PropertyValueException(
|
||||
"assigned tenant id differs from current tenant id: "
|
||||
+ currentValue + "!=" + identifier,
|
||||
+ currentTenantId + "!=" + tenantId,
|
||||
entityName, propertyName
|
||||
);
|
||||
}
|
||||
}
|
||||
return identifier;
|
||||
return tenantId == null ? null : descriptor.fromString(tenantId); //convert to the model type
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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.tenantlongid;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import org.hibernate.annotations.TenantId;
|
||||
|
||||
@Entity
|
||||
public class Account {
|
||||
|
||||
@Id @GeneratedValue Long id;
|
||||
|
||||
@TenantId Long tenantId;
|
||||
|
||||
@ManyToOne(optional = false)
|
||||
Client client;
|
||||
|
||||
public Account(Client client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
Account() {}
|
||||
}
|
||||
|
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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.tenantlongid;
|
||||
|
||||
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;
|
||||
|
||||
@Entity
|
||||
public class Client {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
Long id;
|
||||
|
||||
String name;
|
||||
|
||||
@TenantId
|
||||
Long tenantId;
|
||||
|
||||
@OneToMany(mappedBy = "client")
|
||||
Set<Account> accounts = new HashSet<>();
|
||||
|
||||
public Client(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
Client() {}
|
||||
}
|
@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.orm.test.tenantlongid;
|
||||
|
||||
import org.hibernate.PropertyValueException;
|
||||
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.hibernate.tuple.TenantIdBinder;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hibernate.cfg.AvailableSettings.HBM2DDL_DATABASE_ACTION;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
@SessionFactory
|
||||
@DomainModel(annotatedClasses = { Account.class, Client.class })
|
||||
@ServiceRegistry(
|
||||
settings = {
|
||||
@Setting(name = HBM2DDL_DATABASE_ACTION, value = "create-drop")
|
||||
}
|
||||
)
|
||||
public class TenantLongIdTest implements SessionFactoryProducer {
|
||||
|
||||
private static final Long mine = 1L;
|
||||
private static final Long yours = 2L;
|
||||
|
||||
Long 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() {
|
||||
@Override
|
||||
public String resolveCurrentTenantIdentifier() {
|
||||
return currentTenant.toString();
|
||||
}
|
||||
@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.find(Account.class, acc.id) );
|
||||
assertEquals( 1, session.createQuery("from Account").getResultList().size() );
|
||||
} );
|
||||
assertEquals(mine, acc.tenantId);
|
||||
|
||||
currentTenant = yours;
|
||||
scope.inTransaction( session -> {
|
||||
assertNull( session.find(Account.class, acc.id) );
|
||||
assertEquals( 0, session.createQuery("from Account").getResultList().size() );
|
||||
session.disableFilter(TenantIdBinder.FILTER_NAME);
|
||||
assertNotNull( session.find(Account.class, acc.id) );
|
||||
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;
|
||||
try {
|
||||
scope.inTransaction( session -> {
|
||||
session.persist(client);
|
||||
session.persist(acc);
|
||||
} );
|
||||
fail("should have thrown");
|
||||
}
|
||||
catch (Throwable e) {
|
||||
assertTrue( e.getCause() instanceof PropertyValueException );
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testErrorOnUpdate(SessionFactoryScope scope) {
|
||||
currentTenant = mine;
|
||||
Client client = new Client("Gavin");
|
||||
Account acc = new Account(client);
|
||||
scope.inTransaction( session -> {
|
||||
session.persist(client);
|
||||
session.persist(acc);
|
||||
acc.tenantId = yours;
|
||||
client.tenantId = yours;
|
||||
client.name = "Steve";
|
||||
} );
|
||||
//TODO: it would be better if this were an error
|
||||
scope.inTransaction( session -> {
|
||||
Account account = session.find(Account.class, acc.id);
|
||||
assertNotNull(account);
|
||||
assertEquals( mine, acc.tenantId );
|
||||
assertEquals( "Steve", acc.client.name );
|
||||
assertEquals( mine, acc.client.tenantId );
|
||||
} );
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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.tenantuuid;
|
||||
|
||||
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;
|
||||
|
||||
@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.tenantuuid;
|
||||
|
||||
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;
|
||||
|
||||
@TenantId
|
||||
UUID tenantId;
|
||||
|
||||
@OneToMany(mappedBy = "client")
|
||||
Set<Account> accounts = new HashSet<>();
|
||||
|
||||
public Client(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
Client() {}
|
||||
}
|
@ -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.tenantuuid;
|
||||
|
||||
import org.hibernate.PropertyValueException;
|
||||
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.hibernate.tuple.TenantIdBinder;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.hibernate.cfg.AvailableSettings.HBM2DDL_DATABASE_ACTION;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
@SessionFactory
|
||||
@DomainModel(annotatedClasses = { Account.class, Client.class })
|
||||
@ServiceRegistry(
|
||||
settings = {
|
||||
@Setting(name = HBM2DDL_DATABASE_ACTION, value = "create-drop")
|
||||
}
|
||||
)
|
||||
public class TenantUuidTest 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() {
|
||||
@Override
|
||||
public String resolveCurrentTenantIdentifier() {
|
||||
return currentTenant.toString();
|
||||
}
|
||||
@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.find(Account.class, acc.id) );
|
||||
assertEquals( 1, session.createQuery("from Account").getResultList().size() );
|
||||
} );
|
||||
assertEquals(mine, acc.tenantId);
|
||||
|
||||
currentTenant = yours;
|
||||
scope.inTransaction( session -> {
|
||||
assertNull( session.find(Account.class, acc.id) );
|
||||
assertEquals( 0, session.createQuery("from Account").getResultList().size() );
|
||||
session.disableFilter(TenantIdBinder.FILTER_NAME);
|
||||
assertNotNull( session.find(Account.class, acc.id) );
|
||||
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;
|
||||
try {
|
||||
scope.inTransaction( session -> {
|
||||
session.persist(client);
|
||||
session.persist(acc);
|
||||
} );
|
||||
fail("should have thrown");
|
||||
}
|
||||
catch (Throwable e) {
|
||||
assertTrue( e.getCause() instanceof PropertyValueException );
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testErrorOnUpdate(SessionFactoryScope scope) {
|
||||
currentTenant = mine;
|
||||
Client client = new Client("Gavin");
|
||||
Account acc = new Account(client);
|
||||
scope.inTransaction( session -> {
|
||||
session.persist(client);
|
||||
session.persist(acc);
|
||||
acc.tenantId = yours;
|
||||
client.tenantId = yours;
|
||||
client.name = "Steve";
|
||||
} );
|
||||
//TODO: it would be better if this were an error
|
||||
scope.inTransaction( session -> {
|
||||
Account account = session.find(Account.class, acc.id);
|
||||
assertNotNull(account);
|
||||
assertEquals( mine, acc.tenantId );
|
||||
assertEquals( "Steve", acc.client.name );
|
||||
assertEquals( mine, acc.client.tenantId );
|
||||
} );
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user