Search in sources :

Example 6 with SessionImplementor

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));
    }
}
Also used : ComponentType(org.hibernate.type.ComponentType) Type(org.hibernate.type.Type) ComponentType(org.hibernate.type.ComponentType) RelationDescription(org.hibernate.envers.internal.entities.RelationDescription) SessionImplementor(org.hibernate.engine.spi.SessionImplementor) AuditException(org.hibernate.envers.exception.AuditException)

Example 7 with SessionImplementor

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);
}
Also used : AuditReaderImpl(org.hibernate.envers.internal.reader.AuditReaderImpl) SessionImplementor(org.hibernate.engine.spi.SessionImplementor) EnversService(org.hibernate.envers.boot.internal.EnversService) ServiceRegistry(org.hibernate.service.ServiceRegistry)

Example 8 with SessionImplementor

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);
    }
}
Also used : CannotCreateTransactionException(org.springframework.transaction.CannotCreateTransactionException) IllegalTransactionStateException(org.springframework.transaction.IllegalTransactionStateException) Connection(java.sql.Connection) InvalidIsolationLevelException(org.springframework.transaction.InvalidIsolationLevelException) FlushMode(org.hibernate.FlushMode) ConnectionHolder(org.springframework.jdbc.datasource.ConnectionHolder) Transaction(org.hibernate.Transaction) SessionImplementor(org.hibernate.engine.spi.SessionImplementor) Interceptor(org.hibernate.Interceptor) Session(org.hibernate.Session)

Example 9 with SessionImplementor

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");
    });
}
Also used : SessionFactory(org.hibernate.SessionFactory) Statement(java.sql.Statement) PersistenceUnitUtil(javax.persistence.PersistenceUnitUtil) EntityNotFoundException(javax.persistence.EntityNotFoundException) EntityNotFoundException(javax.persistence.EntityNotFoundException) PersistenceUtil(javax.persistence.PersistenceUtil) SessionImplementor(org.hibernate.engine.spi.SessionImplementor) Session(org.hibernate.Session) Test(org.junit.Test)

Example 10 with SessionImplementor

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);
}
Also used : EntityPersister(org.hibernate.persister.entity.EntityPersister) Serializable(java.io.Serializable) SelfDirtinessTracker(org.hibernate.engine.spi.SelfDirtinessTracker) EntityEntry(org.hibernate.engine.spi.EntityEntry) SessionImplementor(org.hibernate.engine.spi.SessionImplementor)

Aggregations

SessionImplementor (org.hibernate.engine.spi.SessionImplementor)82 Session (org.hibernate.Session)59 Test (org.junit.Test)54 Connection (java.sql.Connection)20 TestForIssue (org.hibernate.testing.TestForIssue)18 PreparedStatement (java.sql.PreparedStatement)17 Work (org.hibernate.jdbc.Work)13 Statement (java.sql.Statement)12 List (java.util.List)12 Transaction (org.hibernate.Transaction)12 EntityPersister (org.hibernate.persister.entity.EntityPersister)12 ResultSet (java.sql.ResultSet)11 SQLException (java.sql.SQLException)11 ArrayList (java.util.ArrayList)7 JDBCException (org.hibernate.JDBCException)6 CollectionEntry (org.hibernate.engine.spi.CollectionEntry)6 EntityEntry (org.hibernate.engine.spi.EntityEntry)6 QueryParameters (org.hibernate.engine.spi.QueryParameters)6 ResultSetProcessor (org.hibernate.loader.plan.exec.process.spi.ResultSetProcessor)6 NamedParameterContext (org.hibernate.loader.plan.exec.query.spi.NamedParameterContext)6