"An Intro to Hibernate Entity Lifecycle"
"An Intro to Hibernate Entity Lifecycle" by Rudi
This commit is contained in:
		
							parent
							
								
									99676b1a9e
								
							
						
					
					
						commit
						413c02c078
					
				| @ -0,0 +1,26 @@ | ||||
| package com.baeldung.hibernate.lifecycle; | ||||
| 
 | ||||
| import org.hibernate.EmptyInterceptor; | ||||
| import org.hibernate.type.Type; | ||||
| 
 | ||||
| import java.io.Serializable; | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| 
 | ||||
| public class DirtyDataInspector extends EmptyInterceptor { | ||||
|     private static final ArrayList<FootballPlayer> dirtyEntities = new ArrayList<>(); | ||||
| 
 | ||||
|     @Override | ||||
|     public boolean onFlushDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState, String[] propertyNames, Type[] types) { | ||||
|         dirtyEntities.add((FootballPlayer) entity); | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     public static List<FootballPlayer> getDirtyEntities() { | ||||
|         return dirtyEntities; | ||||
|     } | ||||
| 
 | ||||
|     public static void clearDirtyEntitites() { | ||||
|         dirtyEntities.clear(); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,41 @@ | ||||
| package com.baeldung.hibernate.lifecycle; | ||||
| 
 | ||||
| import javax.persistence.*; | ||||
| 
 | ||||
| @Entity | ||||
| @Table(name = "Football_Player") | ||||
| public class FootballPlayer { | ||||
|     @Id @GeneratedValue private long id; | ||||
| 
 | ||||
|     @Column private String name; | ||||
| 
 | ||||
|     @Column private String team; | ||||
| 
 | ||||
|     public long getId() { | ||||
|         return id; | ||||
|     } | ||||
| 
 | ||||
|     public void setId(long id) { | ||||
|         this.id = id; | ||||
|     } | ||||
| 
 | ||||
|     public String getName() { | ||||
|         return name; | ||||
|     } | ||||
| 
 | ||||
|     public void setName(String name) { | ||||
|         this.name = name; | ||||
|     } | ||||
| 
 | ||||
|     public String getTeam() { | ||||
|         return team; | ||||
|     } | ||||
| 
 | ||||
|     public void setTeam(String team) { | ||||
|         this.team = team; | ||||
|     } | ||||
| 
 | ||||
|     @Override public String toString() { | ||||
|         return "FootballPlayer{" + "id=" + id + ", name='" + name + '\'' + ", team='" + team + '\'' + '}'; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,100 @@ | ||||
| package com.baeldung.hibernate.lifecycle; | ||||
| 
 | ||||
| import org.h2.tools.RunScript; | ||||
| import org.hibernate.Session; | ||||
| import org.hibernate.SessionFactory; | ||||
| import org.hibernate.Transaction; | ||||
| import org.hibernate.boot.Metadata; | ||||
| import org.hibernate.boot.MetadataSources; | ||||
| import org.hibernate.boot.SessionFactoryBuilder; | ||||
| import org.hibernate.boot.registry.StandardServiceRegistryBuilder; | ||||
| import org.hibernate.engine.spi.EntityEntry; | ||||
| import org.hibernate.engine.spi.SessionImplementor; | ||||
| import org.hibernate.service.ServiceRegistry; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.io.FileInputStream; | ||||
| import java.io.FileReader; | ||||
| import java.io.IOException; | ||||
| import java.net.URL; | ||||
| import java.sql.Connection; | ||||
| import java.sql.DriverManager; | ||||
| import java.sql.ResultSet; | ||||
| import java.util.Arrays; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| import java.util.Properties; | ||||
| import java.util.stream.Collectors; | ||||
| 
 | ||||
| public class HibernateUtil { | ||||
|     private static SessionFactory sessionFactory; | ||||
|     private static Connection connection; | ||||
| 
 | ||||
|     public static void init() throws Exception { | ||||
|         Connection dbConnection = null; | ||||
|         Class.forName("org.h2.Driver"); | ||||
| 
 | ||||
|         connection = connection = DriverManager.getConnection("jdbc:h2:mem:lifecycledb;DB_CLOSE_DELAY=-1;", "sa", ""); | ||||
|         File initFile = new File("src/test/resources/lifecycle-init.sql"); | ||||
|         try(FileReader reader = new FileReader(initFile);) { | ||||
|             RunScript.execute(connection, reader); | ||||
|         } | ||||
| 
 | ||||
|         ServiceRegistry serviceRegistry = configureServiceRegistry(); | ||||
|         sessionFactory = getSessionFactoryBuilder(serviceRegistry).applyInterceptor(new DirtyDataInspector()).build(); | ||||
|     } | ||||
| 
 | ||||
|     public static void tearDown() throws Exception { | ||||
|         sessionFactory.close(); | ||||
|         connection.close(); | ||||
|     } | ||||
| 
 | ||||
|     public static SessionFactory getSessionFactory() { | ||||
|         return sessionFactory; | ||||
|     } | ||||
| 
 | ||||
|     private static SessionFactoryBuilder getSessionFactoryBuilder(ServiceRegistry serviceRegistry) { | ||||
|         MetadataSources metadataSources = new MetadataSources(serviceRegistry); | ||||
|         metadataSources.addAnnotatedClass(FootballPlayer.class); | ||||
| 
 | ||||
|         Metadata metadata = metadataSources.buildMetadata(); | ||||
|         return metadata.getSessionFactoryBuilder(); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     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("hibernate-lifecycle.properties"); | ||||
|         try (FileInputStream inputStream = new FileInputStream(propertiesURL.getFile())) { | ||||
|             properties.load(inputStream); | ||||
|         } | ||||
|         return properties; | ||||
|     } | ||||
| 
 | ||||
|     public static List<EntityEntry> getManagedEntities(Session session) { | ||||
|         Map.Entry<Object, EntityEntry>[] entries = ((SessionImplementor)session).getPersistenceContext().reentrantSafeEntityEntries(); | ||||
|         return Arrays.asList(entries).stream().map(e -> e.getValue()).collect(Collectors.toList()); | ||||
|     } | ||||
| 
 | ||||
|     public static Connection getDBConnection() throws Exception { | ||||
|         return connection; | ||||
|     } | ||||
| 
 | ||||
|     public static Transaction startTransaction(Session s) { | ||||
|         Transaction tx = s.getTransaction(); | ||||
|         tx.begin(); | ||||
|         return tx; | ||||
|     } | ||||
| 
 | ||||
|     public static int queryCount(String query) throws Exception { | ||||
|         try(ResultSet rs = connection.createStatement().executeQuery(query);) { | ||||
|             rs.next(); | ||||
|             return rs.getInt(1); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,166 @@ | ||||
| package com.baeldung.hibernate.lifecycle; | ||||
| 
 | ||||
| import org.hibernate.Session; | ||||
| import org.hibernate.SessionFactory; | ||||
| import org.hibernate.Transaction; | ||||
| import org.hibernate.engine.spi.Status; | ||||
| import org.junit.AfterClass; | ||||
| import org.junit.Before; | ||||
| import org.junit.BeforeClass; | ||||
| import org.junit.Test; | ||||
| 
 | ||||
| import java.util.List; | ||||
| 
 | ||||
| import static com.baeldung.hibernate.lifecycle.DirtyDataInspector.getDirtyEntities; | ||||
| import static com.baeldung.hibernate.lifecycle.HibernateUtil.*; | ||||
| import static org.assertj.core.api.Assertions.assertThat; | ||||
| 
 | ||||
| public class HibernateLifecycleUnitTest { | ||||
| 
 | ||||
|     @BeforeClass | ||||
|     public static void setup() throws Exception { | ||||
|         HibernateUtil.init(); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     @AfterClass | ||||
|     public static void tearDown() throws Exception { | ||||
|         HibernateUtil.tearDown(); | ||||
|     } | ||||
| 
 | ||||
|     @Before | ||||
|     public void beforeMethod() { | ||||
|         DirtyDataInspector.clearDirtyEntitites(); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void whenEntityLoaded_thenEntityManaged() throws Exception { | ||||
|         SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); | ||||
|         try(Session session = sessionFactory.openSession()) { | ||||
|             Transaction transaction = startTransaction(session); | ||||
| 
 | ||||
|             assertThat(getManagedEntities(session)).isEmpty(); | ||||
| 
 | ||||
|             List<FootballPlayer> players = session.createQuery("from FootballPlayer").getResultList(); | ||||
|             assertThat(getManagedEntities(session)).size().isEqualTo(3); | ||||
| 
 | ||||
|             assertThat(getDirtyEntities()).isEmpty(); | ||||
| 
 | ||||
|             FootballPlayer gigiBuffon = players.stream() | ||||
|                                         .filter(p -> p.getId()==3) | ||||
|                                         .findFirst() | ||||
|                                         .get(); | ||||
| 
 | ||||
|             gigiBuffon.setName("Gianluigi Buffon"); | ||||
|             transaction.commit(); | ||||
| 
 | ||||
|             assertThat(getDirtyEntities()).size().isEqualTo(1); | ||||
|             assertThat(getDirtyEntities().get(0).getId()).isEqualTo(3); | ||||
|             assertThat(getDirtyEntities().get(0).getName()).isEqualTo("Gianluigi Buffon"); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void whenDetached_thenNotTracked() throws Exception { | ||||
|         SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); | ||||
|         try(Session session = sessionFactory.openSession()) { | ||||
|             Transaction transaction = startTransaction(session); | ||||
| 
 | ||||
|             FootballPlayer cr7 = session.get(FootballPlayer.class, Long.valueOf(1)); | ||||
|             assertThat(getManagedEntities(session)).size().isEqualTo(1); | ||||
|             assertThat(getManagedEntities(session).get(0).getId()).isEqualTo(cr7.getId()); | ||||
| 
 | ||||
|             session.evict(cr7); | ||||
|             assertThat(getManagedEntities(session)).size().isEqualTo(0); | ||||
| 
 | ||||
|             cr7.setName("CR7"); | ||||
|             transaction.commit(); | ||||
| 
 | ||||
|             assertThat(getDirtyEntities()).isEmpty(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void whenReattached_thenTrackedAgain() throws Exception { | ||||
|         SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); | ||||
|         try(Session session = sessionFactory.openSession()) { | ||||
|             Transaction transaction = startTransaction(session); | ||||
| 
 | ||||
|             FootballPlayer messi = session.get(FootballPlayer.class, Long.valueOf(2)); | ||||
| 
 | ||||
|             session.evict(messi); | ||||
|             messi.setName("Leo Messi"); | ||||
|             transaction.commit(); | ||||
|             assertThat(getDirtyEntities()).isEmpty(); | ||||
| 
 | ||||
|             transaction = startTransaction(session); | ||||
|             session.update(messi); | ||||
|             transaction.commit(); | ||||
|             assertThat(getDirtyEntities()).size().isEqualTo(1); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void givenNewEntityWithID_whenReattached_thenManaged() throws Exception { | ||||
|         SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); | ||||
|         try (Session session = sessionFactory.openSession()) { | ||||
|             Transaction transaction = startTransaction(session); | ||||
| 
 | ||||
|             FootballPlayer gigi = new FootballPlayer(); | ||||
|             gigi.setId(3); | ||||
|             gigi.setName("Gigi the Legend"); | ||||
| 
 | ||||
|             session.update(gigi); | ||||
|             assertThat(getManagedEntities(session)).size().isEqualTo(1); | ||||
| 
 | ||||
|             transaction.commit(); | ||||
|             assertThat(getDirtyEntities()).size().isEqualTo(1); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void givenTransientEntity_whenSave_thenManaged() throws Exception { | ||||
|         SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); | ||||
|         try (Session session = sessionFactory.openSession()) { | ||||
|             Transaction transaction = startTransaction(session); | ||||
| 
 | ||||
|             FootballPlayer neymar = new FootballPlayer(); | ||||
|             neymar.setName("Neymar"); | ||||
| 
 | ||||
|             session.save(neymar); | ||||
|             assertThat(getManagedEntities(session)).size().isEqualTo(1); | ||||
|             assertThat(neymar.getId()).isNotNull(); | ||||
| 
 | ||||
|             int count = queryCount("select count(*) from Football_Player where name='Neymar'"); | ||||
|             assertThat(count).isEqualTo(0); | ||||
| 
 | ||||
|             transaction.commit(); | ||||
| 
 | ||||
|             count = queryCount("select count(*) from Football_Player where name='Neymar'"); | ||||
|             assertThat(count).isEqualTo(1); | ||||
| 
 | ||||
|             transaction = startTransaction(session); | ||||
|             session.delete(neymar); | ||||
|             transaction.commit(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Test() | ||||
|     public void whenDelete_thenMarkDeleted() throws Exception { | ||||
|         SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); | ||||
|         try (Session session = sessionFactory.openSession()) { | ||||
|             Transaction transaction = startTransaction(session); | ||||
| 
 | ||||
|             FootballPlayer neymar = new FootballPlayer(); | ||||
|             neymar.setName("Neymar"); | ||||
| 
 | ||||
|             session.save(neymar); | ||||
|             transaction.commit(); | ||||
| 
 | ||||
|             transaction = startTransaction(session); | ||||
|             session.delete(neymar); | ||||
|             assertThat(getManagedEntities(session).get(0).getStatus()).isEqualTo(Status.DELETED); | ||||
|             transaction.commit(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,9 @@ | ||||
| hibernate.connection.driver_class=org.h2.Driver | ||||
| hibernate.connection.url=jdbc:h2:mem:lifecycledb;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=validate | ||||
							
								
								
									
										26
									
								
								hibernate5/src/test/resources/lifecycle-init.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								hibernate5/src/test/resources/lifecycle-init.sql
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,26 @@ | ||||
| create sequence hibernate_sequence start with 1 increment by 1; | ||||
| 
 | ||||
| create table Football_Player ( | ||||
|   id bigint not null, | ||||
|   team varchar(255), | ||||
|   name varchar(255), | ||||
|   primary key (id) | ||||
| ); | ||||
| 
 | ||||
| insert into | ||||
|     Football_Player | ||||
|         (team, name, id) | ||||
|     values | ||||
|         ('Juventus', 'Cristiano Ronaldo', next value for hibernate_sequence); | ||||
| 
 | ||||
| insert into | ||||
|     Football_Player | ||||
|         (team, name, id) | ||||
|     values | ||||
|         ('Barcelona', 'Lionel Messi', next value for hibernate_sequence); | ||||
| 
 | ||||
| insert into | ||||
|     Football_Player | ||||
|         (team, name, id) | ||||
|     values | ||||
|         ('PSG', 'Gigi Buffon', next value for hibernate_sequence); | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user