Моя проблема в том, что приложение работает нормально, когда я запускаю его в обычном режиме.
Однако в тестах приложение терпит неудачу, поскольку сеанс базы данных все еще имеет арендатор по умолчанию.
Я тестирую базу данных H2 в памяти.
Соответствующие классы:
Код: Выделить всё
// holds the tenant id
public class TenantContext {
private TenantContext() {}
private static final ThreadLocal CURRENT_TENANT = new ThreadLocal();
public static Integer getCurrentTenant() {
return CURRENT_TENANT.get();
}
public static void setCurrentTenant(Integer tenant) {
CURRENT_TENANT.set(tenant);
}
public static void reset() {
CURRENT_TENANT.remove();
}
}
Код: Выделить всё
// provides the tenant id to hibernate
@Component
public class TenantResolver implements CurrentTenantIdentifierResolver, HibernatePropertiesCustomizer {
@Override
public Integer resolveCurrentTenantIdentifier() {
Integer tenant = TenantContext.getCurrentTenant();
if(tenant == null) return -1;
return tenant;
}
@Override
public boolean validateExistingCurrentSessions() {
return false;
}
@Override
public void customize(Map hibernateProperties) {
hibernateProperties.put(MultiTenancySettings.MULTI_TENANT_IDENTIFIER_RESOLVER, this);
}
}
Код: Выделить всё
// Entity class
@Entity
@Getter
@Setter
@Builder(toBuilder = true)
@AllArgsConstructor
@NoArgsConstructor
@Table(schema = "MySchema", name = "MyTable")
public class MyEntity{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
@TenantId
@Column(name = "tenant")
private Integer tenant;
}
Код: Выделить всё
public interface MyEntityRepository extends CrudRepository {}
Тестовый класс выглядит следующим образом:
Код: Выделить всё
@SpringBootTest
@Transactional
@AutoConfigureMockMvc
@ActiveProfiles(profiles = "h2")
class MyEntityRepositoryTest{
@Autowired
MyEntityRepository myEntityRepository;
@Test
void createEntityWithTenant() {
TenantContext.setCurrentTenant(123);
MyEntity myEntity = new MyEntity();
MyEntity storedEntity = myEntityRepository.save(myEntity);
assertEquals(123, storedEntity.getTenant());
}
}
Это связано с тем, что SessionImpl, выполняющий транзакцию, все еще имеет старый идентификатор арендатора с момента инициализации.
Код: Выделить всё
// this is from debugging inside InsertCoordinator#preInsertInMemoryValueGeneration
// https://docs.jboss.org/hibernate/stable/core/javadocs/org/hibernate/persister/entity/mutation/InsertCoordinator.html#preInsertInMemoryValueGeneration(java.lang.Object%5B%5D,java.lang.Object,org.hibernate.engine.spi.SharedSessionContractImplementor)
session.getTenantIdentifierValue(); // returns -1
session.getSessionFactory()
.getCurrentTenantIdentifierResolver()
.resolveCurrentTenantIdentifier() // returns 123
session.getSessionFactory()
.openSession()
.getTenantIdentifierValue() // returns 123
Подробнее здесь: https://stackoverflow.com/questions/785 ... -has-old-t