HHH-11028 - {h-schema} is not replaced in SQLDelete, SQLInsert and SQLUpdate code enhancement
This commit is contained in:
parent
1cb10729b0
commit
090d18dcc8
|
@ -60,6 +60,10 @@ public class SQLQueryParser {
|
|||
return aliasesFound>0;
|
||||
}
|
||||
|
||||
protected String getOriginalQueryString() {
|
||||
return originalQueryString;
|
||||
}
|
||||
|
||||
public String process() {
|
||||
String processedSql = substituteBrackets( originalQueryString );
|
||||
processedSql = substituteParams( processedSql );
|
||||
|
@ -68,7 +72,7 @@ public class SQLQueryParser {
|
|||
|
||||
// TODO: should "record" how many properties we have reffered to - and if we
|
||||
// don't get'em'all we throw an exception! Way better than trial and error ;)
|
||||
private String substituteBrackets(String sqlQuery) throws QueryException {
|
||||
protected String substituteBrackets(String sqlQuery) throws QueryException {
|
||||
|
||||
StringBuilder result = new StringBuilder( sqlQuery.length() + 20 );
|
||||
int left, right;
|
||||
|
@ -126,7 +130,7 @@ public class SQLQueryParser {
|
|||
throw new QueryException( "Unknown placeholder ", aliasPath );
|
||||
}
|
||||
}
|
||||
else {
|
||||
else if (context != null) {
|
||||
int firstDot = aliasPath.indexOf( '.' );
|
||||
if ( firstDot == -1 ) {
|
||||
if ( context.isEntityAlias( aliasPath ) ) {
|
||||
|
|
|
@ -70,7 +70,6 @@ import org.hibernate.engine.spi.LoadQueryInfluencers;
|
|||
import org.hibernate.engine.spi.Mapping;
|
||||
import org.hibernate.engine.spi.PersistenceContext.NaturalIdHelper;
|
||||
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
|
||||
import org.hibernate.engine.spi.SelfDirtinessTracker;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.engine.spi.ValueInclusion;
|
||||
|
@ -87,6 +86,7 @@ import org.hibernate.internal.util.collections.ArrayHelper;
|
|||
import org.hibernate.jdbc.Expectation;
|
||||
import org.hibernate.jdbc.Expectations;
|
||||
import org.hibernate.jdbc.TooManyRowsAffectedException;
|
||||
import org.hibernate.loader.custom.sql.SQLQueryParser;
|
||||
import org.hibernate.loader.entity.BatchingEntityLoaderBuilder;
|
||||
import org.hibernate.loader.entity.CascadeEntityLoader;
|
||||
import org.hibernate.loader.entity.DynamicBatchingEntityLoaderBuilder;
|
||||
|
@ -3927,16 +3927,16 @@ public abstract class AbstractEntityPersister
|
|||
for ( int j = 0; j < joinSpan; j++ ) {
|
||||
sqlInsertStrings[j] = customSQLInsert[j] == null ?
|
||||
generateInsertString( getPropertyInsertability(), j ) :
|
||||
customSQLInsert[j];
|
||||
substituteBrackets( customSQLInsert[j]);
|
||||
sqlUpdateStrings[j] = customSQLUpdate[j] == null ?
|
||||
generateUpdateString( getPropertyUpdateability(), j, false ) :
|
||||
customSQLUpdate[j];
|
||||
substituteBrackets( customSQLUpdate[j]);
|
||||
sqlLazyUpdateStrings[j] = customSQLUpdate[j] == null ?
|
||||
generateUpdateString( getNonLazyPropertyUpdateability(), j, false ) :
|
||||
customSQLUpdate[j];
|
||||
substituteBrackets( customSQLUpdate[j]);
|
||||
sqlDeleteStrings[j] = customSQLDelete[j] == null ?
|
||||
generateDeleteString( j ) :
|
||||
customSQLDelete[j];
|
||||
substituteBrackets( customSQLDelete[j]);
|
||||
}
|
||||
|
||||
tableHasColumns = new boolean[joinSpan];
|
||||
|
@ -3959,7 +3959,7 @@ public abstract class AbstractEntityPersister
|
|||
.getInsertGeneratedIdentifierDelegate( this, getFactory().getDialect(), useGetGeneratedKeys() );
|
||||
sqlIdentityInsertString = customSQLInsert[0] == null
|
||||
? generateIdentityInsertString( getPropertyInsertability() )
|
||||
: customSQLInsert[0];
|
||||
: substituteBrackets( customSQLInsert[0] );
|
||||
}
|
||||
else {
|
||||
sqlIdentityInsertString = null;
|
||||
|
@ -3968,6 +3968,10 @@ public abstract class AbstractEntityPersister
|
|||
logStaticSQL();
|
||||
}
|
||||
|
||||
private String substituteBrackets(String sql) {
|
||||
return new SubstituteBracketSQLQueryParser( sql, getFactory() ).process();
|
||||
}
|
||||
|
||||
public final void postInstantiate() throws MappingException {
|
||||
doLateInit();
|
||||
|
||||
|
@ -5559,5 +5563,15 @@ public abstract class AbstractEntityPersister
|
|||
// };
|
||||
}
|
||||
|
||||
private static class SubstituteBracketSQLQueryParser extends SQLQueryParser {
|
||||
|
||||
SubstituteBracketSQLQueryParser(String queryString, SessionFactoryImplementor factory) {
|
||||
super( queryString, null, factory );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String process() {
|
||||
return substituteBrackets( getOriginalQueryString() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.persister.entity;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.hibernate.annotations.Loader;
|
||||
import org.hibernate.annotations.NamedNativeQuery;
|
||||
import org.hibernate.annotations.Persister;
|
||||
import org.hibernate.annotations.ResultCheckStyle;
|
||||
import org.hibernate.annotations.SQLDelete;
|
||||
import org.hibernate.annotations.SQLInsert;
|
||||
import org.hibernate.annotations.SQLUpdate;
|
||||
import org.hibernate.dialect.H2Dialect;
|
||||
|
||||
import org.hibernate.testing.RequiresDialect;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
/**
|
||||
* @author Laabidi RAISSI
|
||||
*/
|
||||
@RequiresDialect(H2Dialect.class)
|
||||
public class CustomSqlSchemaResolvingIdentityTest extends BaseCoreFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class[]{
|
||||
CustomEntity.class, Dummy.class
|
||||
};
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSchemaNotReplacedInCustomSQL() throws Exception {
|
||||
|
||||
String className = CustomEntity.class.getName();
|
||||
|
||||
final AbstractEntityPersister persister = (AbstractEntityPersister) sessionFactory().getEntityPersister( className );
|
||||
String insertQuery = persister.getSQLInsertStrings()[0];
|
||||
String updateQuery = persister.getSQLUpdateStrings()[0];
|
||||
String deleteQuery = persister.getSQLDeleteStrings()[0];
|
||||
|
||||
assertEquals( "Incorrect custom SQL for insert in Entity: " + className,
|
||||
"INSERT INTO FOO (name) VALUES (?)", insertQuery );
|
||||
|
||||
assertEquals( "Incorrect custom SQL for delete in Entity: " + className,
|
||||
"DELETE FROM FOO WHERE id = ?", deleteQuery );
|
||||
|
||||
assertEquals( "Incorrect custom SQL for update in Entity: " + className,
|
||||
"UPDATE FOO SET name = ? WHERE id = ? ", updateQuery );
|
||||
|
||||
CustomEntity _entitty = doInHibernate( this::sessionFactory, session -> {
|
||||
CustomEntity entity = new CustomEntity();
|
||||
session.persist( entity );
|
||||
|
||||
return entity;
|
||||
} );
|
||||
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
CustomEntity entity = session.find( CustomEntity.class, 1 );
|
||||
assertNotNull(entity);
|
||||
|
||||
entity.name = "Vlad";
|
||||
} );
|
||||
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
CustomEntity entity = session.find( CustomEntity.class, _entitty.id );
|
||||
session.delete( entity );
|
||||
} );
|
||||
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
CustomEntity entity = session.find( CustomEntity.class, _entitty.id );
|
||||
assertNull(entity);
|
||||
} );
|
||||
}
|
||||
|
||||
@Entity(name = "CardWithCustomSQL")
|
||||
@Persister( impl = SingleTableEntityPersister.class )
|
||||
@Loader(namedQuery = "find_foo_by_id")
|
||||
@NamedNativeQuery(
|
||||
name = "find_foo_by_id",
|
||||
query = "SELECT id, name FROM {h-schema}FOO WHERE id = ?",
|
||||
resultClass = CustomEntity.class
|
||||
)
|
||||
@SQLInsert(sql = "INSERT INTO {h-schema}FOO (name) VALUES (?)", callable = true)
|
||||
@SQLDelete(sql = "DELETE FROM {h-schema}FOO WHERE id = ?", check = ResultCheckStyle.COUNT)
|
||||
@SQLUpdate(sql = "UPDATE {h-schema}FOO SET name = ? WHERE id = ? ")
|
||||
public static class CustomEntity {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
public Integer id;
|
||||
|
||||
private String name;
|
||||
}
|
||||
|
||||
@Entity(name = "Dummy")
|
||||
@Table(name = "FOO")
|
||||
public static class Dummy {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
public Integer id;
|
||||
|
||||
private String name;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.persister.entity;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.hibernate.annotations.Loader;
|
||||
import org.hibernate.annotations.NamedNativeQuery;
|
||||
import org.hibernate.annotations.Persister;
|
||||
import org.hibernate.annotations.ResultCheckStyle;
|
||||
import org.hibernate.annotations.SQLDelete;
|
||||
import org.hibernate.annotations.SQLInsert;
|
||||
import org.hibernate.annotations.SQLUpdate;
|
||||
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
/**
|
||||
* @author Laabidi RAISSI
|
||||
*/
|
||||
public class CustomSqlSchemaResolvingTest extends BaseCoreFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class[]{
|
||||
CustomEntity.class, Dummy.class
|
||||
};
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSchemaNotReplacedInCustomSQL() throws Exception {
|
||||
|
||||
String className = CustomEntity.class.getName();
|
||||
|
||||
final AbstractEntityPersister persister = (AbstractEntityPersister) sessionFactory().getEntityPersister( className );
|
||||
String insertQuery = persister.getSQLInsertStrings()[0];
|
||||
String updateQuery = persister.getSQLUpdateStrings()[0];
|
||||
String deleteQuery = persister.getSQLDeleteStrings()[0];
|
||||
|
||||
assertEquals( "Incorrect custom SQL for insert in Entity: " + className,
|
||||
"INSERT INTO FOO (name, id) VALUES (?, ?)", insertQuery );
|
||||
|
||||
assertEquals( "Incorrect custom SQL for delete in Entity: " + className,
|
||||
"DELETE FROM FOO WHERE id = ?", deleteQuery );
|
||||
|
||||
assertEquals( "Incorrect custom SQL for update in Entity: " + className,
|
||||
"UPDATE FOO SET name = ? WHERE id = ? ", updateQuery );
|
||||
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
CustomEntity entity = new CustomEntity();
|
||||
entity.id = 1;
|
||||
session.persist( entity );
|
||||
} );
|
||||
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
CustomEntity entity = session.find( CustomEntity.class, 1 );
|
||||
assertNotNull(entity);
|
||||
|
||||
entity.name = "Vlad";
|
||||
} );
|
||||
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
CustomEntity entity = session.find( CustomEntity.class, 1 );
|
||||
session.delete( entity );
|
||||
} );
|
||||
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
CustomEntity entity = session.find( CustomEntity.class, 1 );
|
||||
assertNull(entity);
|
||||
} );
|
||||
}
|
||||
|
||||
@Entity(name = "CardWithCustomSQL")
|
||||
@Persister( impl = SingleTableEntityPersister.class )
|
||||
@Loader(namedQuery = "find_foo_by_id")
|
||||
@NamedNativeQuery(
|
||||
name = "find_foo_by_id",
|
||||
query = "SELECT id, name FROM {h-schema}FOO WHERE id = ?",
|
||||
resultClass = CustomEntity.class
|
||||
)
|
||||
@SQLInsert(sql = "INSERT INTO {h-schema}FOO (name, id) VALUES (?, ?)", callable = true)
|
||||
@SQLDelete(sql = "DELETE FROM {h-schema}FOO WHERE id = ?", check = ResultCheckStyle.COUNT)
|
||||
@SQLUpdate(sql = "UPDATE {h-schema}FOO SET name = ? WHERE id = ? ")
|
||||
public static class CustomEntity {
|
||||
@Id
|
||||
public Integer id;
|
||||
|
||||
private String name;
|
||||
}
|
||||
|
||||
@Entity(name = "Dummy")
|
||||
@Table(name = "FOO")
|
||||
public static class Dummy {
|
||||
@Id
|
||||
public Integer id;
|
||||
|
||||
private String name;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue