Subversion Repositories Study

Compare Revisions

Ignore whitespace Rev 352 → Rev 353

/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>