use of org.hibernate.engine.spi.SessionImplementor in project hibernate-orm by hibernate.
the class SimpleAuditExpression method addToQuery.
@Override
protected void addToQuery(EnversService enversService, AuditReaderImplementor versionsReader, String entityName, String alias, QueryBuilder qb, Parameters parameters) {
String propertyName = CriteriaTools.determinePropertyName(enversService, versionsReader, entityName, propertyNameGetter);
RelationDescription relatedEntity = CriteriaTools.getRelatedEntity(enversService, entityName, propertyName);
if (relatedEntity == null) {
// HHH-9178 - Add support to component type equality.
// This basically will allow = and <> operators to perform component-based equality checks.
// Any other operator for a component type will not be supported.
// Non-component types will continue to behave normally.
final SessionImplementor session = versionsReader.getSessionImplementor();
final Type type = getPropertyType(session, entityName, propertyName);
if (type != null && type.isComponentType()) {
if (!"=".equals(op) && !"<>".equals(op)) {
throw new AuditException("Component-based criterion is not supported for op: " + op);
}
final ComponentType componentType = (ComponentType) type;
for (int i = 0; i < componentType.getPropertyNames().length; i++) {
final Object componentValue = componentType.getPropertyValue(value, i, session);
parameters.addWhereWithParam(alias, propertyName + "_" + componentType.getPropertyNames()[i], op, componentValue);
}
} else {
parameters.addWhereWithParam(alias, propertyName, op, value);
}
} else {
if (!"=".equals(op) && !"<>".equals(op)) {
throw new AuditException("This type of operation: " + op + " (" + entityName + "." + propertyName + ") isn't supported and can't be used in queries.");
}
Object id = relatedEntity.getIdMapper().mapToIdFromEntity(value);
relatedEntity.getIdMapper().addIdEqualsToQuery(parameters, id, alias, null, "=".equals(op));
}
}
use of org.hibernate.engine.spi.SessionImplementor in project hibernate-orm by hibernate.
the class AuditReaderFactory method get.
/**
* Create an audit reader associated with an open session.
*
* @param session An open session.
*
* @return An audit reader associated with the given sesison. It shouldn't be used
* afterQuery the session is closed.
*
* @throws AuditException When the given required listeners aren't installed.
*/
public static AuditReader get(Session session) throws AuditException {
SessionImplementor sessionImpl;
if (!(session instanceof SessionImplementor)) {
sessionImpl = (SessionImplementor) session.getSessionFactory().getCurrentSession();
} else {
sessionImpl = (SessionImplementor) session;
}
final ServiceRegistry serviceRegistry = sessionImpl.getFactory().getServiceRegistry();
final EnversService enversService = serviceRegistry.getService(EnversService.class);
return new AuditReaderImpl(enversService, session, sessionImpl);
}
use of org.hibernate.engine.spi.SessionImplementor in project spring-framework by spring-projects.
the class HibernateTransactionManager method doBegin.
@Override
@SuppressWarnings("deprecation")
protected void doBegin(Object transaction, TransactionDefinition definition) {
HibernateTransactionObject txObject = (HibernateTransactionObject) transaction;
if (txObject.hasConnectionHolder() && !txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
throw new IllegalTransactionStateException("Pre-bound JDBC Connection found! HibernateTransactionManager does not support " + "running within DataSourceTransactionManager if told to manage the DataSource itself. " + "It is recommended to use a single HibernateTransactionManager for all transactions " + "on a single DataSource, no matter whether Hibernate or JDBC access.");
}
Session session = null;
try {
if (txObject.getSessionHolder() == null || txObject.getSessionHolder().isSynchronizedWithTransaction()) {
Interceptor entityInterceptor = getEntityInterceptor();
Session newSession = (entityInterceptor != null ? getSessionFactory().withOptions().interceptor(entityInterceptor).openSession() : getSessionFactory().openSession());
if (logger.isDebugEnabled()) {
logger.debug("Opened new Session [" + newSession + "] for Hibernate transaction");
}
txObject.setSession(newSession);
}
session = txObject.getSessionHolder().getSession();
if (this.prepareConnection && isSameConnectionForEntireSession(session)) {
// We're allowed to change the transaction settings of the JDBC Connection.
if (logger.isDebugEnabled()) {
logger.debug("Preparing JDBC Connection of Hibernate Session [" + session + "]");
}
Connection con = ((SessionImplementor) session).connection();
Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
txObject.setPreviousIsolationLevel(previousIsolationLevel);
if (this.allowResultAccessAfterCompletion && !txObject.isNewSession()) {
int currentHoldability = con.getHoldability();
if (currentHoldability != ResultSet.HOLD_CURSORS_OVER_COMMIT) {
txObject.setPreviousHoldability(currentHoldability);
con.setHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT);
}
}
} else {
// Not allowed to change the transaction settings of the JDBC Connection.
if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) {
// We should set a specific isolation level but are not allowed to...
throw new InvalidIsolationLevelException("HibernateTransactionManager is not allowed to support custom isolation levels: " + "make sure that its 'prepareConnection' flag is on (the default) and that the " + "Hibernate connection release mode is set to 'on_close' (the default for JDBC).");
}
if (logger.isDebugEnabled()) {
logger.debug("Not preparing JDBC Connection of Hibernate Session [" + session + "]");
}
}
if (definition.isReadOnly() && txObject.isNewSession()) {
// Just set to MANUAL in case of a new Session for this transaction.
session.setFlushMode(FlushMode.MANUAL);
}
if (!definition.isReadOnly() && !txObject.isNewSession()) {
// We need AUTO or COMMIT for a non-read-only transaction.
FlushMode flushMode = SessionFactoryUtils.getFlushMode(session);
if (FlushMode.MANUAL.equals(flushMode)) {
session.setFlushMode(FlushMode.AUTO);
txObject.getSessionHolder().setPreviousFlushMode(flushMode);
}
}
Transaction hibTx;
// Register transaction timeout.
int timeout = determineTimeout(definition);
if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
// Use Hibernate's own transaction timeout mechanism on Hibernate 3.1+
// Applies to all statements, also to inserts, updates and deletes!
hibTx = session.getTransaction();
hibTx.setTimeout(timeout);
hibTx.begin();
} else {
// Open a plain Hibernate transaction without specified timeout.
hibTx = session.beginTransaction();
}
// Add the Hibernate transaction to the session holder.
txObject.getSessionHolder().setTransaction(hibTx);
// Register the Hibernate Session's JDBC Connection for the DataSource, if set.
if (getDataSource() != null) {
Connection con = ((SessionImplementor) session).connection();
ConnectionHolder conHolder = new ConnectionHolder(con);
if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
conHolder.setTimeoutInSeconds(timeout);
}
if (logger.isDebugEnabled()) {
logger.debug("Exposing Hibernate transaction as JDBC transaction [" + con + "]");
}
TransactionSynchronizationManager.bindResource(getDataSource(), conHolder);
txObject.setConnectionHolder(conHolder);
}
// Bind the session holder to the thread.
if (txObject.isNewSessionHolder()) {
TransactionSynchronizationManager.bindResource(getSessionFactory(), txObject.getSessionHolder());
}
txObject.getSessionHolder().setSynchronizedWithTransaction(true);
} catch (Throwable ex) {
if (txObject.isNewSession()) {
try {
if (session.getTransaction().getStatus() == TransactionStatus.ACTIVE) {
session.getTransaction().rollback();
}
} catch (Throwable ex2) {
logger.debug("Could not rollback Session after failed transaction begin", ex);
} finally {
SessionFactoryUtils.closeSession(session);
txObject.setSessionHolder(null);
}
}
throw new CannotCreateTransactionException("Could not open Hibernate Session for transaction", ex);
}
}
use of org.hibernate.engine.spi.SessionImplementor in project hibernate-orm by hibernate.
the class PersistenceContextTest method test.
@Test
public void test() {
doInJPA(this::entityManagerFactory, entityManager -> {
Session session = entityManager.unwrap(Session.class);
SessionImplementor sessionImplementor = entityManager.unwrap(SessionImplementor.class);
SessionFactory sessionFactory = entityManager.getEntityManagerFactory().unwrap(SessionFactory.class);
});
Long _personId = doInJPA(this::entityManagerFactory, entityManager -> {
entityManager.createQuery("delete from Book").executeUpdate();
entityManager.createQuery("delete from Person").executeUpdate();
Person person = new Person();
person.setId(1L);
person.setName("John Doe");
entityManager.persist(person);
entityManager.remove(person);
entityManager.persist(person);
Long personId = person.getId();
Book book = new Book();
book.setAuthor(entityManager.getReference(Person.class, personId));
return personId;
});
doInJPA(this::entityManagerFactory, entityManager -> {
Long personId = _personId;
Person person = entityManager.find(Person.class, personId);
});
doInJPA(this::entityManagerFactory, entityManager -> {
Session session = entityManager.unwrap(Session.class);
entityManager.createQuery("delete from Book").executeUpdate();
entityManager.createQuery("delete from Person").executeUpdate();
Person person = new Person();
person.setId(1L);
person.setName("John Doe");
session.save(person);
session.delete(person);
session.save(person);
Long personId = person.getId();
Book book = new Book();
book.setId(1L);
book.setIsbn("123-456-7890");
entityManager.persist(book);
book.setAuthor(session.load(Person.class, personId));
});
doInJPA(this::entityManagerFactory, entityManager -> {
Session session = entityManager.unwrap(Session.class);
Long personId = _personId;
Person person = session.get(Person.class, personId);
});
doInJPA(this::entityManagerFactory, entityManager -> {
Session session = entityManager.unwrap(Session.class);
Long personId = _personId;
Person person = session.byId(Person.class).load(personId);
Optional<Person> optionalPerson = session.byId(Person.class).loadOptional(personId);
String isbn = "123-456-7890";
Book book = session.bySimpleNaturalId(Book.class).getReference(isbn);
assertNotNull(book);
});
doInJPA(this::entityManagerFactory, entityManager -> {
Session session = entityManager.unwrap(Session.class);
String isbn = "123-456-7890";
Book book = session.byNaturalId(Book.class).using("isbn", isbn).load();
assertNotNull(book);
Optional<Book> optionalBook = session.byNaturalId(Book.class).using("isbn", isbn).loadOptional();
});
doInJPA(this::entityManagerFactory, entityManager -> {
Long personId = _personId;
Person person = entityManager.find(Person.class, personId);
person.setName("John Doe");
entityManager.flush();
});
doInJPA(this::entityManagerFactory, entityManager -> {
Long personId = _personId;
Person person = entityManager.find(Person.class, personId);
entityManager.createQuery("update Person set name = UPPER(name)").executeUpdate();
entityManager.refresh(person);
assertEquals("JOHN DOE", person.getName());
});
try {
doInJPA(this::entityManagerFactory, entityManager -> {
Long personId = _personId;
try {
Person person = entityManager.find(Person.class, personId);
Book book = new Book();
book.setId(100L);
book.setTitle("Hibernate User Guide");
book.setAuthor(person);
person.getBooks().add(book);
entityManager.refresh(person);
} catch (EntityNotFoundException expected) {
log.info("Beware when cascading the refresh associations to transient entities!");
}
});
} catch (Exception expected) {
}
doInJPA(this::entityManagerFactory, entityManager -> {
Session session = entityManager.unwrap(Session.class);
Long personId = _personId;
Person person = session.byId(Person.class).load(personId);
person.setName("John Doe");
entityManager.flush();
});
doInJPA(this::entityManagerFactory, entityManager -> {
Session session = entityManager.unwrap(Session.class);
Long personId = _personId;
Person person = session.byId(Person.class).load(personId);
session.doWork(connection -> {
try (Statement statement = connection.createStatement()) {
statement.executeUpdate("UPDATE Person SET name = UPPER(name)");
}
});
session.refresh(person);
assertEquals("JOHN DOE", person.getName());
});
doInJPA(this::entityManagerFactory, entityManager -> {
Session session = entityManager.unwrap(Session.class);
Long personId = _personId;
Person person = session.byId(Person.class).load(personId);
session.clear();
person.setName("Mr. John Doe");
session.lock(person, LockMode.NONE);
});
doInJPA(this::entityManagerFactory, entityManager -> {
Session session = entityManager.unwrap(Session.class);
Long personId = _personId;
Person person = session.byId(Person.class).load(personId);
session.clear();
person.setName("Mr. John Doe");
session.saveOrUpdate(person);
});
doInJPA(this::entityManagerFactory, entityManager -> {
Session session = entityManager.unwrap(Session.class);
Long personId = _personId;
Person personDetachedReference = session.byId(Person.class).load(personId);
session.clear();
new MergeVisualizer(session).merge(personDetachedReference);
});
doInJPA(this::entityManagerFactory, entityManager -> {
Long personId = _personId;
Person person = entityManager.find(Person.class, personId);
entityManager.clear();
person.setName("Mr. John Doe");
person = entityManager.merge(person);
boolean contained = entityManager.contains(person);
assertTrue(contained);
PersistenceUnitUtil persistenceUnitUtil = entityManager.getEntityManagerFactory().getPersistenceUnitUtil();
boolean personInitialized = persistenceUnitUtil.isLoaded(person);
boolean personBooksInitialized = persistenceUnitUtil.isLoaded(person.getBooks());
boolean personNameInitialized = persistenceUnitUtil.isLoaded(person, "name");
});
doInJPA(this::entityManagerFactory, entityManager -> {
Long personId = _personId;
Person person = entityManager.find(Person.class, personId);
PersistenceUtil persistenceUnitUtil = Persistence.getPersistenceUtil();
boolean personInitialized = persistenceUnitUtil.isLoaded(person);
boolean personBooksInitialized = persistenceUnitUtil.isLoaded(person.getBooks());
boolean personNameInitialized = persistenceUnitUtil.isLoaded(person, "name");
});
doInJPA(this::entityManagerFactory, entityManager -> {
Session session = entityManager.unwrap(Session.class);
Long personId = _personId;
Person person = session.byId(Person.class).load(personId);
session.clear();
person.setName("Mr. John Doe");
person = (Person) session.merge(person);
boolean contained = session.contains(person);
assertTrue(contained);
boolean personInitialized = Hibernate.isInitialized(person);
boolean personBooksInitialized = Hibernate.isInitialized(person.getBooks());
boolean personNameInitialized = Hibernate.isPropertyInitialized(person, "name");
});
}
use of org.hibernate.engine.spi.SessionImplementor in project hibernate-orm by hibernate.
the class DefaultFlushEntityEventListener method dirtyCheck.
/**
* Perform a dirty check, and attach the results to the event
*/
protected void dirtyCheck(final FlushEntityEvent event) throws HibernateException {
final Object entity = event.getEntity();
final Object[] values = event.getPropertyValues();
final SessionImplementor session = event.getSession();
final EntityEntry entry = event.getEntityEntry();
final EntityPersister persister = entry.getPersister();
final Serializable id = entry.getId();
final Object[] loadedState = entry.getLoadedState();
int[] dirtyProperties = session.getInterceptor().findDirty(entity, id, values, loadedState, persister.getPropertyNames(), persister.getPropertyTypes());
if (dirtyProperties == null) {
if (entity instanceof SelfDirtinessTracker) {
if (((SelfDirtinessTracker) entity).$$_hibernate_hasDirtyAttributes()) {
dirtyProperties = persister.resolveAttributeIndexes(((SelfDirtinessTracker) entity).$$_hibernate_getDirtyAttributes());
} else {
dirtyProperties = new int[0];
}
} else {
// see if the custom dirtiness strategy can tell us...
class DirtyCheckContextImpl implements CustomEntityDirtinessStrategy.DirtyCheckContext {
int[] found;
@Override
public void doDirtyChecking(CustomEntityDirtinessStrategy.AttributeChecker attributeChecker) {
found = new DirtyCheckAttributeInfoImpl(event).visitAttributes(attributeChecker);
if (found != null && found.length == 0) {
found = null;
}
}
}
DirtyCheckContextImpl context = new DirtyCheckContextImpl();
session.getFactory().getCustomEntityDirtinessStrategy().findDirty(entity, persister, (Session) session, context);
dirtyProperties = context.found;
}
}
event.setDatabaseSnapshot(null);
final boolean interceptorHandledDirtyCheck;
boolean cannotDirtyCheck;
if (dirtyProperties == null) {
// Interceptor returned null, so do the dirtycheck ourself, if possible
try {
session.getEventListenerManager().dirtyCalculationStart();
interceptorHandledDirtyCheck = false;
// object loaded by update()
cannotDirtyCheck = loadedState == null;
if (!cannotDirtyCheck) {
// dirty check against the usual snapshot of the entity
dirtyProperties = persister.findDirty(values, loadedState, entity, session);
} else if (entry.getStatus() == Status.DELETED && !event.getEntityEntry().isModifiableEntity()) {
// fields should be updated.
if (values != entry.getDeletedState()) {
throw new IllegalStateException("Entity has status Status.DELETED but values != entry.getDeletedState");
}
// Even if loadedState == null, we can dirty-check by comparing currentState and
// entry.getDeletedState() because the only fields to be updated are those that
// refer to transient entities that are being set to null.
// - currentState contains the entity's current property values.
// - entry.getDeletedState() contains the entity's current property values with
// references to transient entities set to null.
// - dirtyProperties will only contain properties that refer to transient entities
final Object[] currentState = persister.getPropertyValues(event.getEntity());
dirtyProperties = persister.findDirty(entry.getDeletedState(), currentState, entity, session);
cannotDirtyCheck = false;
} else {
// dirty check against the database snapshot, if possible/necessary
final Object[] databaseSnapshot = getDatabaseSnapshot(session, persister, id);
if (databaseSnapshot != null) {
dirtyProperties = persister.findModified(databaseSnapshot, values, entity, session);
cannotDirtyCheck = false;
event.setDatabaseSnapshot(databaseSnapshot);
}
}
} finally {
session.getEventListenerManager().dirtyCalculationEnd(dirtyProperties != null);
}
} else {
// the Interceptor handled the dirty checking
cannotDirtyCheck = false;
interceptorHandledDirtyCheck = true;
}
logDirtyProperties(id, dirtyProperties, persister);
event.setDirtyProperties(dirtyProperties);
event.setDirtyCheckHandledByInterceptor(interceptorHandledDirtyCheck);
event.setDirtyCheckPossible(!cannotDirtyCheck);
}
Aggregations