/trunk/spring/spring-data-parent/hibernate-dynamic-annotations/pom.xml |
---|
0,0 → 1,73 |
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
<modelVersion>4.0.0</modelVersion> |
<parent> |
<groupId>fr.ejn.tutorial.spring.spring-data</groupId> |
<artifactId>spring-data-parent</artifactId> |
<version>0.0.1-SNAPSHOT</version> |
</parent> |
<artifactId>hibernate-dynamic-annotations</artifactId> |
<name>Hibernate Dynamic Annotations Value</name> |
<description>Example to set Hibernate annotation on read and write, with dynamic value.</description> |
<dependencies> |
<!-- Apache commons --> |
<dependency> |
<groupId>org.apache.commons</groupId> |
<artifactId>commons-collections4</artifactId> |
</dependency> |
<dependency> |
<groupId>org.apache.commons</groupId> |
<artifactId>commons-text</artifactId> |
</dependency> |
<!-- Spring dependencies --> |
<dependency> |
<groupId>org.springframework.boot</groupId> |
<artifactId>spring-boot-configuration-processor</artifactId> |
</dependency> |
<dependency> |
<groupId>org.springframework.boot</groupId> |
<artifactId>spring-boot-starter-data-jpa</artifactId> |
</dependency> |
<!-- Lombok --> |
<dependency> |
<groupId>org.projectlombok</groupId> |
<artifactId>lombok</artifactId> |
</dependency> |
<!-- Postgre --> |
<dependency> |
<groupId>org.postgresql</groupId> |
<artifactId>postgresql</artifactId> |
</dependency> |
<!-- MySQL --> |
<dependency> |
<groupId>mysql</groupId> |
<artifactId>mysql-connector-java</artifactId> |
</dependency> |
<!-- Unit test --> |
<dependency> |
<groupId>org.meanbean</groupId> |
<artifactId>meanbean</artifactId> |
</dependency> |
</dependencies> |
<build> |
<resources> |
<resource> |
<directory>src/main/resources</directory> |
<filtering>false</filtering> |
</resource> |
<resource> |
<directory>src/main/resources.filtered</directory> |
<filtering>true</filtering> |
</resource> |
</resources> |
</build> |
</project> |
/trunk/spring/spring-data-parent/hibernate-dynamic-annotations/src/main/java/fr/ejn/tutorial/spring/data/configuration/DynamicAnnotationsConfiguration.java |
---|
0,0 → 1,53 |
package fr.ejn.tutorial.spring.data.configuration; |
import java.util.HashMap; |
import java.util.Map; |
import org.springframework.boot.context.properties.ConfigurationProperties; |
import org.springframework.context.annotation.Configuration; |
import org.springframework.context.weaving.LoadTimeWeaverAware; |
import org.springframework.instrument.classloading.LoadTimeWeaver; |
/** |
* Class to register elements from the application configuration file. Need to implements |
* LoadTimeWeaverAware, in order to be populate before Hibernate create the Persister. |
* |
* Store configuration elements inside a static Map. To access it, the getter |
* {@link #getProperties()} is required. |
* |
* @author Etienne Jouvin |
* |
*/ |
@ConfigurationProperties(prefix = "specificConfiguration") |
@Configuration |
public class DynamicAnnotationsConfiguration implements LoadTimeWeaverAware { |
private static final Map<String, String> PROPERTIES = new HashMap<>(); |
/** |
* Get properties map. |
* |
* @return Properties map. |
*/ |
public static Map<String, String> getStaticProperties() { |
return DynamicAnnotationsConfiguration.PROPERTIES; |
} |
/** |
* Get properties map. |
* |
* @return Properties map. |
*/ |
public Map<String, String> getProperties() { |
return DynamicAnnotationsConfiguration.PROPERTIES; |
} |
/** |
* {@inheritDoc} |
*/ |
@Override |
public void setLoadTimeWeaver(LoadTimeWeaver loadTimeWeaver) { |
// Nothing to do |
} |
} |
/trunk/spring/spring-data-parent/hibernate-dynamic-annotations/src/main/java/fr/ejn/tutorial/spring/data/dao/UserRepository.java |
---|
0,0 → 1,15 |
package fr.ejn.tutorial.spring.data.dao; |
import org.springframework.data.jpa.repository.JpaRepository; |
import fr.ejn.tutorial.spring.data.model.TutorialUser; |
/** |
* Repository definitions for users. Implements JpaRepository to have all CRUD functions. |
* |
* @author Etienne Jouvin |
* |
*/ |
public interface UserRepository extends JpaRepository<TutorialUser, Long> { |
} |
/trunk/spring/spring-data-parent/hibernate-dynamic-annotations/src/main/java/fr/ejn/tutorial/spring/data/model/TutorialUser.java |
---|
0,0 → 1,46 |
package fr.ejn.tutorial.spring.data.model; |
import javax.persistence.Column; |
import javax.persistence.Entity; |
import javax.persistence.GeneratedValue; |
import javax.persistence.GenerationType; |
import javax.persistence.Id; |
import javax.persistence.Table; |
import org.hibernate.annotations.ColumnTransformer; |
import org.hibernate.annotations.Persister; |
import fr.ejn.tutorial.spring.data.persister.DynamicAnnotationPersister; |
import lombok.Getter; |
import lombok.Setter; |
/** |
* POJO for the user entity in database. |
* |
* Example with some reader and writer registered with variables, replaced by the custom Persister. |
* |
* All getter and setter are generated with Lombok and annotations <i>Getter</i> / <i>Setter</i>. |
* |
* @author Etienne Jouvin |
* |
*/ |
@Getter |
@Setter |
@Entity |
@Table(name = "app_user") |
@Persister(impl = DynamicAnnotationPersister.class) |
public class TutorialUser { |
@Id |
@GeneratedValue(strategy = GenerationType.IDENTITY) |
@Column(name = "user_id") |
private Long id; |
@Column(name = "user_name") |
private String name; |
@Column(name = "user_password") |
@ColumnTransformer(read = "${functionRead}", write = "${functionWrite(?)}") |
private String password; |
} |
/trunk/spring/spring-data-parent/hibernate-dynamic-annotations/src/main/java/fr/ejn/tutorial/spring/data/persister/DynamicAnnotationPersister.java |
---|
0,0 → 1,38 |
package fr.ejn.tutorial.spring.data.persister; |
import org.hibernate.HibernateException; |
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy; |
import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy; |
import org.hibernate.mapping.PersistentClass; |
import org.hibernate.persister.entity.SingleTableEntityPersister; |
import org.hibernate.persister.spi.PersisterCreationContext; |
import fr.ejn.tutorial.spring.data.persister.transformer.PersistentClassTransformer; |
/** |
* Custom persister that just transform annotation value for custom write and read on fields. |
* |
* @author Etienne Jouvin |
* |
*/ |
public class DynamicAnnotationPersister extends SingleTableEntityPersister { |
/** |
* Custom constructor used to transform the PersistentClass instance before calling default entity |
* persister constructor. |
* |
* @param persistentClass Persistent class to transform. |
* @param cacheAccessStrategy Cache access strategy. |
* @param naturalIdRegionAccessStrategy Id access strategy. |
* @param creationContext Creation context. |
* @throws HibernateException Hibernate exception. |
*/ |
public DynamicAnnotationPersister(PersistentClass persistentClass, |
EntityRegionAccessStrategy cacheAccessStrategy, |
NaturalIdRegionAccessStrategy naturalIdRegionAccessStrategy, |
PersisterCreationContext creationContext) { |
super(PersistentClassTransformer.getInstance() |
.transform(persistentClass), cacheAccessStrategy, naturalIdRegionAccessStrategy, creationContext); |
} |
} |
/trunk/spring/spring-data-parent/hibernate-dynamic-annotations/src/main/java/fr/ejn/tutorial/spring/data/persister/closure/CustomAccessUpdateClosure.java |
---|
0,0 → 1,50 |
package fr.ejn.tutorial.spring.data.persister.closure; |
import java.util.HashMap; |
import java.util.Map; |
import org.apache.commons.collections4.Closure; |
import org.apache.commons.text.StringSubstitutor; |
import org.hibernate.mapping.Column; |
import fr.ejn.tutorial.spring.data.configuration.DynamicAnnotationsConfiguration; |
/** |
* Closure instance used to change custom read and writ on a Column definition. |
* |
* @author Etienne Jouvin |
* |
*/ |
public final class CustomAccessUpdateClosure implements Closure<Column> { |
private static final Closure<Column> INSTANCE = new CustomAccessUpdateClosure(); |
/** |
* Get default instance. |
* |
* @return Default instance. |
*/ |
public static Closure<Column> getInstance() { |
return INSTANCE; |
} |
/** |
* Private constructor. |
*/ |
private CustomAccessUpdateClosure() { |
} |
/** |
* {@inheritDoc} |
*/ |
@Override |
public void execute(Column column) { |
Map<String, String> patternValues = new HashMap<>(DynamicAnnotationsConfiguration |
.getStaticProperties()); |
patternValues.put("columnName", column.getName()); |
column.setCustomRead(StringSubstitutor.replace(column.getCustomRead(), patternValues)); |
column.setCustomWrite(StringSubstitutor.replace(column.getCustomWrite(), patternValues)); |
} |
} |
/trunk/spring/spring-data-parent/hibernate-dynamic-annotations/src/main/java/fr/ejn/tutorial/spring/data/persister/closure/PropertyUpdateClosure.java |
---|
0,0 → 1,49 |
package fr.ejn.tutorial.spring.data.persister.closure; |
import org.apache.commons.collections4.Closure; |
import org.apache.commons.collections4.ClosureUtils; |
import org.apache.commons.collections4.IteratorUtils; |
import org.apache.commons.collections4.PredicateUtils; |
import org.hibernate.mapping.Column; |
import org.hibernate.mapping.Property; |
/** |
* Closure instance used to change custom read and writ on all Columns set inside a Property |
* instance.. |
* |
* @author Etienne Jouvin |
* |
*/ |
public final class PropertyUpdateClosure implements Closure<Property> { |
private static final Closure<Property> INSTANCE = new PropertyUpdateClosure(); |
/** |
* Get default instance. |
* |
* @return Default instance. |
*/ |
public static Closure<Property> getInstance() { |
return INSTANCE; |
} |
@SuppressWarnings({ "rawtypes" }) |
private Closure columnUpdaters = ClosureUtils.ifClosure(PredicateUtils |
.instanceofPredicate(Column.class), CustomAccessUpdateClosure.getInstance()); |
/** |
* Private constructor. |
*/ |
private PropertyUpdateClosure() { |
} |
/** |
* {@inheritDoc} |
*/ |
@SuppressWarnings("unchecked") |
@Override |
public void execute(Property property) { |
IteratorUtils.forEach(property.getColumnIterator(), columnUpdaters); |
} |
} |
/trunk/spring/spring-data-parent/hibernate-dynamic-annotations/src/main/java/fr/ejn/tutorial/spring/data/persister/transformer/PersistentClassTransformer.java |
---|
0,0 → 1,49 |
package fr.ejn.tutorial.spring.data.persister.transformer; |
import org.apache.commons.collections4.IteratorUtils; |
import org.apache.commons.collections4.Transformer; |
import org.hibernate.mapping.PersistentClass; |
import fr.ejn.tutorial.spring.data.persister.closure.PropertyUpdateClosure; |
/** |
* Transformer instance used to update all properties definition, by setting custom read and writer |
* on columns, inside a PersistentClass built by Hibernate. |
* |
* the PersistentClass contains the Entity definition with all annotations. |
* |
* @author Etienne Jouvin |
* |
*/ |
public final class PersistentClassTransformer |
implements Transformer<PersistentClass, PersistentClass> { |
private static final Transformer<PersistentClass, PersistentClass> INSTANCE = new PersistentClassTransformer(); |
/** |
* Get default instance. |
* |
* @return Default instance. |
*/ |
public static Transformer<PersistentClass, PersistentClass> getInstance() { |
return INSTANCE; |
} |
/** |
* Private constructor. |
*/ |
private PersistentClassTransformer() { |
} |
/** |
* {@inheritDoc} |
*/ |
@SuppressWarnings("unchecked") |
@Override |
public PersistentClass transform(PersistentClass persistentClass) { |
IteratorUtils |
.forEach(persistentClass.getPropertyClosureIterator(), PropertyUpdateClosure.getInstance()); |
return persistentClass; |
} |
} |
/trunk/spring/spring-data-parent/hibernate-dynamic-annotations/src/main/resources.filtered/application.yml |
---|
0,0 → 1,28 |
# =================================================================== |
# Standard Spring Boot properties. |
# Full reference is available at: |
# http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html |
# =================================================================== |
spring: |
application: |
name: '@project.name@' |
jpa: |
hibernate: |
ddl-auto: none |
show-sql: true |
properties: |
hibernate: |
default_schema: spring_jpa |
# Logging configuration |
logging: |
path: . |
level: |
root: INFO |
specificConfiguration: |
properties: |
functionRead: 'To complete' |
'functionWrite(?)': 'To complete' |
encryptPwd: 'To complete' |
/trunk/spring/spring-data-parent/hibernate-dynamic-annotations/src/main/resources.filtered/application-mysql.yml |
---|
0,0 → 1,21 |
# =================================================================== |
# Standard Spring Boot properties. |
# Full reference is available at: |
# http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html |
# =================================================================== |
spring: |
datasource: |
url: jdbc:mysql://localhost:3306/spring_jpa |
platform: mysql |
driver-class-name: com.mysql.jdbc.Driver |
username: root |
password: GCW5E5S8Mysql |
jpa: |
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect |
specificConfiguration: |
properties: |
functionRead: 'aes_decrypt(${columnName}, ''${encryptPwd}'')' |
'functionWrite(?)': 'aes_encrypt(?, ''${encryptPwd}'')' |
encryptPwd: 'any password' |
/trunk/spring/spring-data-parent/hibernate-dynamic-annotations/src/main/resources.filtered/application-postgre.yml |
---|
0,0 → 1,21 |
# =================================================================== |
# Standard Spring Boot properties. |
# Full reference is available at: |
# http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html |
# =================================================================== |
spring: |
datasource: |
url: jdbc:postgresql://localhost:5432/study?currentSchema=spring_jpa |
platform: postgres |
driver-class-name: org.postgresql.Driver |
username: postgres |
password: postgres |
jpa: |
database-platform: org.hibernate.dialect.PostgreSQLDialect |
specificConfiguration: |
properties: |
functionRead: 'aes_decrypt(?, ''${encryptPwd}'')' |
'functionWrite(?)': 'aes_encrypt(${columnName}, ''${encryptPwd}'')' |
encryptPwd: 'any password' |
/trunk/spring/spring-data-parent/hibernate-dynamic-annotations/src/test/java/fr/ejn/tutorial/spring/data/configuration/DynamicAnnotationsConfigurationTest.java |
---|
0,0 → 1,66 |
package fr.ejn.tutorial.spring.data.configuration; |
import static org.junit.Assert.assertEquals; |
import static org.junit.Assert.assertNotNull; |
import java.util.HashMap; |
import java.util.Map; |
import org.junit.After; |
import org.junit.AfterClass; |
import org.junit.Before; |
import org.junit.BeforeClass; |
import org.junit.Test; |
public class DynamicAnnotationsConfigurationTest { |
private static Map<String, String> originalProperties; |
@BeforeClass |
public static void setUpBeforeClass() throws Exception { |
Map<String, String> properties = DynamicAnnotationsConfiguration.getStaticProperties(); |
originalProperties = new HashMap<>(properties); |
properties.clear(); |
properties.put("first", "1st"); |
properties.put("second", "2nd"); |
properties.put("third", "3rd"); |
} |
@AfterClass |
public static void tearDownAfterClass() throws Exception { |
Map<String, String> properties = DynamicAnnotationsConfiguration.getStaticProperties(); |
properties.clear(); |
properties.putAll(originalProperties); |
} |
private DynamicAnnotationsConfiguration instance; |
@Before |
public void setUp() throws Exception { |
instance = new DynamicAnnotationsConfiguration(); |
} |
@After |
public void tearDown() throws Exception { |
} |
@Test |
public void testGetProperties() { |
Map<String, String> actual = instance.getProperties(); |
assertNotNull(actual); |
assertEquals(3, actual.size()); |
assertEquals("1st", actual.get("first")); |
assertEquals("2nd", actual.get("second")); |
assertEquals("3rd", actual.get("third")); |
} |
@Test |
public void testSetLoadTimeWeaver() { |
instance.setLoadTimeWeaver(null); |
} |
} |
/trunk/spring/spring-data-parent/hibernate-dynamic-annotations/src/test/java/fr/ejn/tutorial/spring/data/model/TutorialUserTest.java |
---|
0,0 → 1,33 |
package fr.ejn.tutorial.spring.data.model; |
import org.junit.After; |
import org.junit.AfterClass; |
import org.junit.Before; |
import org.junit.BeforeClass; |
import org.junit.Test; |
import org.meanbean.test.BeanTester; |
public class TutorialUserTest { |
@BeforeClass |
public static void setUpBeforeClass() throws Exception { |
} |
@AfterClass |
public static void tearDownAfterClass() throws Exception { |
} |
@Before |
public void setUp() throws Exception { |
} |
@After |
public void tearDown() throws Exception { |
} |
@Test |
public void testInstance() { |
new BeanTester().testBean(TutorialUser.class); |
} |
} |
/trunk/spring/spring-data-parent/hibernate-dynamic-annotations/src/test/java/fr/ejn/tutorial/spring/data/persister/closure/PropertyUpdateClosureTest.java |
---|
0,0 → 1,86 |
package fr.ejn.tutorial.spring.data.persister.closure; |
import static org.assertj.core.api.Assertions.assertThat; |
import java.util.Map; |
import org.apache.commons.collections4.Closure; |
import org.hibernate.mapping.Column; |
import org.hibernate.mapping.Property; |
import org.hibernate.mapping.SimpleValue; |
import org.junit.After; |
import org.junit.AfterClass; |
import org.junit.Before; |
import org.junit.BeforeClass; |
import org.junit.Test; |
import fr.ejn.tutorial.spring.data.configuration.DynamicAnnotationsConfiguration; |
public class PropertyUpdateClosureTest { |
@BeforeClass |
public static void setUpBeforeClass() throws Exception { |
Map<String, String> properties = DynamicAnnotationsConfiguration.getStaticProperties(); |
properties.clear(); |
properties.put("encryptPwd", "password value"); |
properties |
.put("functionRead", "convert_from(pgp_sym_decrypt_bytea(${columnName}, '${encryptPwd}', 'compress-algo=1, cipher-algo=aes256')"); |
properties |
.put("functionWrite(?)", "pgp_sym_encrypt(?, '${encryptPwd}', 'compress-algo=1, cipher-algo=aes256')"); |
} |
@AfterClass |
public static void tearDownAfterClass() throws Exception { |
} |
private Closure<Property> instance; |
@Before |
public void setUp() throws Exception { |
instance = PropertyUpdateClosure.getInstance(); |
} |
@After |
public void tearDown() throws Exception { |
} |
@Test |
public void testExecute() throws Exception { |
Column simpleColumn = new Column(); |
simpleColumn.setName("nothing"); |
simpleColumn.setCustomRead(""); |
simpleColumn.setCustomWrite(""); |
Column customReadColumn = new Column(); |
customReadColumn.setName("custom_read"); |
customReadColumn.setCustomRead("${functionRead}"); |
customReadColumn.setCustomWrite(""); |
Column customWriteColumn = new Column(); |
customWriteColumn.setName("custom_write"); |
customWriteColumn.setCustomRead(""); |
customWriteColumn.setCustomWrite("${functionWrite(?)}"); |
SimpleValue value = new SimpleValue(null); |
value.addColumn(simpleColumn); |
value.addColumn(customReadColumn); |
value.addColumn(customWriteColumn); |
Property property = new Property(); |
property.setValue(value); |
instance.execute(property); |
assertThat(simpleColumn.getCustomRead()).isEqualTo(""); |
assertThat(simpleColumn.getCustomWrite()).isEqualTo(""); |
assertThat(customReadColumn.getCustomRead()) |
.isEqualTo("convert_from(pgp_sym_decrypt_bytea(custom_read, 'password value', 'compress-algo=1, cipher-algo=aes256')"); |
assertThat(customReadColumn.getCustomWrite()).isEqualTo(""); |
assertThat(customWriteColumn.getCustomRead()).isEqualTo(""); |
assertThat(customWriteColumn.getCustomWrite()) |
.isEqualTo("pgp_sym_encrypt(?, 'password value', 'compress-algo=1, cipher-algo=aes256')"); |
} |
} |
/trunk/spring/spring-data-parent/hibernate-dynamic-annotations/src/test/java/fr/ejn/tutorial/spring/data/persister/closure/CustomAccessUpdateClosureTest.java |
---|
0,0 → 1,96 |
package fr.ejn.tutorial.spring.data.persister.closure; |
import static org.assertj.core.api.Assertions.assertThat; |
import java.util.Map; |
import org.apache.commons.collections4.Closure; |
import org.hibernate.mapping.Column; |
import org.junit.After; |
import org.junit.AfterClass; |
import org.junit.Before; |
import org.junit.BeforeClass; |
import org.junit.Test; |
import fr.ejn.tutorial.spring.data.configuration.DynamicAnnotationsConfiguration; |
public class CustomAccessUpdateClosureTest { |
@BeforeClass |
public static void setUpBeforeClass() throws Exception { |
Map<String, String> properties = DynamicAnnotationsConfiguration.getStaticProperties(); |
properties.clear(); |
properties.put("encryptPwd", "password value"); |
properties |
.put("functionRead", "convert_from(pgp_sym_decrypt_bytea(${columnName}, '${encryptPwd}', 'compress-algo=1, cipher-algo=aes256')"); |
properties |
.put("functionWrite(?)", "pgp_sym_encrypt(?, '${encryptPwd}', 'compress-algo=1, cipher-algo=aes256')"); |
} |
@AfterClass |
public static void tearDownAfterClass() throws Exception { |
} |
private Closure<Column> instance; |
@Before |
public void setUp() throws Exception { |
instance = CustomAccessUpdateClosure.getInstance(); |
} |
@After |
public void tearDown() throws Exception { |
} |
@Test |
public void testExecute() throws Exception { |
Column column = new Column(); |
column.setName("user_password"); |
column.setCustomRead("${functionRead}"); |
column.setCustomWrite("${functionWrite(?)}"); |
instance.execute(column); |
String expected = "convert_from(pgp_sym_decrypt_bytea(user_password, 'password value', 'compress-algo=1, cipher-algo=aes256')"; |
String actual = column.getCustomRead(); |
assertThat(actual).isEqualTo(expected); |
expected = "pgp_sym_encrypt(?, 'password value', 'compress-algo=1, cipher-algo=aes256')"; |
actual = column.getCustomWrite(); |
assertThat(actual).isEqualTo(expected); |
} |
@Test |
public void testExecuteOnEmpty() throws Exception { |
Column column = new Column(); |
column.setName("user_password"); |
column.setCustomRead(""); |
column.setCustomWrite(""); |
instance.execute(column); |
String expected = ""; |
String actual = column.getCustomRead(); |
assertThat(actual).isEqualTo(expected); |
expected = ""; |
actual = column.getCustomWrite(); |
assertThat(actual).isEqualTo(expected); |
} |
@Test |
public void testExecuteOnNull() throws Exception { |
Column column = new Column(); |
column.setName("user_password"); |
column.setCustomRead(null); |
column.setCustomWrite(null); |
instance.execute(column); |
String actual = column.getCustomRead(); |
assertThat(actual).isNull(); |
actual = column.getCustomWrite(); |
assertThat(actual).isNull(); |
} |
} |
/trunk/spring/spring-data-parent/hibernate-dynamic-annotations/src/test/java/fr/ejn/tutorial/spring/data/persister/transformer/PersistentClassTransformerTest.java |
---|
0,0 → 1,98 |
package fr.ejn.tutorial.spring.data.persister.transformer; |
import static org.assertj.core.api.Assertions.assertThat; |
import java.util.Iterator; |
import java.util.Map; |
import org.apache.commons.collections4.Transformer; |
import org.hibernate.mapping.Column; |
import org.hibernate.mapping.PersistentClass; |
import org.hibernate.mapping.Property; |
import org.hibernate.mapping.RootClass; |
import org.hibernate.mapping.SimpleValue; |
import org.junit.After; |
import org.junit.AfterClass; |
import org.junit.Before; |
import org.junit.BeforeClass; |
import org.junit.Test; |
import fr.ejn.tutorial.spring.data.configuration.DynamicAnnotationsConfiguration; |
public class PersistentClassTransformerTest { |
@BeforeClass |
public static void setUpBeforeClass() throws Exception { |
Map<String, String> properties = DynamicAnnotationsConfiguration.getStaticProperties(); |
properties.clear(); |
properties.put("encryptPwd", "password value"); |
properties |
.put("functionRead", "convert_from(pgp_sym_decrypt_bytea(${columnName}, '${encryptPwd}', 'compress-algo=1, cipher-algo=aes256')"); |
properties |
.put("functionWrite(?)", "pgp_sym_encrypt(?, '${encryptPwd}', 'compress-algo=1, cipher-algo=aes256')"); |
} |
@AfterClass |
public static void tearDownAfterClass() throws Exception { |
} |
private Transformer<PersistentClass, PersistentClass> instance; |
@Before |
public void setUp() throws Exception { |
instance = PersistentClassTransformer.getInstance(); |
} |
@After |
public void tearDown() throws Exception { |
} |
@SuppressWarnings({ "unchecked", "rawtypes" }) |
@Test |
public void testTransform() throws Exception { |
Column simpleColumn = new Column(); |
simpleColumn.setName("nothing"); |
simpleColumn.setCustomRead(""); |
simpleColumn.setCustomWrite(""); |
Column customReadColumn = new Column(); |
customReadColumn.setName("custom_read"); |
customReadColumn.setCustomRead("${functionRead}"); |
customReadColumn.setCustomWrite(""); |
Column customWriteColumn = new Column(); |
customWriteColumn.setName("custom_write"); |
customWriteColumn.setCustomRead(""); |
customWriteColumn.setCustomWrite("${functionWrite(?)}"); |
SimpleValue value = new SimpleValue(null); |
value.addColumn(simpleColumn); |
value.addColumn(customReadColumn); |
value.addColumn(customWriteColumn); |
Property property = new Property(); |
property.setName("property_name"); |
property.setValue(value); |
PersistentClass input = new RootClass(null); |
input.addProperty(property); |
PersistentClass actual = instance.transform(input); |
Property actualProperty = actual.getProperty("property_name"); |
Iterator actualColumns = actualProperty.getColumnIterator(); |
assertThat(actualColumns).containsExactly(simpleColumn, customReadColumn, customWriteColumn); |
assertThat(simpleColumn.getCustomRead()).isEqualTo(""); |
assertThat(simpleColumn.getCustomWrite()).isEqualTo(""); |
assertThat(customReadColumn.getCustomRead()) |
.isEqualTo("convert_from(pgp_sym_decrypt_bytea(custom_read, 'password value', 'compress-algo=1, cipher-algo=aes256')"); |
assertThat(customReadColumn.getCustomWrite()).isEqualTo(""); |
assertThat(customWriteColumn.getCustomRead()).isEqualTo(""); |
assertThat(customWriteColumn.getCustomWrite()) |
.isEqualTo("pgp_sym_encrypt(?, 'password value', 'compress-algo=1, cipher-algo=aes256')"); |
} |
} |
/trunk/spring/spring-data-parent/hibernate-dynamic-annotations/src/test/resources/logback.xml |
---|
0,0 → 1,14 |
<?xml version="1.0" encoding="UTF-8"?> |
<configuration> |
<include resource="org/springframework/boot/logging/logback/defaults.xml" /> |
<include resource="org/springframework/boot/logging/logback/console-appender.xml" /> |
<logger name="fr.ejn.tutorial" level="info"> |
</logger> |
<root level="error"> |
<appender-ref ref="CONSOLE" /> |
</root> |
</configuration> |
/trunk/spring/spring-data-parent/hibernate-dynamic-annotations/src/test/resources/initDatabase-mysql.sql |
---|
0,0 → 1,11 |
create database if not exists spring_jpa character set = utf8 collate utf8_general_ci |
create table if not exists spring_jpa.app_user ( |
user_id MEDIUMINT not null AUTO_INCREMENT, |
user_name varchar(100) not null, |
user_password VARBINARY(100) null, |
primary key (user_id) |
) |
ENGINE=InnoDB |
default CHARSET=utf8 |
collate=utf8_general_ci |
/trunk/spring/spring-data-parent/hibernate-dynamic-annotations/src/test/resources/initDatabase-postgre.sql |
---|
0,0 → 1,12 |
create schema if not exists "spring_jpa" |
create extension pgcrypto with schema "spring_jpa" |
CREATE TABLE "spring_jpa".app_user ( |
user_id serial NOT NULL, |
user_name varchar NOT NULL, |
user_password bytea NULL |
) |
WITH ( |
OIDS=FALSE |
) |
/trunk/spring/spring-data-parent/jpa-listeners/pom.xml |
---|
0,0 → 1,110 |
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
<modelVersion>4.0.0</modelVersion> |
<parent> |
<groupId>fr.ejn.tutorial.spring.spring-data</groupId> |
<artifactId>spring-data-parent</artifactId> |
<version>0.0.1-SNAPSHOT</version> |
</parent> |
<artifactId>jpa-listeners</artifactId> |
<name>Spring service injected in JPA Listeners</name> |
<description>Example to inject Spring service inside JPA listener.</description> |
<properties> |
<aspectj.version>1.8.12</aspectj.version> |
</properties> |
<dependencies> |
<!-- Spring dependencies --> |
<dependency> |
<groupId>org.springframework.boot</groupId> |
<artifactId>spring-boot-configuration-processor</artifactId> |
</dependency> |
<dependency> |
<groupId>org.springframework.boot</groupId> |
<artifactId>spring-boot-starter-data-jpa</artifactId> |
</dependency> |
<!-- H2 --> |
<dependency> |
<groupId>com.h2database</groupId> |
<artifactId>h2</artifactId> |
</dependency> |
<!-- Postgre --> |
<dependency> |
<groupId>org.postgresql</groupId> |
<artifactId>postgresql</artifactId> |
</dependency> |
<!-- MySQL --> |
<dependency> |
<groupId>mysql</groupId> |
<artifactId>mysql-connector-java</artifactId> |
</dependency> |
<!-- Unit test --> |
<dependency> |
<groupId>org.meanbean</groupId> |
<artifactId>meanbean</artifactId> |
</dependency> |
<dependency> |
<groupId>org.springframework.boot</groupId> |
<artifactId>spring-boot-starter-test</artifactId> |
</dependency> |
</dependencies> |
<build> |
<plugins> |
<plugin> |
<groupId>org.codehaus.mojo</groupId> |
<artifactId>aspectj-maven-plugin</artifactId> |
<version>1.11</version> |
<dependencies> |
<dependency> |
<groupId>org.aspectj</groupId> |
<artifactId>aspectjrt</artifactId> |
<version>${aspectj.version}</version> |
</dependency> |
<dependency> |
<groupId>org.aspectj</groupId> |
<artifactId>aspectjtools</artifactId> |
<version>${aspectj.version}</version> |
</dependency> |
</dependencies> |
<executions> |
<execution> |
<goals> |
<goal>compile</goal> |
</goals> |
</execution> |
</executions> |
<configuration> |
<verbose>true</verbose> |
<!-- |
To workaround: |
- https://issues.apache.org/jira/browse/MCOMPILER-205 |
- https://issues.apache.org/jira/browse/MCOMPILER-209 |
- https://github.com/mojohaus/aspectj-maven-plugin/issues/15 |
--> |
<forceAjcCompile>true</forceAjcCompile> |
<aspectLibraries> |
<aspectLibrary> |
<groupId>org.springframework</groupId> |
<artifactId>spring-aspects</artifactId> |
</aspectLibrary> |
</aspectLibraries> |
<includes> |
<include>**/data/support/LogActionListener.java</include> |
</includes> |
<complianceLevel>${source.level}</complianceLevel> |
<source>${source.level}</source> |
<target>${source.level}</target> |
<xmlConfigured>aop.xml</xmlConfigured> |
</configuration> |
</plugin> |
</plugins> |
</build> |
</project> |
/trunk/spring/spring-data-parent/jpa-listeners/src/main/java/fr/ejn/tutorial/spring/data/dao/LogUserRepository.java |
---|
0,0 → 1,27 |
package fr.ejn.tutorial.spring.data.dao; |
import java.util.List; |
import org.springframework.data.jpa.repository.JpaRepository; |
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; |
import fr.ejn.tutorial.spring.data.model.TutorialLogUser; |
/** |
* Repository definitions for log messages. |
* |
* @author Etienne Jouvin |
* |
*/ |
public interface LogUserRepository |
extends JpaRepository<TutorialLogUser, Long>, JpaSpecificationExecutor<TutorialLogUser> { |
/** |
* Find all log messages for a user according his id. |
* |
* @param userId User id used as filter. |
* @return All found log messages. |
*/ |
List<TutorialLogUser> findAllByUserId(Long userId); |
} |
/trunk/spring/spring-data-parent/jpa-listeners/src/main/java/fr/ejn/tutorial/spring/data/dao/UserRepository.java |
---|
0,0 → 1,26 |
package fr.ejn.tutorial.spring.data.dao; |
import org.springframework.data.jpa.repository.JpaRepository; |
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; |
import fr.ejn.tutorial.spring.data.model.TutorialUser; |
/** |
* Repository definitions for users. Implements JpaRepository to have all CRUD functions and |
* JpaSpecificationExecutor for fluent functions. |
* |
* @author Etienne Jouvin |
* |
*/ |
public interface UserRepository |
extends JpaRepository<TutorialUser, Long>, JpaSpecificationExecutor<TutorialUser> { |
/** |
* Find a user from his name. |
* |
* @param name User name for filter. |
* @return First matching user. |
*/ |
TutorialUser findFirstByName(String name); |
} |
/trunk/spring/spring-data-parent/jpa-listeners/src/main/java/fr/ejn/tutorial/spring/data/model/TutorialLogUser.java |
---|
0,0 → 1,135 |
package fr.ejn.tutorial.spring.data.model; |
import java.util.Date; |
import javax.persistence.Column; |
import javax.persistence.Entity; |
import javax.persistence.EntityListeners; |
import javax.persistence.GeneratedValue; |
import javax.persistence.GenerationType; |
import javax.persistence.Id; |
import javax.persistence.Table; |
import org.springframework.data.annotation.CreatedDate; |
import org.springframework.data.jpa.domain.support.AuditingEntityListener; |
/** |
* POJO for the log entity in database. |
* |
* @author Etienne Jouvin |
* |
*/ |
@Entity |
@EntityListeners(AuditingEntityListener.class) |
@Table(name = "app_log") |
public class TutorialLogUser { |
@CreatedDate |
@Column(name = "event_date") |
private Date eventDate; |
@Column(name = "event_name") |
private String eventName; |
@Id |
@GeneratedValue(strategy = GenerationType.IDENTITY) |
@Column(name = "log_id") |
private Long id; |
@Column(name = "user_id") |
private Long userId; |
@Column(name = "user_name") |
private String userName; |
/** |
* Get the eventDate. |
* |
* @return the eventDate. |
*/ |
public Date getEventDate() { |
return (Date) eventDate.clone(); |
} |
/** |
* Get the eventName. |
* |
* @return the eventName. |
*/ |
public String getEventName() { |
return eventName; |
} |
/** |
* Get the id. |
* |
* @return the id. |
*/ |
public Long getId() { |
return id; |
} |
/** |
* Get the userId. |
* |
* @return the userId. |
*/ |
public Long getUserId() { |
return userId; |
} |
/** |
* Get the userName. |
* |
* @return the userName. |
*/ |
public String getUserName() { |
return userName; |
} |
/** |
* Set the eventDate. |
* |
* @param eventDate the eventDate to set. |
*/ |
public void setEventDate(Date eventDate) { |
this.eventDate = (Date) eventDate.clone(); |
} |
/** |
* Set the eventName. |
* |
* @param eventName the eventName to set. |
*/ |
public void setEventName(String eventName) { |
this.eventName = eventName; |
} |
/** |
* Set the id. |
* |
* @param id the id to set. |
*/ |
public void setId(Long id) { |
this.id = id; |
} |
/** |
* Set the userId. |
* |
* @param userId the userId to set. |
*/ |
public void setUserId(Long userId) { |
this.userId = userId; |
} |
/** |
* Set the userName. |
* |
* @param userName the userName to set. |
*/ |
public void setUserName(String userName) { |
this.userName = userName; |
} |
} |
/trunk/spring/spring-data-parent/jpa-listeners/src/main/java/fr/ejn/tutorial/spring/data/model/TutorialUser.java |
---|
0,0 → 1,89 |
package fr.ejn.tutorial.spring.data.model; |
import javax.persistence.Column; |
import javax.persistence.Entity; |
import javax.persistence.EntityListeners; |
import javax.persistence.GeneratedValue; |
import javax.persistence.GenerationType; |
import javax.persistence.Id; |
import javax.persistence.Table; |
import fr.ejn.tutorial.spring.data.support.LogActionListener; |
/** |
* POJO for the user entity in database. |
* |
* @author Etienne Jouvin |
* |
*/ |
@Entity |
@EntityListeners(LogActionListener.class) |
@Table(name = "app_user") |
public class TutorialUser { |
@Column(name = "user_age") |
private Integer age; |
@Id |
@GeneratedValue(strategy = GenerationType.IDENTITY) |
@Column(name = "user_id") |
private Long id; |
@Column(name = "user_name") |
private String name; |
/** |
* Get the age. |
* |
* @return the age. |
*/ |
public Integer getAge() { |
return age; |
} |
/** |
* Get the id. |
* |
* @return the id. |
*/ |
public Long getId() { |
return id; |
} |
/** |
* Get the name. |
* |
* @return the name. |
*/ |
public String getName() { |
return name; |
} |
/** |
* Set the age. |
* |
* @param age the age to set. |
*/ |
public void setAge(Integer age) { |
this.age = age; |
} |
/** |
* Set the id. |
* |
* @param id the id to set. |
*/ |
public void setId(Long id) { |
this.id = id; |
} |
/** |
* Set the name. |
* |
* @param name the name to set. |
*/ |
public void setName(String name) { |
this.name = name; |
} |
} |
/trunk/spring/spring-data-parent/jpa-listeners/src/main/java/fr/ejn/tutorial/spring/data/support/LogActionListener.java |
---|
0,0 → 1,125 |
package fr.ejn.tutorial.spring.data.support; |
import javax.persistence.PostLoad; |
import javax.persistence.PostPersist; |
import javax.persistence.PostRemove; |
import javax.persistence.PostUpdate; |
import javax.persistence.PrePersist; |
import javax.persistence.PreRemove; |
import javax.persistence.PreUpdate; |
import org.springframework.beans.factory.annotation.Autowire; |
import org.springframework.beans.factory.annotation.Configurable; |
import org.springframework.context.annotation.Lazy; |
import fr.ejn.tutorial.spring.data.dao.LogUserRepository; |
import fr.ejn.tutorial.spring.data.model.TutorialLogUser; |
import fr.ejn.tutorial.spring.data.model.TutorialUser; |
/** |
* Example of listener with functions annotated with available JPA annotations. |
* |
* @author Etienne Jouvin |
* |
*/ |
@Configurable(autowire = Autowire.BY_TYPE, dependencyCheck = true) |
public class LogActionListener { |
private LogUserRepository logUserRepository; |
/** |
* Function with PostLoad annotation, called when the entity is loaded. |
* |
* @param user Loaded entity. |
*/ |
@PostLoad |
public void onPostLoad(TutorialUser user) { |
this.publishLog("load", user); |
} |
/** |
* Function with PostPersist annotation, called when the entity is saved the first time. |
* |
* @param user Saved entity. |
*/ |
@PostPersist |
public void onPostPersist(TutorialUser user) { |
this.publishLog("saved", user); |
} |
/** |
* Function with PostRemove annotation, called when the entity is deleted. |
* |
* @param user Deleted entity. |
*/ |
@PostRemove |
public void onPostRemove(TutorialUser user) { |
this.publishLog("deleted", user); |
} |
/** |
* Function with PostUpdate annotation, called when the entity is updated. |
* |
* @param user Updated entity. |
*/ |
@PostUpdate |
public void onPostUpdate(TutorialUser user) { |
this.publishLog("updated", user); |
} |
/** |
* Function with PrePersist annotation, called before the entity is saved the first time. |
* |
* @param user Entity in save progress. |
*/ |
@PrePersist |
public void onPrePersist(TutorialUser user) { |
this.publishLog("before save", user); |
} |
/** |
* Function with PreRemove annotation, called before the entity is deleted. |
* |
* @param user Entity in save progress. |
*/ |
@PreRemove |
public void onPreRemove(TutorialUser user) { |
this.publishLog("before remove", user); |
} |
/** |
* Function with PreUpdate annotation, called before the entity is updated. |
* |
* @param user Entity in save progress. |
*/ |
@PreUpdate |
public void onPreUpdate(TutorialUser user) { |
this.publishLog("before update", user); |
} |
/** |
* Publish a log for an event and entity. |
* |
* @param eventName Event name. |
* @param user Source entity. |
*/ |
private void publishLog(String eventName, TutorialUser user) { |
TutorialLogUser log = new TutorialLogUser(); |
log.setEventName(eventName); |
log.setUserId(user.getId()); |
log.setUserName(user.getName()); |
logUserRepository.save(log); |
} |
/** |
* Set the logUserRepository. |
* |
* @param logUserRepository the logUserRepository to set. |
*/ |
public void setLogUserRepository(@Lazy LogUserRepository logUserRepository) { |
this.logUserRepository = logUserRepository; |
} |
} |
/trunk/spring/spring-data-parent/jpa-listeners/src/main/resources/application-h2.yml |
---|
0,0 → 1,21 |
# =================================================================== |
# Standard Spring Boot properties. |
# Full reference is available at: |
# http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html |
# =================================================================== |
spring: |
datasource: |
url: jdbc:h2:mem:testdb;INIT=CREATE SCHEMA IF NOT EXISTS SPRING_JPA_LISTENERS;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE |
platform: h2 |
driver-class-name: org.h2.Driver |
username: sa |
password: |
jpa: |
hibernate: |
ddl-auto: create-drop |
database-platform: org.hibernate.dialect.H2Dialect |
properties: |
hibernate: |
show_sql: true |
# use_sql_comments: true |
# format_sql: true |
/trunk/spring/spring-data-parent/jpa-listeners/src/main/resources/application.yml |
---|
0,0 → 1,21 |
# =================================================================== |
# Standard Spring Boot properties. |
# Full reference is available at: |
# http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html |
# =================================================================== |
spring: |
application: |
name: '@project.name@' |
jpa: |
hibernate: |
ddl-auto: none |
show-sql: true |
properties: |
hibernate: |
default_schema: spring_jpa_listeners |
# Logging configuration |
logging: |
path: . |
level: |
root: INFO |
/trunk/spring/spring-data-parent/jpa-listeners/src/main/resources/application-mysql.yml |
---|
0,0 → 1,14 |
# =================================================================== |
# Standard Spring Boot properties. |
# Full reference is available at: |
# http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html |
# =================================================================== |
spring: |
datasource: |
url: jdbc:mysql://localhost:3306/spring_jpa_listeners |
platform: mysql |
driver-class-name: com.mysql.jdbc.Driver |
username: tutorial |
password: tutorial |
jpa: |
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect |
/trunk/spring/spring-data-parent/jpa-listeners/src/main/resources/application-postgre.yml |
---|
0,0 → 1,16 |
# =================================================================== |
# Standard Spring Boot properties. |
# Full reference is available at: |
# http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html |
# =================================================================== |
spring: |
datasource: |
url: jdbc:postgresql://localhost:5432/study?currentSchema=spring_jpa_listeners |
platform: postgres |
driver-class-name: org.postgresql.Driver |
# username: tutorial |
# password: tutorial |
username: postgres |
password: postgres |
jpa: |
database-platform: org.hibernate.dialect.PostgreSQLDialect |
/trunk/spring/spring-data-parent/jpa-listeners/src/test/java/fr/ejn/tutorial/spring/data/model/TutorialLogUserTest.java |
---|
0,0 → 1,33 |
package fr.ejn.tutorial.spring.data.model; |
import org.junit.After; |
import org.junit.AfterClass; |
import org.junit.Before; |
import org.junit.BeforeClass; |
import org.junit.Test; |
import org.meanbean.test.BeanTester; |
public class TutorialLogUserTest { |
@BeforeClass |
public static void setUpBeforeClass() throws Exception { |
} |
@AfterClass |
public static void tearDownAfterClass() throws Exception { |
} |
@Before |
public void setUp() throws Exception { |
} |
@After |
public void tearDown() throws Exception { |
} |
@Test |
public void testInstance() { |
new BeanTester().testBean(TutorialLogUser.class); |
} |
} |
/trunk/spring/spring-data-parent/jpa-listeners/src/test/java/fr/ejn/tutorial/spring/data/model/TutorialUserTest.java |
---|
0,0 → 1,33 |
package fr.ejn.tutorial.spring.data.model; |
import org.junit.After; |
import org.junit.AfterClass; |
import org.junit.Before; |
import org.junit.BeforeClass; |
import org.junit.Test; |
import org.meanbean.test.BeanTester; |
public class TutorialUserTest { |
@BeforeClass |
public static void setUpBeforeClass() throws Exception { |
} |
@AfterClass |
public static void tearDownAfterClass() throws Exception { |
} |
@Before |
public void setUp() throws Exception { |
} |
@After |
public void tearDown() throws Exception { |
} |
@Test |
public void testInstance() { |
new BeanTester().testBean(TutorialUser.class); |
} |
} |
/trunk/spring/spring-data-parent/jpa-listeners/src/test/java/fr/ejn/tutorial/spring/data/support/LogActionListenerTest.java |
---|
0,0 → 1,138 |
package fr.ejn.tutorial.spring.data.support; |
import org.assertj.core.api.Assertions; |
import org.junit.After; |
import org.junit.AfterClass; |
import org.junit.Before; |
import org.junit.BeforeClass; |
import org.junit.Test; |
import org.junit.runner.RunWith; |
import org.mockito.Mockito; |
import org.mockito.invocation.InvocationOnMock; |
import org.mockito.runners.MockitoJUnitRunner; |
import org.mockito.stubbing.Answer; |
import fr.ejn.tutorial.spring.data.dao.LogUserRepository; |
import fr.ejn.tutorial.spring.data.model.TutorialLogUser; |
import fr.ejn.tutorial.spring.data.model.TutorialUser; |
@RunWith(MockitoJUnitRunner.class) |
public class LogActionListenerTest { |
@BeforeClass |
public static void setUpBeforeClass() throws Exception { |
} |
@AfterClass |
public static void tearDownAfterClass() throws Exception { |
} |
private TutorialLogUser actualEvent; |
private TutorialLogUser expectedEvent; |
private LogActionListener instance; |
private TutorialUser tutorialUser; |
@Before |
public void setUp() throws Exception { |
actualEvent = null; |
LogUserRepository logUserRepository = Mockito.mock(LogUserRepository.class); |
Mockito.doAnswer(new Answer<Object>() { |
@Override |
public Object answer(InvocationOnMock invocation) throws Throwable { |
TutorialLogUser argument = invocation.getArgumentAt(0, TutorialLogUser.class); |
actualEvent = argument; |
return argument; |
} |
}).when(logUserRepository).save(Mockito.any(TutorialLogUser.class)); |
instance = new LogActionListener(); |
instance.setLogUserRepository(logUserRepository); |
tutorialUser = new TutorialUser(); |
tutorialUser.setId(1L); |
tutorialUser.setName("user name"); |
tutorialUser.setAge(18); |
expectedEvent = new TutorialLogUser(); |
// Event date is completed with JPA annotation. |
// expectedEvent.setEventDate(eventDate); |
// The event name is completed in the test function. |
// expectedEvent.setEventName(eventName); |
// Id is set during the real save in JPA. |
// expectedEvent.setId(id); |
expectedEvent.setUserId(1L); |
expectedEvent.setUserName("user name"); |
} |
@After |
public void tearDown() throws Exception { |
} |
@Test |
public void testOnPostLoad() throws Exception { |
instance.onPostLoad(tutorialUser); |
expectedEvent.setEventName("load"); |
Assertions.assertThat(actualEvent).isEqualToComparingFieldByField(expectedEvent); |
} |
@Test |
public void testOnPostPersist() throws Exception { |
instance.onPostPersist(tutorialUser); |
expectedEvent.setEventName("saved"); |
Assertions.assertThat(actualEvent).isEqualToComparingFieldByField(expectedEvent); |
} |
@Test |
public void testOnPostRemove() throws Exception { |
instance.onPostRemove(tutorialUser); |
expectedEvent.setEventName("deleted"); |
Assertions.assertThat(actualEvent).isEqualToComparingFieldByField(expectedEvent); |
} |
@Test |
public void testOnPostUpdate() throws Exception { |
instance.onPostUpdate(tutorialUser); |
expectedEvent.setEventName("updated"); |
Assertions.assertThat(actualEvent).isEqualToComparingFieldByField(expectedEvent); |
} |
@Test |
public void testOnPrePersist() throws Exception { |
instance.onPrePersist(tutorialUser); |
expectedEvent.setEventName("before save"); |
Assertions.assertThat(actualEvent).isEqualToComparingFieldByField(expectedEvent); |
} |
@Test |
public void testOnPreRemove() throws Exception { |
instance.onPreRemove(tutorialUser); |
expectedEvent.setEventName("before remove"); |
Assertions.assertThat(actualEvent).isEqualToComparingFieldByField(expectedEvent); |
} |
@Test |
public void testOnPreUpdate() throws Exception { |
instance.onPreUpdate(tutorialUser); |
expectedEvent.setEventName("before update"); |
Assertions.assertThat(actualEvent).isEqualToComparingFieldByField(expectedEvent); |
} |
} |
/trunk/spring/spring-data-parent/jpa-listeners/src/test/resources/initDatabase-mysql.sql |
---|
0,0 → 1,28 |
create database if not exists spring_jpa_listeners character set = utf8 collate utf8_general_ci; |
create table if not exists spring_jpa_listeners.app_user ( |
user_id mediumint not null auto_increment, |
user_name varchar(100) not null, |
user_age int null, |
primary key (user_id) |
) |
engine=InnoDB |
default charset=utf8 |
collate=utf8_general_ci; |
create table if not exists spring_jpa_listeners.app_log ( |
log_id mediumint not null auto_increment, |
event_date datetime not null, |
event_name varchar(15) not null, |
user_id mediumint, |
user_name varchar(100), |
primary key (log_id) |
) |
engine=InnoDB |
default charset=utf8 |
collate=utf8_general_ci; |
create user 'tutorial'@'localhost' identified by 'tutorial'; |
grant select, insert, update, delete on spring_jpa_listeners.app_user to 'tutorial'@'localhost'; |
grant select, insert on spring_jpa_listeners.app_log to 'tutorial'@'localhost'; |
/trunk/spring/spring-data-parent/jpa-listeners/src/test/resources/initDatabase-postgre.sql |
---|
0,0 → 1,29 |
create schema if not exists "spring_jpa_listeners" |
create table "spring_jpa_listeners".app_user ( |
user_id serial not null, |
user_name varchar(100) not null, |
user_age int null, |
constraint pk_app_user PRIMARY KEY (user_id) |
) |
WITH ( |
OIDS=FALSE |
); |
create table spring_jpa_listeners.app_log ( |
log_id serial not null, |
event_date timestamp not null, |
event_name varchar(15) not null, |
user_id int4, |
user_name varchar(100), |
constraint pk_app_log PRIMARY KEY (log_id) |
) |
WITH ( |
OIDS=FALSE |
); |
create user tutorial with encrypted password 'tutorial'; |
grant usage on schema spring_jpa_listeners to tutorial; |
grant select, insert, update, delete on table spring_jpa_listeners.app_user to tutorial; |
grant select, insert on table spring_jpa_listeners.app_log to tutorial; |
/trunk/spring/spring-data-parent/jpa-listeners/src/test/resources/logback.xml |
---|
0,0 → 1,14 |
<?xml version="1.0" encoding="UTF-8"?> |
<configuration> |
<include resource="org/springframework/boot/logging/logback/defaults.xml" /> |
<include resource="org/springframework/boot/logging/logback/console-appender.xml" /> |
<logger name="fr.ejn.tutorial" level="info"> |
</logger> |
<root level="error"> |
<appender-ref ref="CONSOLE" /> |
</root> |
</configuration> |
/trunk/spring/spring-data-parent/jpa-listeners/aop.xml |
---|
0,0 → 1,6 |
<?xml version="1.0" encoding="UTF-8"?> |
<aspectj> |
<aspects> |
<aspect name="org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect" /> |
</aspects> |
</aspectj> |
/trunk/spring/spring-data-parent/pom.xml |
---|
0,0 → 1,85 |
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
<modelVersion>4.0.0</modelVersion> |
<parent> |
<groupId>fr.ejn.tutorial.spring</groupId> |
<artifactId>spring-parent</artifactId> |
<version>0.0.1-SNAPSHOT</version> |
</parent> |
<groupId>fr.ejn.tutorial.spring.spring-data</groupId> |
<artifactId>spring-data-parent</artifactId> |
<packaging>pom</packaging> |
<name>Spring Data</name> |
<description>Study Spring Data framework</description> |
<modules> |
<module>hibernate-dynamic-annotations</module> |
<module>jpa-listeners</module> |
</modules> |
<properties> |
<maven.compiler.source>1.8</maven.compiler.source> |
<maven.compiler.target>1.8</maven.compiler.target> |
<source.level>1.8</source.level> |
</properties> |
<dependencyManagement> |
<dependencies> |
<!-- Lombok --> |
<dependency> |
<groupId>org.projectlombok</groupId> |
<artifactId>lombok</artifactId> |
<version>1.18.4</version> |
</dependency> |
<!-- H2 --> |
<dependency> |
<groupId>com.h2database</groupId> |
<artifactId>h2</artifactId> |
<version>1.4.197</version> |
</dependency> |
<!-- Postgre --> |
<dependency> |
<groupId>org.postgresql</groupId> |
<artifactId>postgresql</artifactId> |
<version>42.2.5</version> |
</dependency> |
<!-- MySQL --> |
<dependency> |
<groupId>mysql</groupId> |
<artifactId>mysql-connector-java</artifactId> |
<version>5.1.47</version> |
</dependency> |
</dependencies> |
</dependencyManagement> |
<dependencies> |
<!-- Spring dependencies --> |
<dependency> |
<groupId>org.springframework.boot</groupId> |
<artifactId>spring-boot-configuration-processor</artifactId> |
</dependency> |
<dependency> |
<groupId>org.springframework.boot</groupId> |
<artifactId>spring-boot-starter-data-jpa</artifactId> |
</dependency> |
</dependencies> |
<build> |
<plugins> |
<plugin> |
<groupId>org.apache.maven.plugins</groupId> |
<artifactId>maven-compiler-plugin</artifactId> |
<configuration> |
<source>1.8</source> |
<target>1.8</target> |
</configuration> |
</plugin> |
</plugins> |
</build> |
</project> |