BAEL-2088 Common Hibernate Exceptions
Commin Hibernate Exceptions unit tests
This commit is contained in:
		
							parent
							
								
									262d2efb7b
								
							
						
					
					
						commit
						dcc1cd3850
					
				| @ -0,0 +1,16 @@ | ||||
| package com.baeldung.hibernate.exception; | ||||
| 
 | ||||
| import javax.persistence.Entity; | ||||
| 
 | ||||
| @Entity | ||||
| public class EntityWithNoId { | ||||
|     private int id; | ||||
| 
 | ||||
|     public int getId() { | ||||
|         return id; | ||||
|     } | ||||
| 
 | ||||
|     public void setId(int id) { | ||||
|         this.id = id; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,63 @@ | ||||
| package com.baeldung.hibernate.exception; | ||||
| 
 | ||||
| import java.io.FileInputStream; | ||||
| import java.io.IOException; | ||||
| import java.net.URL; | ||||
| import java.util.Properties; | ||||
| 
 | ||||
| import org.apache.commons.lang3.StringUtils; | ||||
| import org.hibernate.SessionFactory; | ||||
| import org.hibernate.boot.Metadata; | ||||
| import org.hibernate.boot.MetadataSources; | ||||
| import org.hibernate.boot.registry.StandardServiceRegistryBuilder; | ||||
| import org.hibernate.service.ServiceRegistry; | ||||
| 
 | ||||
| public class HibernateUtil { | ||||
|     private static SessionFactory sessionFactory; | ||||
|     private static String PROPERTY_FILE_NAME; | ||||
| 
 | ||||
|     public static SessionFactory getSessionFactory() throws IOException { | ||||
|         return getSessionFactory(null); | ||||
|     } | ||||
| 
 | ||||
|     public static SessionFactory getSessionFactory(String propertyFileName) | ||||
|         throws IOException { | ||||
|         PROPERTY_FILE_NAME = propertyFileName; | ||||
|         if (sessionFactory == null) { | ||||
|             ServiceRegistry serviceRegistry = configureServiceRegistry(); | ||||
|             sessionFactory = makeSessionFactory(serviceRegistry); | ||||
|         } | ||||
|         return sessionFactory; | ||||
|     } | ||||
| 
 | ||||
|     private static SessionFactory makeSessionFactory( | ||||
|         ServiceRegistry serviceRegistry) { | ||||
|         MetadataSources metadataSources = new MetadataSources(serviceRegistry); | ||||
|         metadataSources.addAnnotatedClass(Product.class); | ||||
|         Metadata metadata = metadataSources.getMetadataBuilder() | ||||
|             .build(); | ||||
|         return metadata.getSessionFactoryBuilder() | ||||
|             .build(); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     private static ServiceRegistry configureServiceRegistry() | ||||
|         throws IOException { | ||||
|         Properties properties = getProperties(); | ||||
|         return new StandardServiceRegistryBuilder().applySettings(properties) | ||||
|             .build(); | ||||
|     } | ||||
| 
 | ||||
|     private static Properties getProperties() throws IOException { | ||||
|         Properties properties = new Properties(); | ||||
|         URL propertiesURL = Thread.currentThread() | ||||
|             .getContextClassLoader() | ||||
|             .getResource(StringUtils.defaultString(PROPERTY_FILE_NAME, | ||||
|                 "hibernate-exception.properties")); | ||||
|         try (FileInputStream inputStream = new FileInputStream( | ||||
|             propertiesURL.getFile())) { | ||||
|             properties.load(inputStream); | ||||
|         } | ||||
|         return properties; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,40 @@ | ||||
| package com.baeldung.hibernate.exception; | ||||
| 
 | ||||
| import javax.persistence.Column; | ||||
| import javax.persistence.Entity; | ||||
| import javax.persistence.Id; | ||||
| 
 | ||||
| @Entity | ||||
| public class Product { | ||||
| 
 | ||||
|     private int id; | ||||
|      | ||||
|     private String name; | ||||
|     private String description; | ||||
| 
 | ||||
|     @Id | ||||
|     public int getId() { | ||||
|         return id; | ||||
|     } | ||||
| 
 | ||||
|     public void setId(int id) { | ||||
|         this.id = id; | ||||
|     } | ||||
|      | ||||
|     @Column(nullable=false) | ||||
|     public String getName() { | ||||
|         return name; | ||||
|     } | ||||
| 
 | ||||
|     public void setName(String name) { | ||||
|         this.name = name; | ||||
|     } | ||||
| 
 | ||||
|     public String getDescription() { | ||||
|         return description; | ||||
|     } | ||||
| 
 | ||||
|     public void setDescription(String description) { | ||||
|         this.description = description; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,425 @@ | ||||
| package com.baeldung.hibernate.exception; | ||||
| 
 | ||||
| import static org.hamcrest.CoreMatchers.isA; | ||||
| import static org.junit.Assert.assertNotNull; | ||||
| 
 | ||||
| import java.io.IOException; | ||||
| import java.util.List; | ||||
| 
 | ||||
| import javax.persistence.OptimisticLockException; | ||||
| import javax.persistence.PersistenceException; | ||||
| 
 | ||||
| import org.hibernate.AnnotationException; | ||||
| import org.hibernate.HibernateException; | ||||
| import org.hibernate.MappingException; | ||||
| import org.hibernate.NonUniqueObjectException; | ||||
| import org.hibernate.PropertyValueException; | ||||
| import org.hibernate.Session; | ||||
| import org.hibernate.SessionFactory; | ||||
| import org.hibernate.StaleObjectStateException; | ||||
| import org.hibernate.StaleStateException; | ||||
| import org.hibernate.Transaction; | ||||
| import org.hibernate.TransactionException; | ||||
| import org.hibernate.cfg.AvailableSettings; | ||||
| import org.hibernate.cfg.Configuration; | ||||
| import org.hibernate.exception.ConstraintViolationException; | ||||
| import org.hibernate.exception.DataException; | ||||
| import org.hibernate.exception.SQLGrammarException; | ||||
| import org.hibernate.query.NativeQuery; | ||||
| import org.hibernate.tool.schema.spi.CommandAcceptanceException; | ||||
| import org.hibernate.tool.schema.spi.SchemaManagementException; | ||||
| import org.junit.Before; | ||||
| import org.junit.Rule; | ||||
| import org.junit.Test; | ||||
| import org.junit.rules.ExpectedException; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
| 
 | ||||
| public class HibernateExceptionUnitTest { | ||||
| 
 | ||||
|     private static final Logger logger = LoggerFactory | ||||
|         .getLogger(HibernateExceptionUnitTest.class); | ||||
|     private SessionFactory sessionFactory; | ||||
| 
 | ||||
|     @Before | ||||
|     public void setUp() throws IOException { | ||||
|         sessionFactory = HibernateUtil.getSessionFactory(); | ||||
|     } | ||||
| 
 | ||||
|     @Rule | ||||
|     public ExpectedException thrown = ExpectedException.none(); | ||||
| 
 | ||||
|     private Configuration getConfiguration() { | ||||
|         Configuration cfg = new Configuration(); | ||||
|         cfg.setProperty(AvailableSettings.DIALECT, | ||||
|             "org.hibernate.dialect.H2Dialect"); | ||||
|         cfg.setProperty(AvailableSettings.HBM2DDL_AUTO, "none"); | ||||
|         cfg.setProperty(AvailableSettings.DRIVER, "org.h2.Driver"); | ||||
|         cfg.setProperty(AvailableSettings.URL, | ||||
|             "jdbc:h2:mem:myexceptiondb2;DB_CLOSE_DELAY=-1"); | ||||
|         cfg.setProperty(AvailableSettings.USER, "sa"); | ||||
|         cfg.setProperty(AvailableSettings.PASS, ""); | ||||
|         return cfg; | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void whenQueryExecutedWithUnmappedEntity_thenMappingException() { | ||||
|         thrown.expectCause(isA(MappingException.class)); | ||||
|         thrown.expectMessage("Unknown entity: java.lang.String"); | ||||
| 
 | ||||
|         Session session = sessionFactory.openSession(); | ||||
|         NativeQuery<String> query = session | ||||
|             .createNativeQuery("select name from PRODUCT", String.class); | ||||
|         query.getResultList(); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     @SuppressWarnings("rawtypes") | ||||
|     public void whenQueryExecuted_thenOK() { | ||||
|         Session session = sessionFactory.openSession(); | ||||
|         NativeQuery query = session | ||||
|             .createNativeQuery("select name from PRODUCT"); | ||||
|         List results = query.getResultList(); | ||||
|         assertNotNull(results); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void givenEntityWithoutId_whenSessionFactoryCreated_thenAnnotationException() { | ||||
|         thrown.expect(AnnotationException.class); | ||||
|         thrown.expectMessage("No identifier specified for entity"); | ||||
| 
 | ||||
|         Configuration cfg = getConfiguration(); | ||||
|         cfg.addAnnotatedClass(EntityWithNoId.class); | ||||
|         cfg.buildSessionFactory(); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void givenMissingTable_whenSchemaValidated_thenSchemaManagementException() { | ||||
|         thrown.expect(SchemaManagementException.class); | ||||
|         thrown.expectMessage("Schema-validation: missing table"); | ||||
| 
 | ||||
|         Configuration cfg = getConfiguration(); | ||||
|         cfg.setProperty(AvailableSettings.HBM2DDL_AUTO, "validate"); | ||||
|         cfg.addAnnotatedClass(Product.class); | ||||
|         cfg.buildSessionFactory(); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void whenWrongDialectSpecified_thenCommandAcceptanceException() { | ||||
|         thrown.expect(SchemaManagementException.class); | ||||
|         thrown.expectCause(isA(CommandAcceptanceException.class)); | ||||
|         thrown.expectMessage("Halting on error : Error executing DDL"); | ||||
| 
 | ||||
|         Configuration cfg = getConfiguration(); | ||||
|         cfg.setProperty(AvailableSettings.DIALECT, | ||||
|             "org.hibernate.dialect.MySQLDialect"); | ||||
|         cfg.setProperty(AvailableSettings.HBM2DDL_AUTO, "update"); | ||||
| 
 | ||||
|         // This does not work due to hibernate bug | ||||
|         // cfg.setProperty(AvailableSettings.HBM2DDL_HALT_ON_ERROR,"true"); | ||||
|         cfg.getProperties() | ||||
|             .put(AvailableSettings.HBM2DDL_HALT_ON_ERROR, true); | ||||
| 
 | ||||
|         cfg.addAnnotatedClass(Product.class); | ||||
|         cfg.buildSessionFactory(); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void givenMissingTable_whenEntitySaved_thenSQLGrammarException() { | ||||
|         thrown.expect(isA(PersistenceException.class)); | ||||
|         thrown.expectCause(isA(SQLGrammarException.class)); | ||||
|         thrown | ||||
|             .expectMessage("SQLGrammarException: could not prepare statement"); | ||||
| 
 | ||||
|         Configuration cfg = getConfiguration(); | ||||
|         cfg.addAnnotatedClass(Product.class); | ||||
| 
 | ||||
|         SessionFactory sessionFactory = cfg.buildSessionFactory(); | ||||
|         Session session = null; | ||||
|         Transaction transaction = null; | ||||
|         try { | ||||
| 
 | ||||
|             session = sessionFactory.openSession(); | ||||
|             transaction = session.beginTransaction(); | ||||
|             Product product = new Product(); | ||||
|             product.setId(1); | ||||
|             product.setName("Product 1"); | ||||
|             session.save(product); | ||||
|             transaction.commit(); | ||||
|         } catch (Exception e) { | ||||
|             rollbackTransactionQuietly(transaction); | ||||
|             throw (e); | ||||
|         } finally { | ||||
|             closeSessionQuietly(session); | ||||
|             closeSessionFactoryQuietly(sessionFactory); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void givenMissingTable_whenQueryExecuted_thenSQLGrammarException() { | ||||
|         thrown.expect(isA(PersistenceException.class)); | ||||
|         thrown.expectCause(isA(SQLGrammarException.class)); | ||||
|         thrown | ||||
|             .expectMessage("SQLGrammarException: could not prepare statement"); | ||||
| 
 | ||||
|         Session session = sessionFactory.openSession(); | ||||
|         NativeQuery<Product> query = session.createNativeQuery( | ||||
|             "select * from NON_EXISTING_TABLE", Product.class); | ||||
|         query.getResultList(); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void whenDuplicateIdSaved_thenConstraintViolationException() { | ||||
|         thrown.expect(isA(PersistenceException.class)); | ||||
|         thrown.expectCause(isA(ConstraintViolationException.class)); | ||||
|         thrown.expectMessage( | ||||
|             "ConstraintViolationException: could not execute statement"); | ||||
| 
 | ||||
|         Session session = null; | ||||
|         Transaction transaction = null; | ||||
| 
 | ||||
|         for (int i = 1; i <= 2; i++) { | ||||
|             try { | ||||
|                 session = sessionFactory.openSession(); | ||||
|                 transaction = session.beginTransaction(); | ||||
|                 Product product = new Product(); | ||||
|                 product.setId(1); | ||||
|                 product.setName("Product " + i); | ||||
|                 session.save(product); | ||||
|                 transaction.commit(); | ||||
|             } catch (Exception e) { | ||||
|                 rollbackTransactionQuietly(transaction); | ||||
|                 throw (e); | ||||
|             } finally { | ||||
|                 closeSessionQuietly(session); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void givenNotNullPropertyNotSet_whenEntityIdSaved_thenPropertyValueException() { | ||||
|         thrown.expect(isA(PropertyValueException.class)); | ||||
|         thrown.expectMessage( | ||||
|             "not-null property references a null or transient value"); | ||||
| 
 | ||||
|         Session session = null; | ||||
|         Transaction transaction = null; | ||||
| 
 | ||||
|         try { | ||||
|             session = sessionFactory.openSession(); | ||||
|             transaction = session.beginTransaction(); | ||||
| 
 | ||||
|             Product product = new Product(); | ||||
|             product.setId(1); | ||||
|             session.save(product); | ||||
|             transaction.commit(); | ||||
|         } catch (Exception e) { | ||||
|             rollbackTransactionQuietly(transaction); | ||||
|             throw (e); | ||||
|         } finally { | ||||
|             closeSessionQuietly(session); | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void givenQueryWithDataTypeMismatch_WhenQueryExecuted_thenDataException() { | ||||
|         thrown.expectCause(isA(DataException.class)); | ||||
|         thrown.expectMessage( | ||||
|             "org.hibernate.exception.DataException: could not prepare statement"); | ||||
| 
 | ||||
|         Session session = sessionFactory.openSession(); | ||||
|         NativeQuery<Product> query = session.createNativeQuery( | ||||
|             "select * from PRODUCT where id='wrongTypeId'", Product.class); | ||||
|         query.getResultList(); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void givenSessionContainingAnId_whenIdAssociatedAgain_thenNonUniqueObjectException() { | ||||
|         thrown.expect(isA(NonUniqueObjectException.class)); | ||||
|         thrown.expectMessage( | ||||
|             "A different object with the same identifier value was already associated with the session"); | ||||
| 
 | ||||
|         Session session = null; | ||||
|         Transaction transaction = null; | ||||
| 
 | ||||
|         try { | ||||
|             session = sessionFactory.openSession(); | ||||
|             transaction = session.beginTransaction(); | ||||
| 
 | ||||
|             Product product1 = new Product(); | ||||
|             product1.setId(1); | ||||
|             product1.setName("Product 1"); | ||||
|             session.save(product1); | ||||
| 
 | ||||
|             Product product2 = new Product(); | ||||
|             product2.setId(1); | ||||
|             product2.setName("Product 2"); | ||||
|             session.save(product2); | ||||
| 
 | ||||
|             transaction.commit(); | ||||
|         } catch (Exception e) { | ||||
|             rollbackTransactionQuietly(transaction); | ||||
|             throw (e); | ||||
|         } finally { | ||||
|             closeSessionQuietly(session); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void whenDeletingADeletedObject_thenOptimisticLockException() { | ||||
|         thrown.expect(isA(OptimisticLockException.class)); | ||||
|         thrown.expectMessage( | ||||
|             "Batch update returned unexpected row count from update"); | ||||
|         thrown.expectCause(isA(StaleStateException.class)); | ||||
| 
 | ||||
|         Session session = null; | ||||
|         Transaction transaction = null; | ||||
| 
 | ||||
|         try { | ||||
|             session = sessionFactory.openSession(); | ||||
|             transaction = session.beginTransaction(); | ||||
| 
 | ||||
|             Product product1 = new Product(); | ||||
|             product1.setId(12); | ||||
|             product1.setName("Product 12"); | ||||
|             session.save(product1); | ||||
|             transaction.commit(); | ||||
|             session.close(); | ||||
| 
 | ||||
|             session = sessionFactory.openSession(); | ||||
|             transaction = session.beginTransaction(); | ||||
|             Product product2 = session.get(Product.class, 12); | ||||
|             session.createNativeQuery("delete from Product where id=12") | ||||
|                 .executeUpdate(); | ||||
|             // We need to refresh to fix the error. | ||||
|             // session.refresh(product2); | ||||
|             session.delete(product2); | ||||
|             transaction.commit(); | ||||
|         } catch (Exception e) { | ||||
|             rollbackTransactionQuietly(transaction); | ||||
|             throw (e); | ||||
|         } finally { | ||||
|             closeSessionQuietly(session); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void whenUpdatingNonExistingObject_thenStaleStateException() { | ||||
|         thrown.expect(isA(OptimisticLockException.class)); | ||||
|         thrown | ||||
|             .expectMessage("Row was updated or deleted by another transaction"); | ||||
|         thrown.expectCause(isA(StaleObjectStateException.class)); | ||||
| 
 | ||||
|         Session session = null; | ||||
|         Transaction transaction = null; | ||||
| 
 | ||||
|         try { | ||||
|             session = sessionFactory.openSession(); | ||||
|             transaction = session.beginTransaction(); | ||||
| 
 | ||||
|             Product product1 = new Product(); | ||||
|             product1.setId(15); | ||||
|             product1.setName("Product1"); | ||||
|             session.update(product1); | ||||
|             transaction.commit(); | ||||
|         } catch (Exception e) { | ||||
|             rollbackTransactionQuietly(transaction); | ||||
|             throw (e); | ||||
|         } finally { | ||||
|             closeSessionQuietly(session); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void givenTxnMarkedRollbackOnly_whenCommitted_thenTransactionException() { | ||||
|         thrown.expect(isA(TransactionException.class)); | ||||
| 
 | ||||
|         Session session = null; | ||||
|         Transaction transaction = null; | ||||
|         try { | ||||
|             session = sessionFactory.openSession(); | ||||
|             transaction = session.beginTransaction(); | ||||
| 
 | ||||
|             Product product1 = new Product(); | ||||
|             product1.setId(15); | ||||
|             product1.setName("Product1"); | ||||
|             session.save(product1); | ||||
|             transaction.setRollbackOnly(); | ||||
| 
 | ||||
|             transaction.commit(); | ||||
|         } catch (Exception e) { | ||||
|             rollbackTransactionQuietly(transaction); | ||||
|             throw (e); | ||||
|         } finally { | ||||
|             closeSessionQuietly(session); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private void rollbackTransactionQuietly(Transaction transaction) { | ||||
|         if (transaction != null && transaction.isActive()) { | ||||
|             try { | ||||
|                 transaction.rollback(); | ||||
|             } catch (Exception e) { | ||||
|                 logger.error("Exception while rolling back transaction", e); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private void closeSessionQuietly(Session session) { | ||||
|         if (session != null) { | ||||
|             try { | ||||
|                 session.close(); | ||||
|             } catch (Exception e) { | ||||
|                 logger.error("Exception while closing session", e); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private void closeSessionFactoryQuietly(SessionFactory sessionFactory) { | ||||
|         if (sessionFactory != null) { | ||||
|             try { | ||||
|                 sessionFactory.close(); | ||||
|             } catch (Exception e) { | ||||
|                 logger.error("Exception while closing sessionFactory", e); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void givenExistingEntity_whenIdUpdated_thenHibernateException() { | ||||
|         thrown.expect(isA(PersistenceException.class)); | ||||
|         thrown.expectCause(isA(HibernateException.class)); | ||||
|         thrown.expectMessage( | ||||
|             "identifier of an instance of com.baeldung.hibernate.exception.Product was altered"); | ||||
| 
 | ||||
|         Session session = null; | ||||
|         Transaction transaction = null; | ||||
| 
 | ||||
|         try { | ||||
|             session = sessionFactory.openSession(); | ||||
|             transaction = session.beginTransaction(); | ||||
| 
 | ||||
|             Product product1 = new Product(); | ||||
|             product1.setId(222); | ||||
|             product1.setName("Product 222"); | ||||
|             session.save(product1); | ||||
|             transaction.commit(); | ||||
|             closeSessionQuietly(session); | ||||
| 
 | ||||
|             session = sessionFactory.openSession(); | ||||
|             transaction = session.beginTransaction(); | ||||
| 
 | ||||
|             Product product2 = session.get(Product.class, 222); | ||||
|             product2.setId(333); | ||||
|             session.save(product2); | ||||
| 
 | ||||
|             transaction.commit(); | ||||
|         } catch (Exception e) { | ||||
|             rollbackTransactionQuietly(transaction); | ||||
|             throw (e); | ||||
|         } finally { | ||||
|             closeSessionQuietly(session); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,16 @@ | ||||
| hibernate.connection.driver_class=org.h2.Driver | ||||
| hibernate.connection.url=jdbc:h2:mem:myexceptiondb1;DB_CLOSE_DELAY=-1 | ||||
| hibernate.connection.username=sa | ||||
| hibernate.connection.autocommit=true | ||||
| jdbc.password= | ||||
| 
 | ||||
| hibernate.dialect=org.hibernate.dialect.H2Dialect | ||||
| hibernate.show_sql=true | ||||
| hibernate.hbm2ddl.auto=create-drop | ||||
| 
 | ||||
| hibernate.c3p0.min_size=5 | ||||
| hibernate.c3p0.max_size=20 | ||||
| hibernate.c3p0.acquire_increment=5 | ||||
| hibernate.c3p0.timeout=1800 | ||||
| 
 | ||||
| hibernate.transaction.factory_class=org.hibernate.transaction.JTATransactionFactory | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user