diff --git a/hibernate-core/src/test/java/org/hibernate/test/exceptionhandling/ExceptionExpectations.java b/hibernate-core/src/test/java/org/hibernate/test/exceptionhandling/ExceptionExpectations.java index 84d1dc66f3..8e5f239826 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/exceptionhandling/ExceptionExpectations.java +++ b/hibernate-core/src/test/java/org/hibernate/test/exceptionhandling/ExceptionExpectations.java @@ -7,10 +7,14 @@ package org.hibernate.test.exceptionhandling; import java.sql.SQLException; +import javax.persistence.OptimisticLockException; import javax.persistence.PersistenceException; +import org.hibernate.StaleObjectStateException; import org.hibernate.TransientObjectException; import org.hibernate.exception.ConstraintViolationException; +import org.hibernate.hql.internal.ast.QuerySyntaxException; +import org.hibernate.id.IdentifierGenerationException; import static org.hamcrest.CoreMatchers.instanceOf; import static org.junit.Assert.assertThat; @@ -41,6 +45,24 @@ public void onTransientObjectOnPersistAndMergeAndFlush(RuntimeException e) { assertThat( e, instanceOf( IllegalStateException.class ) ); assertThat( e.getCause(), instanceOf( TransientObjectException.class ) ); } + + @Override + public void onInvalidQueryExecuted(RuntimeException e) { + assertThat( e, instanceOf( IllegalArgumentException.class ) ); + assertThat( e.getCause(), instanceOf( QuerySyntaxException.class ) ); + } + + @Override + public void onStaleObjectMergeAndUpdateFlush(RuntimeException e) { + assertThat( e, instanceOf( OptimisticLockException.class ) ); + assertThat( e.getCause(), instanceOf( StaleObjectStateException.class ) ); + } + + @Override + public void onIdentifierGeneratorFailure(RuntimeException e) { + assertThat( e, instanceOf( PersistenceException.class ) ); + assertThat( e.getCause(), instanceOf( IdentifierGenerationException.class ) ); + } }; } @@ -67,6 +89,21 @@ public void onTransientObjectOnSaveAndSaveOrUpdate(RuntimeException e) { public void onTransientObjectOnPersistAndMergeAndFlush(RuntimeException e) { assertThat( e, instanceOf( TransientObjectException.class ) ); } + + @Override + public void onInvalidQueryExecuted(RuntimeException e) { + assertThat( e, instanceOf( QuerySyntaxException.class ) ); + } + + @Override + public void onStaleObjectMergeAndUpdateFlush(RuntimeException e) { + assertThat( e, instanceOf( StaleObjectStateException.class ) ); + } + + @Override + public void onIdentifierGeneratorFailure(RuntimeException e) { + assertThat( e, instanceOf( IdentifierGenerationException.class ) ); + } }; } @@ -95,6 +132,24 @@ public void onTransientObjectOnPersistAndMergeAndFlush(RuntimeException e) { assertThat( e, instanceOf( IllegalStateException.class ) ); assertThat( e.getCause(), instanceOf( TransientObjectException.class ) ); } + + @Override + public void onInvalidQueryExecuted(RuntimeException e) { + assertThat( e, instanceOf( IllegalArgumentException.class ) ); + assertThat( e.getCause(), instanceOf( QuerySyntaxException.class ) ); + } + + @Override + public void onStaleObjectMergeAndUpdateFlush(RuntimeException e) { + assertThat( e, instanceOf( OptimisticLockException.class ) ); + assertThat( e.getCause(), instanceOf( StaleObjectStateException.class ) ); + } + + @Override + public void onIdentifierGeneratorFailure(RuntimeException e) { + assertThat( e, instanceOf( PersistenceException.class ) ); + assertThat( e.getCause(), instanceOf( IdentifierGenerationException.class ) ); + } }; } @@ -105,4 +160,10 @@ public void onTransientObjectOnPersistAndMergeAndFlush(RuntimeException e) { void onTransientObjectOnSaveAndSaveOrUpdate(RuntimeException e); void onTransientObjectOnPersistAndMergeAndFlush(RuntimeException e); -} + + void onInvalidQueryExecuted(RuntimeException e); + + void onStaleObjectMergeAndUpdateFlush(RuntimeException e); + + void onIdentifierGeneratorFailure(RuntimeException e); +} \ No newline at end of file diff --git a/hibernate-core/src/test/java/org/hibernate/test/exceptionhandling/IdentifierGenerationExceptionHandlingTest.java b/hibernate-core/src/test/java/org/hibernate/test/exceptionhandling/IdentifierGenerationExceptionHandlingTest.java new file mode 100644 index 0000000000..0a24498783 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/exceptionhandling/IdentifierGenerationExceptionHandlingTest.java @@ -0,0 +1,86 @@ +/* + * 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 . + */ +package org.hibernate.test.exceptionhandling; + +import javax.persistence.CascadeType; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.OneToOne; +import javax.persistence.PrimaryKeyJoinColumn; + +import org.hibernate.Session; +import org.hibernate.annotations.GenericGenerator; +import org.hibernate.annotations.Parameter; + +import org.hibernate.testing.TestForIssue; +import org.junit.Test; + +import static org.junit.Assert.fail; + +@TestForIssue(jiraKey = "HHH-12666") +public class IdentifierGenerationExceptionHandlingTest extends BaseExceptionHandlingTest { + + public IdentifierGenerationExceptionHandlingTest( + BootstrapMethod bootstrapMethod, + ExceptionHandlingSetting exceptionHandlingSetting, + ExceptionExpectations exceptionExpectations) { + super( bootstrapMethod, exceptionHandlingSetting, exceptionExpectations ); + } + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { + Owner.class, + OwnerAddress.class + }; + } + + @Test + public void testIdentifierGeneratorException() { + OwnerAddress address = new OwnerAddress(); + address.owner = null; + + Session s = openSession(); + s.beginTransaction(); + try { + s.persist( address ); + s.flush(); + fail( "should have thrown an exception" ); + } + catch (RuntimeException expected) { + exceptionExpectations.onIdentifierGeneratorFailure( expected ); + } + finally { + s.getTransaction().rollback(); + s.close(); + } + } + + @Entity(name = "OwnerAddress") + public static class OwnerAddress { + @Id + @GeneratedValue(generator = "fk_1") + @GenericGenerator(strategy = "foreign", name = "fk_1", parameters = @Parameter(name = "property", value = "owner")) + private Integer id; + + @OneToOne(mappedBy = "address") + private Owner owner; + } + + @Entity(name = "Owner") + public static class Owner { + @Id + @GeneratedValue + private Integer id; + + @OneToOne(cascade = CascadeType.ALL) + @PrimaryKeyJoinColumn + private OwnerAddress address; + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/exceptionhandling/QuerySyntaxExceptionHandlingTest.java b/hibernate-core/src/test/java/org/hibernate/test/exceptionhandling/QuerySyntaxExceptionHandlingTest.java new file mode 100644 index 0000000000..a464cf3fdf --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/exceptionhandling/QuerySyntaxExceptionHandlingTest.java @@ -0,0 +1,64 @@ +/* + * 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 . + */ +package org.hibernate.test.exceptionhandling; + +import static org.junit.Assert.fail; + +import javax.persistence.Entity; +import javax.persistence.Id; + +import org.hibernate.Session; +import org.hibernate.Transaction; +import org.hibernate.testing.TestForIssue; +import org.junit.Test; + +@TestForIssue(jiraKey = "HHH-12666") +public class QuerySyntaxExceptionHandlingTest extends BaseExceptionHandlingTest { + + public QuerySyntaxExceptionHandlingTest( + BootstrapMethod bootstrapMethod, + ExceptionHandlingSetting exceptionHandlingSetting, + ExceptionExpectations exceptionExpectations) { + super( bootstrapMethod, exceptionHandlingSetting, exceptionExpectations ); + } + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { + A.class + }; + } + + @Test + public void testInvalidQuery() { + Session s = openSession(); + Transaction tx = s.beginTransaction(); + A a = new A(); + a.id = 1; + s.persist( a ); + s.flush(); + s.clear(); + + try { + s.createQuery( "from A where blahblahblah" ).list(); + fail( "should have thrown an exception" ); + } + catch (RuntimeException expected) { + exceptionExpectations.onInvalidQueryExecuted( expected ); + } + finally { + tx.rollback(); + s.close(); + } + } + + @Entity(name = "A") + public static class A { + @Id + private long id; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/exceptionhandling/StateObjectStateExceptionHandlingTest.java b/hibernate-core/src/test/java/org/hibernate/test/exceptionhandling/StateObjectStateExceptionHandlingTest.java new file mode 100644 index 0000000000..7bd418d9ac --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/exceptionhandling/StateObjectStateExceptionHandlingTest.java @@ -0,0 +1,117 @@ +/* + * 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 . + */ +package org.hibernate.test.exceptionhandling; + +import static org.junit.Assert.fail; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Version; + +import org.hibernate.Session; +import org.hibernate.testing.TestForIssue; +import org.junit.Test; + +@TestForIssue(jiraKey = "HHH-12666") +public class StateObjectStateExceptionHandlingTest extends BaseExceptionHandlingTest { + + public StateObjectStateExceptionHandlingTest( + BootstrapMethod bootstrapMethod, + ExceptionHandlingSetting exceptionHandlingSetting, + ExceptionExpectations exceptionExpectations) { + super( bootstrapMethod, exceptionHandlingSetting, exceptionExpectations ); + } + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { + A.class + }; + } + + @Test + public void testStaleObjectMerged() { + Session s = openSession(); + s.beginTransaction(); + A a = new A(); + a.id = 1; + s.persist( a ); + s.getTransaction().commit(); + s.close(); + + s = openSession(); + s.beginTransaction(); + A aGet = s.get( A.class, a.id ); + aGet.name = "A. Name"; + s.getTransaction().commit(); + s.close(); + + a.name = "Another Name"; + + s = openSession(); + s.beginTransaction(); + try { + s.merge( a ); + fail( "should have thrown an exception" ); + } + catch (RuntimeException expected) { + exceptionExpectations.onStaleObjectMergeAndUpdateFlush( expected ); + } + finally { + s.getTransaction().rollback(); + s.close(); + } + } + + @Test + public void testStaleObjectUpdatedAndFlushed() { + Session s = openSession(); + s.beginTransaction(); + A a = new A(); + a.id = 2; + s.persist( a ); + s.getTransaction().commit(); + s.close(); + + s = openSession(); + s.beginTransaction(); + A aGet = s.get( A.class, a.id ); + aGet.name = "A. Name"; + s.getTransaction().commit(); + s.close(); + + a.name = "Another Name"; + + s = openSession(); + s.beginTransaction(); + try { + s.update( a ); + s.flush(); + fail( "should have thrown an exception" ); + } + catch (RuntimeException expected) { + exceptionExpectations.onStaleObjectMergeAndUpdateFlush( expected ); + } + finally { + s.getTransaction().rollback(); + s.close(); + } + } + + @Entity(name = "A") + public static class A { + @Id + private long id; + + private String name; + + @Version + @Column(name = "ver") + private int version; + } +}