use of org.hibernate.persister.entity.Queryable in project hibernate-orm by hibernate.
the class GlobalTemporaryTableBulkIdStrategy method buildDeleteHandler.
@Override
public DeleteHandler buildDeleteHandler(SessionFactoryImplementor factory, HqlSqlWalker walker) {
final DeleteStatement updateStatement = (DeleteStatement) walker.getAST();
final FromElement fromElement = updateStatement.getFromClause().getFromElement();
final Queryable targetedPersister = fromElement.getQueryable();
return new TableBasedDeleteHandlerImpl(factory, walker, getIdTableInfo(targetedPersister)) {
@Override
protected void releaseFromUse(Queryable persister, SharedSessionContractImplementor session) {
if (afterUseAction == AfterUseAction.NONE) {
return;
}
// clean up our id-table rows
cleanUpRows(getIdTableInfo(persister).getQualifiedIdTableName(), session);
}
};
}
use of org.hibernate.persister.entity.Queryable in project hibernate-orm by hibernate.
the class FromParser method token.
public void token(String token, QueryTranslatorImpl q) throws QueryException {
// start by looking for HQL keywords...
String lcToken = token.toLowerCase(Locale.ROOT);
if (lcToken.equals(",")) {
if (!(expectingJoin | expectingAs)) {
throw new QueryException("unexpected token: ,");
}
expectingJoin = false;
expectingAs = false;
} else if (lcToken.equals("join")) {
if (!afterJoinType) {
if (!(expectingJoin | expectingAs)) {
throw new QueryException("unexpected token: join");
}
// inner joins can be abbreviated to 'join'
joinType = JoinType.INNER_JOIN;
expectingJoin = false;
expectingAs = false;
} else {
afterJoinType = false;
}
} else if (lcToken.equals("fetch")) {
if (q.isShallowQuery()) {
throw new QueryException(QueryTranslator.ERROR_CANNOT_FETCH_WITH_ITERATE);
}
if (joinType == JoinType.NONE) {
throw new QueryException("unexpected token: fetch");
}
if (joinType == JoinType.FULL_JOIN || joinType == JoinType.RIGHT_OUTER_JOIN) {
throw new QueryException("fetch may only be used with inner join or left outer join");
}
afterFetch = true;
} else if (lcToken.equals("outer")) {
// 'outer' is optional and is ignored
if (!afterJoinType || (joinType != JoinType.LEFT_OUTER_JOIN && joinType != JoinType.RIGHT_OUTER_JOIN)) {
throw new QueryException("unexpected token: outer");
}
} else if (JOIN_TYPES.containsKey(lcToken)) {
if (!(expectingJoin | expectingAs)) {
throw new QueryException("unexpected token: " + token);
}
joinType = JOIN_TYPES.get(lcToken);
afterJoinType = true;
expectingJoin = false;
expectingAs = false;
} else if (lcToken.equals("class")) {
if (!afterIn) {
throw new QueryException("unexpected token: class");
}
if (joinType != JoinType.NONE) {
throw new QueryException("outer or full join must be followed by path expression");
}
afterClass = true;
} else if (lcToken.equals("in")) {
if (alias == null) {
memberDeclarations = true;
afterMemberDeclarations = false;
} else if (!expectingIn) {
throw new QueryException("unexpected token: in");
} else {
afterIn = true;
expectingIn = false;
}
} else if (lcToken.equals("as")) {
if (!expectingAs) {
throw new QueryException("unexpected token: as");
}
afterAs = true;
expectingAs = false;
} else if ("(".equals(token)) {
if (!memberDeclarations) {
throw new QueryException("unexpected token: (");
}
//TODO alias should be null here
expectingPathExpression = true;
} else if (")".equals(token)) {
// memberDeclarations = false;
// expectingPathExpression = false;
afterMemberDeclarations = true;
} else {
if (afterJoinType) {
throw new QueryException("join expected: " + token);
}
if (expectingJoin) {
throw new QueryException("unexpected token: " + token);
}
if (expectingIn) {
throw new QueryException("in expected: " + token);
}
if (afterAs || expectingAs) {
if (entityName != null) {
q.setAliasName(token, entityName);
} else if (collectionName != null) {
q.setAliasName(token, collectionName);
} else {
throw new QueryException("unexpected: as " + token);
}
afterAs = false;
expectingJoin = true;
expectingAs = false;
entityName = null;
collectionName = null;
memberDeclarations = false;
expectingPathExpression = false;
afterMemberDeclarations = false;
} else if (afterIn) {
if (alias == null) {
throw new QueryException("alias not specified for: " + token);
}
if (joinType != JoinType.NONE) {
throw new QueryException("outer or full join must be followed by path expression");
}
if (afterClass) {
// treat it as a classname
Queryable p = q.getEntityPersisterUsingImports(token);
if (p == null) {
throw new QueryException("persister not found: " + token);
}
q.addFromClass(alias, p);
} else {
// treat it as a path expression
peParser.setJoinType(JoinType.INNER_JOIN);
peParser.setUseThetaStyleJoin(true);
ParserHelper.parse(peParser, q.unalias(token), ParserHelper.PATH_SEPARATORS, q);
if (!peParser.isCollectionValued()) {
throw new QueryException("path expression did not resolve to collection: " + token);
}
String nm = peParser.addFromCollection(q);
q.setAliasName(alias, nm);
}
alias = null;
afterIn = false;
afterClass = false;
expectingJoin = true;
} else if (memberDeclarations && expectingPathExpression) {
expectingAs = true;
peParser.setJoinType(JoinType.INNER_JOIN);
peParser.setUseThetaStyleJoin(false);
ParserHelper.parse(peParser, q.unalias(token), ParserHelper.PATH_SEPARATORS, q);
if (!peParser.isCollectionValued()) {
throw new QueryException("path expression did not resolve to collection: " + token);
}
collectionName = peParser.addFromCollection(q);
expectingPathExpression = false;
memberDeclarations = false;
} else {
// handle a path expression or class name that
// appears at the start, in the "new" HQL
// style or an alias that appears at the start
// in the "old" HQL style
Queryable p = q.getEntityPersisterUsingImports(token);
if (p != null) {
// starts with the name of a mapped class (new style)
if (joinType != JoinType.NONE) {
throw new QueryException("outer or full join must be followed by path expression");
}
entityName = q.createNameFor(p.getEntityName());
q.addFromClass(entityName, p);
expectingAs = true;
} else if (token.indexOf('.') < 0) {
// starts with an alias (old style)
// semi-bad thing about this: can't re-alias another alias.....
alias = token;
expectingIn = true;
} else {
//allow ODMG OQL style: from Person p, p.cars c
if (joinType != JoinType.NONE) {
peParser.setJoinType(joinType);
} else {
peParser.setJoinType(JoinType.INNER_JOIN);
}
peParser.setUseThetaStyleJoin(q.isSubquery());
ParserHelper.parse(peParser, q.unalias(token), ParserHelper.PATH_SEPARATORS, q);
entityName = peParser.addFromAssociation(q);
joinType = JoinType.NONE;
peParser.setJoinType(JoinType.INNER_JOIN);
if (afterFetch) {
peParser.fetch(q, entityName);
afterFetch = false;
}
expectingAs = true;
}
}
}
}
use of org.hibernate.persister.entity.Queryable in project hibernate-orm by hibernate.
the class PathExpressionParser method continueFromManyToMany.
String continueFromManyToMany(String entityName, String[] joinColumns, QueryTranslatorImpl q) throws QueryException {
start(q);
continuation = true;
currentName = q.createNameFor(entityName);
q.addType(currentName, entityName);
Queryable classPersister = q.getEntityPersister(entityName);
//QueryJoinFragment join = q.createJoinFragment(useThetaStyleJoin);
addJoin(currentName, q.getFactory().getTypeResolver().getTypeFactory().manyToOne(entityName), joinColumns);
currentPropertyMapping = classPersister;
return currentName;
}
use of org.hibernate.persister.entity.Queryable in project hibernate-orm by hibernate.
the class ValidityAuditStrategy method perform.
@Override
public void perform(final Session session, final String entityName, final AuditEntitiesConfiguration audEntitiesCfg, final Serializable id, final Object data, final Object revision) {
final String auditedEntityName = audEntitiesCfg.getAuditEntityName(entityName);
final String revisionInfoEntityName = audEntitiesCfg.getRevisionInfoEntityName();
// Save the audit data
session.save(auditedEntityName, data);
// Update the end date of the previous row.
//
// When application reuses identifiers of previously removed entities:
// The UPDATE statement will no-op if an entity with a given identifier has been
// inserted for the first time. But in case a deleted primary key value was
// reused, this guarantees correct strategy behavior: exactly one row with
// null end date exists for each identifier.
final boolean reuseEntityIdentifier = audEntitiesCfg.getEnversService().getGlobalConfiguration().isAllowIdentifierReuse();
if (reuseEntityIdentifier || getRevisionType(audEntitiesCfg, data) != RevisionType.ADD) {
// Register transaction completion process to guarantee execution of UPDATE statement afterQuery INSERT.
((EventSource) session).getActionQueue().registerProcess(new BeforeTransactionCompletionProcess() {
@Override
public void doBeforeTransactionCompletion(final SessionImplementor sessionImplementor) {
final Queryable productionEntityQueryable = getQueryable(entityName, sessionImplementor);
final Queryable rootProductionEntityQueryable = getQueryable(productionEntityQueryable.getRootEntityName(), sessionImplementor);
final Queryable auditedEntityQueryable = getQueryable(auditedEntityName, sessionImplementor);
final Queryable rootAuditedEntityQueryable = getQueryable(auditedEntityQueryable.getRootEntityName(), sessionImplementor);
final String updateTableName;
if (UnionSubclassEntityPersister.class.isInstance(rootProductionEntityQueryable)) {
// this is the condition causing all the problems in terms of the generated SQL UPDATE
// the problem being that we currently try to update the in-line view made up of the union query
//
// this is extremely hacky means to get the root table name for the union subclass style entities.
// hacky because it relies on internal behavior of UnionSubclassEntityPersister
// !!!!!! NOTICE - using subclass persister, not root !!!!!!
updateTableName = auditedEntityQueryable.getSubclassTableName(0);
} else {
updateTableName = rootAuditedEntityQueryable.getTableName();
}
final Type revisionInfoIdType = sessionImplementor.getFactory().getMetamodel().entityPersister(revisionInfoEntityName).getIdentifierType();
final String revEndColumnName = rootAuditedEntityQueryable.toColumns(audEntitiesCfg.getRevisionEndFieldName())[0];
final boolean isRevisionEndTimestampEnabled = audEntitiesCfg.isRevisionEndTimestampEnabled();
// update audit_ent set REVEND = ? [, REVEND_TSTMP = ?] where (prod_ent_id) = ? and REV <> ? and REVEND is null
final Update update = new Update(sessionImplementor.getFactory().getJdbcServices().getDialect()).setTableName(updateTableName);
// set REVEND = ?
update.addColumn(revEndColumnName);
// set [, REVEND_TSTMP = ?]
if (isRevisionEndTimestampEnabled) {
update.addColumn(rootAuditedEntityQueryable.toColumns(audEntitiesCfg.getRevisionEndTimestampFieldName())[0]);
}
// where (prod_ent_id) = ?
update.addPrimaryKeyColumns(rootProductionEntityQueryable.getIdentifierColumnNames());
// where REV <> ?
update.addWhereColumn(rootAuditedEntityQueryable.toColumns(audEntitiesCfg.getRevisionNumberPath())[0], "<> ?");
// where REVEND is null
update.addWhereColumn(revEndColumnName, " is null");
// Now lets execute the sql...
final String updateSql = update.toStatementString();
int rowCount = sessionImplementor.doReturningWork(new ReturningWork<Integer>() {
@Override
public Integer execute(Connection connection) throws SQLException {
PreparedStatement preparedStatement = sessionImplementor.getJdbcCoordinator().getStatementPreparer().prepareStatement(updateSql);
try {
int index = 1;
// set REVEND = ?
final Number revisionNumber = audEntitiesCfg.getEnversService().getRevisionInfoNumberReader().getRevisionNumber(revision);
revisionInfoIdType.nullSafeSet(preparedStatement, revisionNumber, index, sessionImplementor);
index += revisionInfoIdType.getColumnSpan(sessionImplementor.getFactory());
// set [, REVEND_TSTMP = ?]
if (isRevisionEndTimestampEnabled) {
final Object revEndTimestampObj = revisionTimestampGetter.get(revision);
final Date revisionEndTimestamp = convertRevEndTimestampToDate(revEndTimestampObj);
final Type revEndTsType = rootAuditedEntityQueryable.getPropertyType(audEntitiesCfg.getRevisionEndTimestampFieldName());
revEndTsType.nullSafeSet(preparedStatement, revisionEndTimestamp, index, sessionImplementor);
index += revEndTsType.getColumnSpan(sessionImplementor.getFactory());
}
// where (prod_ent_id) = ?
final Type idType = rootProductionEntityQueryable.getIdentifierType();
idType.nullSafeSet(preparedStatement, id, index, sessionImplementor);
index += idType.getColumnSpan(sessionImplementor.getFactory());
// where REV <> ?
final Type revType = rootAuditedEntityQueryable.getPropertyType(audEntitiesCfg.getRevisionNumberPath());
revType.nullSafeSet(preparedStatement, revisionNumber, index, sessionImplementor);
return sessionImplementor.getJdbcCoordinator().getResultSetReturn().executeUpdate(preparedStatement);
} finally {
sessionImplementor.getJdbcCoordinator().getLogicalConnection().getResourceRegistry().release(preparedStatement);
sessionImplementor.getJdbcCoordinator().afterStatementExecution();
}
}
});
if (rowCount != 1 && (!reuseEntityIdentifier || (getRevisionType(audEntitiesCfg, data) != RevisionType.ADD))) {
throw new RuntimeException("Cannot update previous revision for entity " + auditedEntityName + " and id " + id);
}
}
});
}
sessionCacheCleaner.scheduleAuditDataRemoval(session, data);
}
Aggregations