diff --git a/persistence-modules/hibernate-jpa-2/pom.xml b/persistence-modules/hibernate-jpa-2/pom.xml index 0c98bd8026c9..144c0a2db479 100644 --- a/persistence-modules/hibernate-jpa-2/pom.xml +++ b/persistence-modules/hibernate-jpa-2/pom.xml @@ -80,6 +80,11 @@ postgresql ${postgresql.version} + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + diff --git a/persistence-modules/hibernate-jpa-2/src/main/java/com/baeldung/changevalue/ChangeValueApplication.java b/persistence-modules/hibernate-jpa-2/src/main/java/com/baeldung/changevalue/ChangeValueApplication.java new file mode 100644 index 000000000000..322d66692816 --- /dev/null +++ b/persistence-modules/hibernate-jpa-2/src/main/java/com/baeldung/changevalue/ChangeValueApplication.java @@ -0,0 +1,12 @@ +package com.baeldung.changevalue; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class ChangeValueApplication { + + public static void main(String[] args) { + SpringApplication.run(com.baeldung.changevalue.ChangeValueApplication.class, args); + } + +} diff --git a/persistence-modules/hibernate-jpa-2/src/main/java/com/baeldung/changevalue/entity/Person.java b/persistence-modules/hibernate-jpa-2/src/main/java/com/baeldung/changevalue/entity/Person.java new file mode 100644 index 000000000000..10f91cfcc77c --- /dev/null +++ b/persistence-modules/hibernate-jpa-2/src/main/java/com/baeldung/changevalue/entity/Person.java @@ -0,0 +1,9 @@ +package com.baeldung.changevalue.entity; + +public interface Person { + + String getName(); + + void setName(String name); + +} diff --git a/persistence-modules/hibernate-jpa-2/src/main/java/com/baeldung/changevalue/entity/Student.java b/persistence-modules/hibernate-jpa-2/src/main/java/com/baeldung/changevalue/entity/Student.java new file mode 100644 index 000000000000..9fa1a43057e5 --- /dev/null +++ b/persistence-modules/hibernate-jpa-2/src/main/java/com/baeldung/changevalue/entity/Student.java @@ -0,0 +1,46 @@ +package com.baeldung.changevalue.entity; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.PrePersist; +import jakarta.persistence.PreUpdate; +import jakarta.persistence.Table; +import org.apache.commons.lang3.StringUtils; + +@Entity +@Table(name = "student") +public class Student { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + @Column + private String name; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @PrePersist + @PreUpdate + private void changeNameToUpperCase() { + name = StringUtils.upperCase(name); + } + +} \ No newline at end of file diff --git a/persistence-modules/hibernate-jpa-2/src/main/java/com/baeldung/changevalue/entity/StudentWithColumnTransformer.java b/persistence-modules/hibernate-jpa-2/src/main/java/com/baeldung/changevalue/entity/StudentWithColumnTransformer.java new file mode 100644 index 000000000000..52d0268d6e77 --- /dev/null +++ b/persistence-modules/hibernate-jpa-2/src/main/java/com/baeldung/changevalue/entity/StudentWithColumnTransformer.java @@ -0,0 +1,39 @@ +package com.baeldung.changevalue.entity; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import org.hibernate.annotations.ColumnTransformer; + +@Entity +@Table(name = "student") +public class StudentWithColumnTransformer { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + @Column + @ColumnTransformer(write = "UPPER(?)") + private String name; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + +} \ No newline at end of file diff --git a/persistence-modules/hibernate-jpa-2/src/main/java/com/baeldung/changevalue/entity/StudentWithEventListener.java b/persistence-modules/hibernate-jpa-2/src/main/java/com/baeldung/changevalue/entity/StudentWithEventListener.java new file mode 100644 index 000000000000..26846815dbd9 --- /dev/null +++ b/persistence-modules/hibernate-jpa-2/src/main/java/com/baeldung/changevalue/entity/StudentWithEventListener.java @@ -0,0 +1,34 @@ +package com.baeldung.changevalue.entity; + +import com.baeldung.changevalue.jpa.PersonEventListener; +import jakarta.persistence.*; + +@Entity +@Table(name = "student") +@EntityListeners(PersonEventListener.class) +public class StudentWithEventListener implements Person { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + @Column + private String name; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + +} \ No newline at end of file diff --git a/persistence-modules/hibernate-jpa-2/src/main/java/com/baeldung/changevalue/entity/StudentWithHibernateEvent.java b/persistence-modules/hibernate-jpa-2/src/main/java/com/baeldung/changevalue/entity/StudentWithHibernateEvent.java new file mode 100644 index 000000000000..a84a95f88ace --- /dev/null +++ b/persistence-modules/hibernate-jpa-2/src/main/java/com/baeldung/changevalue/entity/StudentWithHibernateEvent.java @@ -0,0 +1,37 @@ +package com.baeldung.changevalue.entity; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; + +@Entity +@Table(name = "student") +public class StudentWithHibernateEvent { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + @Column + private String name; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + +} diff --git a/persistence-modules/hibernate-jpa-2/src/main/java/com/baeldung/changevalue/hibernate/HibernateEventListener.java b/persistence-modules/hibernate-jpa-2/src/main/java/com/baeldung/changevalue/hibernate/HibernateEventListener.java new file mode 100644 index 000000000000..eaa2b91b98ac --- /dev/null +++ b/persistence-modules/hibernate-jpa-2/src/main/java/com/baeldung/changevalue/hibernate/HibernateEventListener.java @@ -0,0 +1,31 @@ +package com.baeldung.changevalue.hibernate; + +import com.baeldung.changevalue.entity.StudentWithHibernateEvent; +import org.apache.commons.lang3.StringUtils; +import org.hibernate.event.spi.PreInsertEvent; +import org.hibernate.event.spi.PreInsertEventListener; +import org.hibernate.event.spi.PreUpdateEvent; +import org.hibernate.event.spi.PreUpdateEventListener; + +public class HibernateEventListener implements PreInsertEventListener, PreUpdateEventListener { + + @Override + public boolean onPreInsert(PreInsertEvent event) { + upperCaseStudentName(event.getEntity()); + return false; + } + + @Override + public boolean onPreUpdate(PreUpdateEvent event) { + upperCaseStudentName(event.getEntity()); + return false; + } + + private void upperCaseStudentName(Object entity) { + if (entity instanceof StudentWithHibernateEvent) { + StudentWithHibernateEvent student = (StudentWithHibernateEvent) entity; + student.setName(StringUtils.upperCase(student.getName())); + } + } + +} diff --git a/persistence-modules/hibernate-jpa-2/src/main/java/com/baeldung/changevalue/hibernate/HibernateEventListenerIntegrator.java b/persistence-modules/hibernate-jpa-2/src/main/java/com/baeldung/changevalue/hibernate/HibernateEventListenerIntegrator.java new file mode 100644 index 000000000000..179242a30718 --- /dev/null +++ b/persistence-modules/hibernate-jpa-2/src/main/java/com/baeldung/changevalue/hibernate/HibernateEventListenerIntegrator.java @@ -0,0 +1,27 @@ +package com.baeldung.changevalue.hibernate; + +import org.hibernate.boot.Metadata; +import org.hibernate.boot.spi.BootstrapContext; +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.event.service.spi.EventListenerRegistry; +import org.hibernate.event.spi.EventType; +import org.hibernate.integrator.spi.Integrator; +import org.hibernate.service.spi.ServiceRegistryImplementor; +import org.hibernate.service.spi.SessionFactoryServiceRegistry; + +public class HibernateEventListenerIntegrator implements Integrator { + + @Override + public void integrate(Metadata metadata, BootstrapContext bootstrapContext, SessionFactoryImplementor sessionFactoryImplementor) { + ServiceRegistryImplementor serviceRegistry = sessionFactoryImplementor.getServiceRegistry(); + EventListenerRegistry eventListenerRegistry = serviceRegistry.getService(EventListenerRegistry.class); + HibernateEventListener listener = new HibernateEventListener(); + eventListenerRegistry.appendListeners(EventType.PRE_INSERT, listener); + eventListenerRegistry.appendListeners(EventType.PRE_UPDATE, listener); + } + + @Override + public void disintegrate(SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) { + } + +} \ No newline at end of file diff --git a/persistence-modules/hibernate-jpa-2/src/main/java/com/baeldung/changevalue/hibernate/HibernateEventListenerIntegratorProvider.java b/persistence-modules/hibernate-jpa-2/src/main/java/com/baeldung/changevalue/hibernate/HibernateEventListenerIntegratorProvider.java new file mode 100644 index 000000000000..adeb14192e46 --- /dev/null +++ b/persistence-modules/hibernate-jpa-2/src/main/java/com/baeldung/changevalue/hibernate/HibernateEventListenerIntegratorProvider.java @@ -0,0 +1,14 @@ +package com.baeldung.changevalue.hibernate; + +import org.hibernate.integrator.spi.Integrator; +import org.hibernate.jpa.boot.spi.IntegratorProvider; + +import java.util.Collections; +import java.util.List; + +public class HibernateEventListenerIntegratorProvider implements IntegratorProvider { + @Override + public List getIntegrators() { + return Collections.singletonList(new HibernateEventListenerIntegrator()); + } +} \ No newline at end of file diff --git a/persistence-modules/hibernate-jpa-2/src/main/java/com/baeldung/changevalue/jpa/PersonEventListener.java b/persistence-modules/hibernate-jpa-2/src/main/java/com/baeldung/changevalue/jpa/PersonEventListener.java new file mode 100644 index 000000000000..b9861c560332 --- /dev/null +++ b/persistence-modules/hibernate-jpa-2/src/main/java/com/baeldung/changevalue/jpa/PersonEventListener.java @@ -0,0 +1,16 @@ +package com.baeldung.changevalue.jpa; + +import com.baeldung.changevalue.entity.Person; +import jakarta.persistence.PrePersist; +import jakarta.persistence.PreUpdate; +import org.apache.commons.lang3.StringUtils; + +public class PersonEventListener { + + @PrePersist + @PreUpdate + private void changeNameToUpperCase(T person) { + person.setName(StringUtils.upperCase(person.getName())); + } + +} diff --git a/persistence-modules/hibernate-jpa-2/src/main/resources/application.yaml b/persistence-modules/hibernate-jpa-2/src/main/resources/application.yaml index 45894a1a0c29..c14062559d82 100644 --- a/persistence-modules/hibernate-jpa-2/src/main/resources/application.yaml +++ b/persistence-modules/hibernate-jpa-2/src/main/resources/application.yaml @@ -2,9 +2,9 @@ spring: jpa: properties: hibernate: + integrator_provider: com.baeldung.changevalue.hibernate.HibernateEventListenerIntegratorProvider query: in_clause_parameter_padding: true - logging: level: org: diff --git a/persistence-modules/hibernate-jpa-2/src/test/java/com/baeldung/changevalue/repository/ChangeValueIntegrationTest.java b/persistence-modules/hibernate-jpa-2/src/test/java/com/baeldung/changevalue/repository/ChangeValueIntegrationTest.java new file mode 100644 index 000000000000..a046409029ee --- /dev/null +++ b/persistence-modules/hibernate-jpa-2/src/test/java/com/baeldung/changevalue/repository/ChangeValueIntegrationTest.java @@ -0,0 +1,93 @@ +package com.baeldung.changevalue.repository; + +import com.baeldung.changevalue.entity.Student; +import com.baeldung.changevalue.entity.StudentWithColumnTransformer; +import com.baeldung.changevalue.entity.StudentWithEventListener; +import com.baeldung.changevalue.entity.StudentWithHibernateEvent; +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; +import jakarta.transaction.Transactional; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; + +import static org.assertj.core.api.Assertions.assertThat; + +@DataJpaTest +@Transactional +class ChangeValueIntegrationTest { + + private static int recordIndex = 0; + + @PersistenceContext + private EntityManager entityManager; + + @BeforeEach + void setup() { + recordIndex++; + } + + @Test + void whenPersistStudent_thenNameIsInUpperCase() { + Student student = new Student(); + student.setName("David Morgan"); + + entityManager.persist(student); + + // then + student = entityManager.find(Student.class, recordIndex); + assertThat(student.getName()).isEqualTo("DAVID MORGAN"); + } + + @Test + void whenPersistStudentEventListener_thenNameIsInUpperCase() { + StudentWithEventListener student = new StudentWithEventListener(); + student.setName("David Morgan"); + + entityManager.persist(student); + + // then + student = entityManager.find(StudentWithEventListener.class, recordIndex); + assertThat(student.getName()).isEqualTo("DAVID MORGAN"); + } + + @Test + void whenPersistStudentHibernateEvent_thenNameIsInUpperCase() { + StudentWithHibernateEvent student = new StudentWithHibernateEvent(); + student.setName("David Morgan"); + + entityManager.persist(student); + + // then + student = entityManager.find(StudentWithHibernateEvent.class, recordIndex); + assertThat(student.getName()).isEqualTo("DAVID MORGAN"); + } + + @Test + void whenPersistStudentWithoutEmClear_thenNameIsNotInUpperCase() { + // given + StudentWithColumnTransformer student = new StudentWithColumnTransformer(); + student.setName("David Morgan"); + + entityManager.persist(student); + + // then + student = entityManager.find(StudentWithColumnTransformer.class, recordIndex); + assertThat(student.getName()).isNotEqualTo("DAVID MORGAN"); + } + + @Test + void whenPersistStudentWithEmClear_thenNameIsInUpperCase() { + // given + StudentWithColumnTransformer student = new StudentWithColumnTransformer(); + student.setName("David Morgan"); + + entityManager.persist(student); + entityManager.clear(); + + // then + student = entityManager.find(StudentWithColumnTransformer.class, recordIndex); + assertThat(student.getName()).isEqualTo("DAVID MORGAN"); + } + +} \ No newline at end of file