HHH-8487 - Auto-flush on JPA native SQL query
This commit is contained in:
parent
05dcb8f5c1
commit
c6fbd4be4c
|
@ -51,8 +51,7 @@ import org.hibernate.jpa.graph.internal.EntityGraphImpl;
|
|||
*/
|
||||
public class EntityManagerImpl extends AbstractEntityManagerImpl implements SessionOwner {
|
||||
|
||||
public static final EntityManagerMessageLogger LOG = Logger.getMessageLogger(EntityManagerMessageLogger.class,
|
||||
EntityManagerImpl.class.getName());
|
||||
public static final EntityManagerMessageLogger LOG = HEMLogging.messageLogger( EntityManagerImpl.class.getName() );
|
||||
|
||||
protected Session session;
|
||||
protected boolean open;
|
||||
|
|
|
@ -49,6 +49,7 @@ import org.hibernate.CacheMode;
|
|||
import org.hibernate.FlushMode;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.SQLQuery;
|
||||
import org.hibernate.TypeMismatchException;
|
||||
import org.hibernate.engine.query.spi.NamedParameterDescriptor;
|
||||
import org.hibernate.engine.query.spi.OrdinalParameterDescriptor;
|
||||
|
@ -382,6 +383,7 @@ public class QueryImpl<X> extends AbstractQueryImpl<X> implements TypedQuery<X>,
|
|||
@SuppressWarnings({ "unchecked", "RedundantCast" })
|
||||
public List<X> getResultList() {
|
||||
getEntityManager().checkOpen( true );
|
||||
beforeQuery();
|
||||
try {
|
||||
return query.list();
|
||||
}
|
||||
|
@ -396,10 +398,33 @@ public class QueryImpl<X> extends AbstractQueryImpl<X> implements TypedQuery<X>,
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For JPA native SQL queries, we may need to perform a flush before executing the query.
|
||||
*/
|
||||
private void beforeQuery() {
|
||||
final org.hibernate.Query query = getHibernateQuery();
|
||||
if ( ! SQLQuery.class.isInstance( query ) ) {
|
||||
// this need only exists for native SQL queries, not JPQL or Criteria queries (both of which do
|
||||
// partial auto flushing already).
|
||||
return;
|
||||
}
|
||||
|
||||
final SQLQuery sqlQuery = (SQLQuery) query;
|
||||
if ( sqlQuery.getSynchronizedQuerySpaces() != null && ! sqlQuery.getSynchronizedQuerySpaces().isEmpty() ) {
|
||||
// The application defined query spaces on the Hibernate native SQLQuery which means the query will already
|
||||
// perform a partial flush according to the defined query spaces, no need to do a full flush.
|
||||
return;
|
||||
}
|
||||
|
||||
// otherwise we need to flush
|
||||
getEntityManager().flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked", "RedundantCast" })
|
||||
public X getSingleResult() {
|
||||
getEntityManager().checkOpen( true );
|
||||
beforeQuery();
|
||||
try {
|
||||
final List<X> result = query.list();
|
||||
|
||||
|
|
|
@ -35,6 +35,8 @@ import org.junit.Before;
|
|||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.jpa.test.metamodel.AbstractMetamodelSpecificTest;
|
||||
import org.hibernate.jpa.test.metamodel.CreditCard;
|
||||
import org.hibernate.jpa.test.metamodel.CreditCard_;
|
||||
import org.hibernate.jpa.test.metamodel.Customer_;
|
||||
import org.hibernate.jpa.test.metamodel.Order;
|
||||
import org.hibernate.jpa.test.metamodel.Order_;
|
||||
|
@ -282,4 +284,28 @@ public class PredicateTest extends AbstractMetamodelSpecificTest {
|
|||
em.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExplicitBuilderBooleanHandling() {
|
||||
// just checking syntax of the resulting query
|
||||
EntityManager em = getOrCreateEntityManager();
|
||||
em.getTransaction().begin();
|
||||
|
||||
// note : these may fail on various matrix db jobs depending on how the dialect handles booleans
|
||||
{
|
||||
CriteriaQuery<CreditCard> criteriaQuery = builder.createQuery( CreditCard.class );
|
||||
Root<CreditCard> root = criteriaQuery.from( CreditCard.class );
|
||||
criteriaQuery.where( builder.isFalse( root.get( CreditCard_.approved ) ) );
|
||||
em.createQuery( criteriaQuery ).getResultList();
|
||||
}
|
||||
|
||||
{
|
||||
CriteriaQuery<Order> criteriaQuery = builder.createQuery( Order.class );
|
||||
Root<Order> root = criteriaQuery.from( Order.class );
|
||||
criteriaQuery.where( builder.isFalse( root.get( Order_.creditCard ).get( CreditCard_.approved ) ) );
|
||||
em.createQuery( criteriaQuery ).getResultList();
|
||||
}
|
||||
|
||||
em.getTransaction().commit();
|
||||
em.close();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ import java.util.Arrays;
|
|||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.Parameter;
|
||||
import javax.persistence.Query;
|
||||
|
@ -38,10 +39,15 @@ import javax.persistence.Tuple;
|
|||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||
import org.hibernate.jpa.test.Distributor;
|
||||
import org.hibernate.jpa.test.Item;
|
||||
import org.hibernate.jpa.test.Wallet;
|
||||
import org.hibernate.stat.Statistics;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
|
||||
|
@ -56,6 +62,22 @@ import static org.junit.Assert.fail;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class QueryTest extends BaseEntityManagerFunctionalTestCase {
|
||||
@Override
|
||||
public Class[] getAnnotatedClasses() {
|
||||
return new Class[] {
|
||||
Item.class,
|
||||
Distributor.class,
|
||||
Wallet.class
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void addConfigOptions(Map options) {
|
||||
super.addConfigOptions( options );
|
||||
options.put( AvailableSettings.GENERATE_STATISTICS, "true" );
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-7192" )
|
||||
public void testTypedManipulationQueryError() {
|
||||
|
@ -300,8 +322,13 @@ public class QueryTest extends BaseEntityManagerFunctionalTestCase {
|
|||
assertTrue( em.contains( item ) );
|
||||
em.getTransaction().commit();
|
||||
|
||||
Statistics stats = em.getEntityManagerFactory().unwrap( SessionFactoryImplementor.class ).getStatistics();
|
||||
stats.clear();
|
||||
assertEquals( 0, stats.getFlushCount() );
|
||||
|
||||
em.getTransaction().begin();
|
||||
item = (Item) em.createNativeQuery( "select * from Item", Item.class ).getSingleResult();
|
||||
assertEquals( 1, stats.getFlushCount() );
|
||||
assertNotNull( item );
|
||||
assertEquals( "Micro$oft mouse", item.getDescr() );
|
||||
em.remove( item );
|
||||
|
@ -590,14 +617,18 @@ public class QueryTest extends BaseEntityManagerFunctionalTestCase {
|
|||
catch (IllegalArgumentException e) {
|
||||
//success
|
||||
}
|
||||
assertTrue( "thrown IllegalArgumentException should of caused transaction to be marked for rollback only",
|
||||
true == em.getTransaction().getRollbackOnly() );
|
||||
assertTrue(
|
||||
"thrown IllegalArgumentException should of caused transaction to be marked for rollback only",
|
||||
true == em.getTransaction().getRollbackOnly()
|
||||
);
|
||||
em.getTransaction().rollback(); // HHH-8442 changed to rollback since thrown ISE causes
|
||||
// transaction to be marked for rollback only.
|
||||
// No need to remove entity since it was rolled back.
|
||||
|
||||
assertNull( "entity should not of been saved to database since IllegalArgumentException should of" +
|
||||
"caused transaction to be marked for rollback only", em.find(Item.class, item.getName()));
|
||||
assertNull(
|
||||
"entity should not of been saved to database since IllegalArgumentException should of" +
|
||||
"caused transaction to be marked for rollback only", em.find( Item.class, item.getName() )
|
||||
);
|
||||
em.close();
|
||||
|
||||
}
|
||||
|
@ -652,13 +683,4 @@ public class QueryTest extends BaseEntityManagerFunctionalTestCase {
|
|||
|
||||
em.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class[] getAnnotatedClasses() {
|
||||
return new Class[]{
|
||||
Item.class,
|
||||
Distributor.class,
|
||||
Wallet.class
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue