Search in sources :

Example 1 with VersionType

use of org.hibernate.type.VersionType in project hibernate-orm by hibernate.

the class HqlSqlWalker method postProcessInsert.

@Override
protected void postProcessInsert(AST insert) throws SemanticException, QueryException {
    InsertStatement insertStatement = (InsertStatement) insert;
    insertStatement.validate();
    SelectClause selectClause = insertStatement.getSelectClause();
    Queryable persister = insertStatement.getIntoClause().getQueryable();
    if (!insertStatement.getIntoClause().isExplicitIdInsertion()) {
        // the insert did not explicitly reference the id.  See if
        //		1) that is allowed
        //		2) whether we need to alter the SQL tree to account for id
        final IdentifierGenerator generator = persister.getIdentifierGenerator();
        if (!BulkInsertionCapableIdentifierGenerator.class.isInstance(generator)) {
            throw new QueryException("Invalid identifier generator encountered for implicit id handling as part of bulk insertions");
        }
        final BulkInsertionCapableIdentifierGenerator capableGenerator = BulkInsertionCapableIdentifierGenerator.class.cast(generator);
        if (!capableGenerator.supportsBulkInsertionIdentifierGeneration()) {
            throw new QueryException("Identifier generator reported it does not support implicit id handling as part of bulk insertions");
        }
        final String fragment = capableGenerator.determineBulkInsertionIdentifierGenerationSelectFragment(sessionFactoryHelper.getFactory().getDialect());
        if (fragment != null) {
            // we got a fragment from the generator, so alter the sql tree...
            //
            // first, wrap the fragment as a node
            AST fragmentNode = getASTFactory().create(HqlSqlTokenTypes.SQL_TOKEN, fragment);
            // next, rearrange the SQL tree to add the fragment node as the first select expression
            AST originalFirstSelectExprNode = selectClause.getFirstChild();
            selectClause.setFirstChild(fragmentNode);
            fragmentNode.setNextSibling(originalFirstSelectExprNode);
            // finally, prepend the id column name(s) to the insert-spec
            insertStatement.getIntoClause().prependIdColumnSpec();
        }
    }
    if (sessionFactoryHelper.getFactory().getDialect().supportsParametersInInsertSelect()) {
        AST child = selectClause.getFirstChild();
        int i = 0;
        while (child != null) {
            if (child instanceof ParameterNode) {
                // infer the parameter type from the type listed in the INSERT INTO clause
                ((ParameterNode) child).setExpectedType(insertStatement.getIntoClause().getInsertionTypes()[selectClause.getParameterPositions().get(i)]);
                i++;
            }
            child = child.getNextSibling();
        }
    }
    final boolean includeVersionProperty = persister.isVersioned() && !insertStatement.getIntoClause().isExplicitVersionInsertion() && persister.isVersionPropertyInsertable();
    if (includeVersionProperty) {
        // We need to seed the version value as part of this bulk insert
        VersionType versionType = persister.getVersionType();
        AST versionValueNode = null;
        if (sessionFactoryHelper.getFactory().getDialect().supportsParametersInInsertSelect()) {
            int[] sqlTypes = versionType.sqlTypes(sessionFactoryHelper.getFactory());
            if (sqlTypes == null || sqlTypes.length == 0) {
                throw new IllegalStateException(versionType.getClass() + ".sqlTypes() returns null or empty array");
            }
            if (sqlTypes.length > 1) {
                throw new IllegalStateException(versionType.getClass() + ".sqlTypes() returns > 1 element; only single-valued versions are allowed.");
            }
            versionValueNode = getASTFactory().create(HqlSqlTokenTypes.PARAM, "?");
            ParameterSpecification paramSpec = new VersionTypeSeedParameterSpecification(versionType);
            ((ParameterNode) versionValueNode).setHqlParameterSpecification(paramSpec);
            parameters.add(0, paramSpec);
            if (sessionFactoryHelper.getFactory().getDialect().requiresCastingOfParametersInSelectClause()) {
                // we need to wrtap the param in a cast()
                MethodNode versionMethodNode = (MethodNode) getASTFactory().create(HqlSqlTokenTypes.METHOD_CALL, "(");
                AST methodIdentNode = getASTFactory().create(HqlSqlTokenTypes.IDENT, "cast");
                versionMethodNode.addChild(methodIdentNode);
                versionMethodNode.initializeMethodNode(methodIdentNode, true);
                AST castExprListNode = getASTFactory().create(HqlSqlTokenTypes.EXPR_LIST, "exprList");
                methodIdentNode.setNextSibling(castExprListNode);
                castExprListNode.addChild(versionValueNode);
                versionValueNode.setNextSibling(getASTFactory().create(HqlSqlTokenTypes.IDENT, sessionFactoryHelper.getFactory().getDialect().getTypeName(sqlTypes[0])));
                processFunction(versionMethodNode, true);
                versionValueNode = versionMethodNode;
            }
        } else {
            if (isIntegral(versionType)) {
                try {
                    Object seedValue = versionType.seed(null);
                    versionValueNode = getASTFactory().create(HqlSqlTokenTypes.SQL_TOKEN, seedValue.toString());
                } catch (Throwable t) {
                    throw new QueryException("could not determine seed value for version on bulk insert [" + versionType + "]");
                }
            } else if (isDatabaseGeneratedTimestamp(versionType)) {
                String functionName = sessionFactoryHelper.getFactory().getDialect().getCurrentTimestampSQLFunctionName();
                versionValueNode = getASTFactory().create(HqlSqlTokenTypes.SQL_TOKEN, functionName);
            } else {
                throw new QueryException("cannot handle version type [" + versionType + "] on bulk inserts with dialects not supporting parameters in insert-select statements");
            }
        }
        AST currentFirstSelectExprNode = selectClause.getFirstChild();
        selectClause.setFirstChild(versionValueNode);
        versionValueNode.setNextSibling(currentFirstSelectExprNode);
        insertStatement.getIntoClause().prependVersionColumnSpec();
    }
    if (insertStatement.getIntoClause().isDiscriminated()) {
        String sqlValue = insertStatement.getIntoClause().getQueryable().getDiscriminatorSQLValue();
        AST discrimValue = getASTFactory().create(HqlSqlTokenTypes.SQL_TOKEN, sqlValue);
        insertStatement.getSelectClause().addChild(discrimValue);
    }
}
Also used : SelectClause(org.hibernate.hql.internal.ast.tree.SelectClause) AST(antlr.collections.AST) CollectionFilterKeyParameterSpecification(org.hibernate.param.CollectionFilterKeyParameterSpecification) ParameterSpecification(org.hibernate.param.ParameterSpecification) PositionalParameterSpecification(org.hibernate.param.PositionalParameterSpecification) VersionTypeSeedParameterSpecification(org.hibernate.param.VersionTypeSeedParameterSpecification) NamedParameterSpecification(org.hibernate.param.NamedParameterSpecification) VersionTypeSeedParameterSpecification(org.hibernate.param.VersionTypeSeedParameterSpecification) Queryable(org.hibernate.persister.entity.Queryable) InsertStatement(org.hibernate.hql.internal.ast.tree.InsertStatement) UserVersionType(org.hibernate.usertype.UserVersionType) VersionType(org.hibernate.type.VersionType) BulkInsertionCapableIdentifierGenerator(org.hibernate.id.BulkInsertionCapableIdentifierGenerator) QueryException(org.hibernate.QueryException) ParameterNode(org.hibernate.hql.internal.ast.tree.ParameterNode) MethodNode(org.hibernate.hql.internal.ast.tree.MethodNode) IdentifierGenerator(org.hibernate.id.IdentifierGenerator) BulkInsertionCapableIdentifierGenerator(org.hibernate.id.BulkInsertionCapableIdentifierGenerator)

Example 2 with VersionType

use of org.hibernate.type.VersionType in project hibernate-orm by hibernate.

the class Loader method checkVersion.

/**
	 * Check the version of the object in the <tt>ResultSet</tt> against
	 * the object version in the session cache, throwing an exception
	 * if the version numbers are different
	 */
private void checkVersion(final int i, final Loadable persister, final Serializable id, final Object entity, final ResultSet rs, final SharedSessionContractImplementor session) throws HibernateException, SQLException {
    Object version = session.getPersistenceContext().getEntry(entity).getVersion();
    if (version != null) {
        //null version means the object is in the process of being loaded somewhere else in the ResultSet
        final VersionType versionType = persister.getVersionType();
        final Object currentVersion = versionType.nullSafeGet(rs, getEntityAliases()[i].getSuffixedVersionAliases(), session, null);
        if (!versionType.isEqual(version, currentVersion)) {
            if (session.getFactory().getStatistics().isStatisticsEnabled()) {
                session.getFactory().getStatistics().optimisticFailure(persister.getEntityName());
            }
            throw new StaleObjectStateException(persister.getEntityName(), id);
        }
    }
}
Also used : StaleObjectStateException(org.hibernate.StaleObjectStateException) VersionType(org.hibernate.type.VersionType)

Example 3 with VersionType

use of org.hibernate.type.VersionType in project hibernate-orm by hibernate.

the class SybaseTimestampComparisonAnnotationsTest method testComparableTimestamps.

@Test
@TestForIssue(jiraKey = "HHH-10413")
public void testComparableTimestamps() {
    final VersionType versionType = sessionFactory().getEntityPersister(Thing.class.getName()).getVersionType();
    assertSame(RowVersionType.INSTANCE, versionType);
    Session s = openSession();
    s.getTransaction().begin();
    Thing thing = new Thing();
    thing.name = "n";
    s.persist(thing);
    s.getTransaction().commit();
    s.close();
    byte[] previousVersion = thing.version;
    for (int i = 0; i < 20; i++) {
        try {
            //1000 milliseconds is one second.
            Thread.sleep(1000);
        } catch (InterruptedException ex) {
            Thread.currentThread().interrupt();
        }
        s = openSession();
        s.getTransaction().begin();
        thing.name = "n" + i;
        thing = (Thing) s.merge(thing);
        s.getTransaction().commit();
        s.close();
        assertTrue(versionType.compare(previousVersion, thing.version) < 0);
        previousVersion = thing.version;
    }
    s = openSession();
    s.getTransaction().begin();
    s.delete(thing);
    s.getTransaction().commit();
    s.close();
}
Also used : RowVersionType(org.hibernate.type.RowVersionType) VersionType(org.hibernate.type.VersionType) Session(org.hibernate.Session) Test(org.junit.Test) TestForIssue(org.hibernate.testing.TestForIssue)

Example 4 with VersionType

use of org.hibernate.type.VersionType in project hibernate-orm by hibernate.

the class SybaseTimestampVersioningTest method testComparableTimestamps.

@Test
@TestForIssue(jiraKey = "HHH-10413")
public void testComparableTimestamps() {
    final VersionType versionType = sessionFactory().getEntityPersister(User.class.getName()).getVersionType();
    assertSame(RowVersionType.INSTANCE, versionType);
    Session s = openSession();
    s.getTransaction().begin();
    User user = new User();
    user.setUsername("n");
    s.persist(user);
    s.getTransaction().commit();
    s.close();
    byte[] previousTimestamp = user.getTimestamp();
    for (int i = 0; i < 20; i++) {
        try {
            //1000 milliseconds is one second.
            Thread.sleep(1000);
        } catch (InterruptedException ex) {
            Thread.currentThread().interrupt();
        }
        s = openSession();
        s.getTransaction().begin();
        user.setUsername("n" + i);
        user = (User) s.merge(user);
        s.getTransaction().commit();
        s.close();
        assertTrue(versionType.compare(previousTimestamp, user.getTimestamp()) < 0);
        previousTimestamp = user.getTimestamp();
    }
    s = openSession();
    s.getTransaction().begin();
    s.delete(user);
    s.getTransaction().commit();
    s.close();
}
Also used : RowVersionType(org.hibernate.type.RowVersionType) VersionType(org.hibernate.type.VersionType) Session(org.hibernate.Session) Test(org.junit.Test) TestForIssue(org.hibernate.testing.TestForIssue)

Example 5 with VersionType

use of org.hibernate.type.VersionType in project hibernate-orm by hibernate.

the class HqlSqlWalker method prepareVersioned.

@Override
protected void prepareVersioned(AST updateNode, AST versioned) throws SemanticException {
    UpdateStatement updateStatement = (UpdateStatement) updateNode;
    FromClause fromClause = updateStatement.getFromClause();
    if (versioned != null) {
        // Make sure that the persister is versioned
        Queryable persister = fromClause.getFromElement().getQueryable();
        if (!persister.isVersioned()) {
            throw new SemanticException("increment option specified for update of non-versioned entity");
        }
        VersionType versionType = persister.getVersionType();
        if (versionType instanceof UserVersionType) {
            throw new SemanticException("user-defined version types not supported for increment option");
        }
        AST eq = getASTFactory().create(HqlSqlTokenTypes.EQ, "=");
        AST versionPropertyNode = generateVersionPropertyNode(persister);
        eq.setFirstChild(versionPropertyNode);
        AST versionIncrementNode = null;
        if (isTimestampBasedVersion(versionType)) {
            versionIncrementNode = getASTFactory().create(HqlSqlTokenTypes.PARAM, "?");
            ParameterSpecification paramSpec = new VersionTypeSeedParameterSpecification(versionType);
            ((ParameterNode) versionIncrementNode).setHqlParameterSpecification(paramSpec);
            parameters.add(0, paramSpec);
        } else {
            // Not possible to simply re-use the versionPropertyNode here as it causes
            // OOM errors due to circularity :(
            versionIncrementNode = getASTFactory().create(HqlSqlTokenTypes.PLUS, "+");
            versionIncrementNode.setFirstChild(generateVersionPropertyNode(persister));
            versionIncrementNode.addChild(getASTFactory().create(HqlSqlTokenTypes.IDENT, "1"));
        }
        eq.addChild(versionIncrementNode);
        evaluateAssignment(eq, persister, 0);
        AST setClause = updateStatement.getSetClause();
        AST currentFirstSetElement = setClause.getFirstChild();
        setClause.setFirstChild(eq);
        eq.setNextSibling(currentFirstSetElement);
    }
}
Also used : UpdateStatement(org.hibernate.hql.internal.ast.tree.UpdateStatement) UserVersionType(org.hibernate.usertype.UserVersionType) AST(antlr.collections.AST) CollectionFilterKeyParameterSpecification(org.hibernate.param.CollectionFilterKeyParameterSpecification) ParameterSpecification(org.hibernate.param.ParameterSpecification) PositionalParameterSpecification(org.hibernate.param.PositionalParameterSpecification) VersionTypeSeedParameterSpecification(org.hibernate.param.VersionTypeSeedParameterSpecification) NamedParameterSpecification(org.hibernate.param.NamedParameterSpecification) VersionTypeSeedParameterSpecification(org.hibernate.param.VersionTypeSeedParameterSpecification) ParameterNode(org.hibernate.hql.internal.ast.tree.ParameterNode) FromClause(org.hibernate.hql.internal.ast.tree.FromClause) Queryable(org.hibernate.persister.entity.Queryable) UserVersionType(org.hibernate.usertype.UserVersionType) VersionType(org.hibernate.type.VersionType) SemanticException(antlr.SemanticException)

Aggregations

VersionType (org.hibernate.type.VersionType)6 AST (antlr.collections.AST)2 Session (org.hibernate.Session)2 StaleObjectStateException (org.hibernate.StaleObjectStateException)2 ParameterNode (org.hibernate.hql.internal.ast.tree.ParameterNode)2 CollectionFilterKeyParameterSpecification (org.hibernate.param.CollectionFilterKeyParameterSpecification)2 NamedParameterSpecification (org.hibernate.param.NamedParameterSpecification)2 ParameterSpecification (org.hibernate.param.ParameterSpecification)2 PositionalParameterSpecification (org.hibernate.param.PositionalParameterSpecification)2 VersionTypeSeedParameterSpecification (org.hibernate.param.VersionTypeSeedParameterSpecification)2 Queryable (org.hibernate.persister.entity.Queryable)2 TestForIssue (org.hibernate.testing.TestForIssue)2 RowVersionType (org.hibernate.type.RowVersionType)2 UserVersionType (org.hibernate.usertype.UserVersionType)2 Test (org.junit.Test)2 SemanticException (antlr.SemanticException)1 SQLException (java.sql.SQLException)1 QueryException (org.hibernate.QueryException)1 JdbcServices (org.hibernate.engine.jdbc.spi.JdbcServices)1 FromClause (org.hibernate.hql.internal.ast.tree.FromClause)1