diff --git a/JGit/README.md b/JGit/README.md
new file mode 100644
index 0000000000..5c65f1101b
--- /dev/null
+++ b/JGit/README.md
@@ -0,0 +1,3 @@
+## Relevant articles:
+
+- [A Guide to JGit](http://www.baeldung.com/jgit)
diff --git a/algorithms/README.md b/algorithms/README.md
new file mode 100644
index 0000000000..42f696d9be
--- /dev/null
+++ b/algorithms/README.md
@@ -0,0 +1,4 @@
+## Relevant articles:
+
+- [Dijkstra Algorithm in Java](http://www.baeldung.com/java-dijkstra)
+- [Introduction to Cobertura](http://www.baeldung.com/cobertura)
diff --git a/algorithms/pom.xml b/algorithms/pom.xml
index 0c85a19534..f72457650a 100644
--- a/algorithms/pom.xml
+++ b/algorithms/pom.xml
@@ -41,4 +41,23 @@
-
\ No newline at end of file
+
+
+
+ org.codehaus.mojo
+ cobertura-maven-plugin
+ 2.7
+
+
+
+ com/baeldung/algorithms/dijkstra/*
+
+
+ com/baeldung/algorithms/dijkstra/*
+
+
+
+
+
+
+
diff --git a/apache-bval/README.md b/apache-bval/README.md
new file mode 100644
index 0000000000..80ea149993
--- /dev/null
+++ b/apache-bval/README.md
@@ -0,0 +1,2 @@
+### Relevant Articles:
+- [Intro to Apache BVal](http://www.baeldung.com/apache-bval)
diff --git a/apache-bval/pom.xml b/apache-bval/pom.xml
new file mode 100644
index 0000000000..5d556af56f
--- /dev/null
+++ b/apache-bval/pom.xml
@@ -0,0 +1,51 @@
+
+ 4.0.0
+ apache-bval
+ apache-bval
+ 0.0.1-SNAPSHOT
+
+
+
+ org.apache.bval
+ bval-jsr
+ ${bval.version}
+
+
+ javax.validation
+ validation-api
+ 1.1.0.Final
+
+
+ org.apache.bval
+ bval-extras
+ ${bval.version}
+
+
+
+ junit
+ junit
+ ${junit.version}
+ test
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ ${maven-compiler-plugin.version}
+
+
+ 1.8
+
+
+
+
+
+ 3.6.0
+ 4.12
+ 1.1.2
+
+
\ No newline at end of file
diff --git a/apache-bval/src/main/java/com/baeldung/model/User.java b/apache-bval/src/main/java/com/baeldung/model/User.java
new file mode 100644
index 0000000000..477136ddb4
--- /dev/null
+++ b/apache-bval/src/main/java/com/baeldung/model/User.java
@@ -0,0 +1,120 @@
+package com.baeldung.model;
+
+import java.io.File;
+
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+
+import org.apache.bval.constraints.Email;
+import org.apache.bval.constraints.NotEmpty;
+import org.apache.bval.extras.constraints.checkdigit.IBAN;
+import org.apache.bval.extras.constraints.creditcard.Visa;
+import org.apache.bval.extras.constraints.file.Directory;
+import org.apache.bval.extras.constraints.net.InetAddress;
+
+import com.baeldung.validation.Password;
+
+public class User {
+ @NotNull
+ @Email
+ private String email;
+
+ @NotEmpty
+ @Password
+ private String password;
+
+ @Size(min = 1, max = 20)
+ private String name;
+
+ @Min(18)
+ private int age;
+
+ @Visa
+ private String cardNumber = "";
+
+ @IBAN
+ private String iban = "";
+
+ @InetAddress
+ private String website = "";
+
+ @Directory
+ private File mainDirectory=new File(".");
+
+ public User() {
+ }
+
+ public User(String email, String password, String name, int age) {
+ super();
+ this.email = email;
+ this.password = password;
+ this.name = name;
+ this.age = age;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public void setEmail(String email) {
+ this.email = email;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public int getAge() {
+ return age;
+ }
+
+ public void setAge(int age) {
+ this.age = age;
+ }
+
+ public String getCardNumber() {
+ return cardNumber;
+ }
+
+ public void setCardNumber(String cardNumber) {
+ this.cardNumber = cardNumber;
+ }
+
+ public String getIban() {
+ return iban;
+ }
+
+ public void setIban(String iban) {
+ this.iban = iban;
+ }
+
+ public String getWebsite() {
+ return website;
+ }
+
+ public void setWebsite(String website) {
+ this.website = website;
+ }
+
+ public File getMainDirectory() {
+ return mainDirectory;
+ }
+
+ public void setMainDirectory(File mainDirectory) {
+ this.mainDirectory = mainDirectory;
+ }
+
+}
diff --git a/apache-bval/src/main/java/com/baeldung/validation/Password.java b/apache-bval/src/main/java/com/baeldung/validation/Password.java
new file mode 100644
index 0000000000..4ae06b2fb0
--- /dev/null
+++ b/apache-bval/src/main/java/com/baeldung/validation/Password.java
@@ -0,0 +1,25 @@
+package com.baeldung.validation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+
+import static java.lang.annotation.ElementType.*;
+
+@Constraint(validatedBy = { PasswordValidator.class })
+@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Password {
+ String message() default "Invalid password";
+
+ Class>[] groups() default {};
+
+ Class extends Payload>[] payload() default {};
+
+ int length() default 6;
+
+ int nonAlpha() default 1;
+}
diff --git a/apache-bval/src/main/java/com/baeldung/validation/PasswordValidator.java b/apache-bval/src/main/java/com/baeldung/validation/PasswordValidator.java
new file mode 100644
index 0000000000..19038d04d5
--- /dev/null
+++ b/apache-bval/src/main/java/com/baeldung/validation/PasswordValidator.java
@@ -0,0 +1,35 @@
+package com.baeldung.validation;
+
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+
+public class PasswordValidator implements ConstraintValidator {
+
+ private int length;
+ private int nonAlpha;
+
+ @Override
+ public void initialize(Password password) {
+ this.length = password.length();
+ this.nonAlpha = password.nonAlpha();
+
+ }
+
+ @Override
+ public boolean isValid(String value, ConstraintValidatorContext context) {
+ if (value.length() < length) {
+ return false;
+ }
+ int nonAlphaNr = 0;
+ for (int i = 0; i < value.length(); i++) {
+ if (!Character.isLetterOrDigit(value.charAt(i))) {
+ nonAlphaNr++;
+ }
+ }
+ if (nonAlphaNr < nonAlpha) {
+ return false;
+ }
+ return true;
+ }
+
+}
diff --git a/apache-bval/src/test/java/com/baeldung/validation/ValidationTest.java b/apache-bval/src/test/java/com/baeldung/validation/ValidationTest.java
new file mode 100644
index 0000000000..cd58d4460a
--- /dev/null
+++ b/apache-bval/src/test/java/com/baeldung/validation/ValidationTest.java
@@ -0,0 +1,97 @@
+package com.baeldung.validation;
+
+import java.io.File;
+import java.util.Set;
+
+import javax.validation.ConstraintViolation;
+import javax.validation.Validation;
+import javax.validation.Validator;
+import javax.validation.ValidatorFactory;
+
+import org.apache.bval.jsr.ApacheValidationProvider;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+import com.baeldung.model.User;
+
+public class ValidationTest {
+ private static ValidatorFactory validatorFactory;
+ private static Validator validator;
+
+ @BeforeClass
+ public static void setup() {
+ validatorFactory = Validation.byProvider(ApacheValidationProvider.class)
+ .configure()
+ .buildValidatorFactory();
+ validator = validatorFactory.getValidator();
+ }
+
+ @Test
+ public void givenUser_whenValidate_thenValidationViolations() {
+ User user = new User("ana@yahoo.com", "pass", "nameTooLong_______________", 15);
+
+ Set> violations = validator.validate(user);
+ assertTrue("no violations", violations.size() > 0);
+ }
+
+ @Test
+ public void givenInvalidAge_whenValidateProperty_thenConstraintViolation() {
+ User user = new User("ana@yahoo.com", "pass", "Ana", 12);
+
+ Set> propertyViolations = validator.validateProperty(user, "age");
+ assertEquals("size is not 1", 1, propertyViolations.size());
+ }
+
+ @Test
+ public void givenValidAge_whenValidateValue_thenNoConstraintViolation() {
+ User user = new User("ana@yahoo.com", "pass", "Ana", 18);
+
+ Set> valueViolations = validator.validateValue(User.class, "age", 20);
+ assertEquals("size is not 0", 0, valueViolations.size());
+ }
+
+ @Test
+ public void whenValidateNonJSR_thenCorrect() {
+ User user = new User("ana@yahoo.com", "pass", "Ana", 20);
+ user.setCardNumber("1234");
+ user.setIban("1234");
+ user.setWebsite("10.0.2.50");
+ user.setMainDirectory(new File("."));
+
+ Set> violations = validator.validateProperty(user, "iban");
+ assertEquals("size is not 1", 1, violations.size());
+
+ violations = validator.validateProperty(user, "website");
+ assertEquals("size is not 0", 0, violations.size());
+
+ violations = validator.validateProperty(user, "mainDirectory");
+ assertEquals("size is not 0", 0, violations.size());
+ }
+
+ @Test
+ public void givenInvalidPassword_whenValidatePassword_thenConstraintViolation() {
+ User user = new User("ana@yahoo.com", "password", "Ana", 20);
+ Set> violations = validator.validateProperty(user, "password");
+ assertEquals("message incorrect", "Invalid password", violations.iterator()
+ .next()
+ .getMessage());
+ }
+
+ @Test
+ public void givenValidPassword_whenValidatePassword_thenNoConstraintViolation() {
+ User user = new User("ana@yahoo.com", "password#", "Ana", 20);
+
+ Set> violations = validator.validateProperty(user, "password");
+ assertEquals("size is not 0", 0, violations.size());
+ }
+
+ @AfterClass
+ public static void close() {
+ if (validatorFactory != null) {
+ validatorFactory.close();
+ }
+ }
+}
diff --git a/apache-solrj/pom.xml b/apache-solrj/pom.xml
new file mode 100644
index 0000000000..74daeae55c
--- /dev/null
+++ b/apache-solrj/pom.xml
@@ -0,0 +1,50 @@
+
+ 4.0.0
+ com.baeldung
+ apache-solrj
+ 0.0.1-SNAPSHOT
+ jar
+ apache-solrj
+
+
+ 4.12
+ 2.19.1
+
+
+
+
+ org.apache.solr
+ solr-solrj
+ 6.4.0
+
+
+ junit
+ junit
+ ${junit.version}
+ test
+
+
+
+
+
+
+ maven-compiler-plugin
+ 2.3.2
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ ${maven-surefire-plugin.version}
+
+
+ 1.8
+
+ **/*IntegrationTest.java
+ **/*LiveTest.java
+
+
+
+
+
+
\ No newline at end of file
diff --git a/apache-solrj/src/main/java/com/baeldung/solrjava/SolrJavaIntegration.java b/apache-solrj/src/main/java/com/baeldung/solrjava/SolrJavaIntegration.java
new file mode 100644
index 0000000000..f2d21f0993
--- /dev/null
+++ b/apache-solrj/src/main/java/com/baeldung/solrjava/SolrJavaIntegration.java
@@ -0,0 +1,43 @@
+package com.baeldung.solrjava;
+
+import java.io.IOException;
+
+import org.apache.solr.client.solrj.SolrServerException;
+import org.apache.solr.client.solrj.impl.HttpSolrClient;
+import org.apache.solr.client.solrj.impl.XMLResponseParser;
+import org.apache.solr.common.SolrInputDocument;
+
+public class SolrJavaIntegration {
+
+ private HttpSolrClient solrClient;
+
+ public SolrJavaIntegration(String clientUrl) {
+
+ solrClient = new HttpSolrClient.Builder(clientUrl).build();
+ solrClient.setParser(new XMLResponseParser());
+ }
+
+ public void addSolrDocument(String documentId, String itemName, String itemPrice) throws SolrServerException, IOException {
+
+ SolrInputDocument document = new SolrInputDocument();
+ document.addField("id", documentId);
+ document.addField("name", itemName);
+ document.addField("price", itemPrice);
+ solrClient.add(document);
+ solrClient.commit();
+ }
+
+ public void deleteSolrDocument(String documentId) throws SolrServerException, IOException {
+
+ solrClient.deleteById(documentId);
+ solrClient.commit();
+ }
+
+ protected HttpSolrClient getSolrClient() {
+ return solrClient;
+ }
+
+ protected void setSolrClient(HttpSolrClient solrClient) {
+ this.solrClient = solrClient;
+ }
+}
diff --git a/spring-data-solr/src/test/java/com/baeldung/solrjava/SolrJavaIntegrationTest.java b/apache-solrj/src/test/java/com/baeldung/solrjava/SolrJavaIntegrationTest.java
similarity index 57%
rename from spring-data-solr/src/test/java/com/baeldung/solrjava/SolrJavaIntegrationTest.java
rename to apache-solrj/src/test/java/com/baeldung/solrjava/SolrJavaIntegrationTest.java
index 1613ba5480..22f9eae8ee 100644
--- a/spring-data-solr/src/test/java/com/baeldung/solrjava/SolrJavaIntegrationTest.java
+++ b/apache-solrj/src/test/java/com/baeldung/solrjava/SolrJavaIntegrationTest.java
@@ -6,42 +6,31 @@ import java.io.IOException;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
-import org.apache.solr.client.solrj.impl.HttpSolrClient;
-import org.apache.solr.client.solrj.impl.XMLResponseParser;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
-import org.apache.solr.common.SolrInputDocument;
import org.junit.Before;
import org.junit.Test;
public class SolrJavaIntegrationTest {
- private HttpSolrClient solr;
+ private SolrJavaIntegration solrJavaIntegration;
@Before
public void setUp() throws Exception {
- solr = new HttpSolrClient("http://localhost:8983/solr/bigboxstore");
- solr.setParser(new XMLResponseParser());
+ solrJavaIntegration = new SolrJavaIntegration("http://localhost:8983/solr/bigboxstore");
+ solrJavaIntegration.addSolrDocument("123456", "Kenmore Dishwasher", "599.99");
}
@Test
- public void givenAdd_thenVerifyAdded() throws SolrServerException, IOException {
-
- SolrInputDocument document = new SolrInputDocument();
- document.addField("id", "123456");
- document.addField("name", "Kenmore Dishwasher");
- document.addField("price", "599.99");
-
- solr.add(document);
- solr.commit();
+ public void whenAdd_thenVerifyAdded() throws SolrServerException, IOException {
SolrQuery query = new SolrQuery();
query.set("q", "id:123456");
QueryResponse response = null;
- response = solr.query(query);
+ response = solrJavaIntegration.getSolrClient().query(query);
SolrDocumentList docList = response.getResults();
assertEquals(docList.getNumFound(), 1);
@@ -53,16 +42,15 @@ public class SolrJavaIntegrationTest {
}
@Test
- public void givenDelete_thenVerifyDeleted() throws SolrServerException, IOException {
+ public void whenDelete_thenVerifyDeleted() throws SolrServerException, IOException {
- solr.deleteById("123456");
- solr.commit();
+ solrJavaIntegration.deleteSolrDocument("123456");
SolrQuery query = new SolrQuery();
query.set("q", "id:123456");
QueryResponse response = null;
- response = solr.query(query);
+ response = solrJavaIntegration.getSolrClient().query(query);
SolrDocumentList docList = response.getResults();
assertEquals(docList.getNumFound(), 0);
diff --git a/apache-thrift/README.md b/apache-thrift/README.md
new file mode 100644
index 0000000000..d8b9195dcc
--- /dev/null
+++ b/apache-thrift/README.md
@@ -0,0 +1,3 @@
+## Relevant articles:
+
+- [Working with Apache Thrift](http://www.baeldung.com/apache-thrift)
diff --git a/apache-velocity/README.md b/apache-velocity/README.md
new file mode 100644
index 0000000000..53c67f847e
--- /dev/null
+++ b/apache-velocity/README.md
@@ -0,0 +1,3 @@
+## Relevant articles:
+
+- [Introduction to Apache Velocity](http://www.baeldung.com/apache-velocity)
diff --git a/aws/pom.xml b/aws/pom.xml
index f3ae672a2f..681b76cfd4 100644
--- a/aws/pom.xml
+++ b/aws/pom.xml
@@ -7,17 +7,36 @@
jar
aws
+
+ 2.5
+ 1.3.0
+ 1.1.0
+ 2.8.0
+
+
com.amazonaws
aws-lambda-java-core
- 1.1.0
+ ${aws-lambda-java-core.version}
+
+
+
+ com.amazonaws
+ aws-lambda-java-events
+ ${aws-lambda-java-events.version}
commons-io
commons-io
- 2.5
+ ${commons-io.version}
+
+
+
+ com.google.code.gson
+ gson
+ ${gson.version}
@@ -26,7 +45,7 @@
org.apache.maven.plugins
maven-shade-plugin
- 2.3
+ 3.0.0
false
diff --git a/aws/src/main/java/com/baeldung/lambda/dynamodb/SavePersonHandler.java b/aws/src/main/java/com/baeldung/lambda/dynamodb/SavePersonHandler.java
new file mode 100644
index 0000000000..625da62efd
--- /dev/null
+++ b/aws/src/main/java/com/baeldung/lambda/dynamodb/SavePersonHandler.java
@@ -0,0 +1,49 @@
+package com.baeldung.lambda.dynamodb;
+
+import com.amazonaws.regions.Region;
+import com.amazonaws.regions.Regions;
+import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
+import com.amazonaws.services.dynamodbv2.document.DynamoDB;
+import com.amazonaws.services.dynamodbv2.document.Item;
+import com.amazonaws.services.dynamodbv2.document.PutItemOutcome;
+import com.amazonaws.services.dynamodbv2.document.spec.PutItemSpec;
+import com.amazonaws.services.dynamodbv2.model.ConditionalCheckFailedException;
+import com.amazonaws.services.lambda.runtime.Context;
+import com.amazonaws.services.lambda.runtime.RequestHandler;
+import com.baeldung.lambda.dynamodb.bean.PersonRequest;
+import com.baeldung.lambda.dynamodb.bean.PersonResponse;
+
+public class SavePersonHandler implements RequestHandler {
+
+ private DynamoDB dynamoDb;
+
+ private String DYNAMODB_TABLE_NAME = "Person";
+ private Regions REGION = Regions.US_WEST_2;
+
+ public PersonResponse handleRequest(PersonRequest personRequest, Context context) {
+ this.initDynamoDbClient();
+
+ persistData(personRequest);
+
+ PersonResponse personResponse = new PersonResponse();
+ personResponse.setMessage("Saved Successfully!!!");
+ return personResponse;
+ }
+
+ private PutItemOutcome persistData(PersonRequest personRequest) throws ConditionalCheckFailedException {
+ return this.dynamoDb.getTable(DYNAMODB_TABLE_NAME)
+ .putItem(
+ new PutItemSpec().withItem(new Item()
+ .withNumber("id", personRequest.getId())
+ .withString("firstName", personRequest.getFirstName())
+ .withString("lastName", personRequest.getLastName())
+ .withNumber("age", personRequest.getAge())
+ .withString("address", personRequest.getAddress())));
+ }
+
+ private void initDynamoDbClient() {
+ AmazonDynamoDBClient client = new AmazonDynamoDBClient();
+ client.setRegion(Region.getRegion(REGION));
+ this.dynamoDb = new DynamoDB(client);
+ }
+}
diff --git a/aws/src/main/java/com/baeldung/lambda/dynamodb/bean/PersonRequest.java b/aws/src/main/java/com/baeldung/lambda/dynamodb/bean/PersonRequest.java
new file mode 100644
index 0000000000..0c0706e676
--- /dev/null
+++ b/aws/src/main/java/com/baeldung/lambda/dynamodb/bean/PersonRequest.java
@@ -0,0 +1,67 @@
+package com.baeldung.lambda.dynamodb.bean;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+public class PersonRequest {
+ private int id;
+ private String firstName;
+ private String lastName;
+ private int age;
+ private String address;
+
+ public static void main(String[] args) {
+ PersonRequest personRequest = new PersonRequest();
+ personRequest.setId(1);
+ personRequest.setFirstName("John");
+ personRequest.setLastName("Doe");
+ personRequest.setAge(30);
+ personRequest.setAddress("United States");
+ System.out.println(personRequest);
+ }
+
+ public String toString() {
+ final Gson gson = new GsonBuilder().setPrettyPrinting().create();
+ return gson.toJson(this);
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getFirstName() {
+ return firstName;
+ }
+
+ public void setFirstName(String firstName) {
+ this.firstName = firstName;
+ }
+
+ public String getLastName() {
+ return lastName;
+ }
+
+ public void setLastName(String lastName) {
+ this.lastName = lastName;
+ }
+
+ public int getAge() {
+ return age;
+ }
+
+ public void setAge(int age) {
+ this.age = age;
+ }
+
+ public String getAddress() {
+ return address;
+ }
+
+ public void setAddress(String address) {
+ this.address = address;
+ }
+}
diff --git a/aws/src/main/java/com/baeldung/lambda/dynamodb/bean/PersonResponse.java b/aws/src/main/java/com/baeldung/lambda/dynamodb/bean/PersonResponse.java
new file mode 100644
index 0000000000..a61294ddea
--- /dev/null
+++ b/aws/src/main/java/com/baeldung/lambda/dynamodb/bean/PersonResponse.java
@@ -0,0 +1,20 @@
+package com.baeldung.lambda.dynamodb.bean;
+
+import com.google.gson.Gson;
+
+public class PersonResponse {
+ private String message;
+
+ public String toString() {
+ final Gson gson = new Gson();
+ return gson.toJson(this);
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+}
diff --git a/core-java-9/README.md b/core-java-9/README.md
index 1b44239e40..53ad79e59c 100644
--- a/core-java-9/README.md
+++ b/core-java-9/README.md
@@ -6,3 +6,5 @@
### Relevant Articles:
- [Java 9 Stream API Improvements](http://www.baeldung.com/java-9-stream-api)
+- [Java 9 Convenience Factory Methods for Collections](http://www.baeldung.com/java-9-collections-factory-methods)
+- [New Stream Collectors in Java 9](http://www.baeldung.com/java9-stream-collectors)
diff --git a/core-java-9/pom.xml b/core-java-9/pom.xml
index 9d1ff29ef7..23473ff161 100644
--- a/core-java-9/pom.xml
+++ b/core-java-9/pom.xml
@@ -21,6 +21,11 @@
slf4j-api
${org.slf4j.version}
+
+ ch.qos.logback
+ logback-classic
+ ${ch.qos.logback.version}
+
org.hamcrest
@@ -76,9 +81,9 @@
1.7.21
-
+ 1.2.1
- 3.6-jigsaw-SNAPSHOT
+ 3.6.0
2.19.1
diff --git a/core-java-9/src/test/java/com/baeldung/java9/process/ProcessAPIEnhancementsTest.java b/core-java-9/src/test/java/com/baeldung/java9/process/ProcessAPIEnhancementsTest.java
new file mode 100644
index 0000000000..1129a10d17
--- /dev/null
+++ b/core-java-9/src/test/java/com/baeldung/java9/process/ProcessAPIEnhancementsTest.java
@@ -0,0 +1,133 @@
+package com.baeldung.java9.process;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.concurrent.CompletableFuture;
+import java.util.stream.Stream;
+
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Created by sanaulla on 2/23/2017.
+ */
+
+public class ProcessAPIEnhancementsTest {
+
+ Logger log = LoggerFactory.getLogger(ProcessAPIEnhancementsTest.class);
+
+ @Test
+ public void givenCurrentProcess_whenInvokeGetInfo_thenSuccess() throws IOException {
+ ProcessHandle processHandle = ProcessHandle.current();
+ ProcessHandle.Info processInfo = processHandle.info();
+ assertNotNull(processHandle.getPid());
+ assertEquals(false, processInfo.arguments()
+ .isPresent());
+ assertEquals(true, processInfo.command()
+ .isPresent());
+ assertTrue(processInfo.command()
+ .get()
+ .contains("java"));
+
+ assertEquals(true, processInfo.startInstant()
+ .isPresent());
+ assertEquals(true, processInfo.totalCpuDuration()
+ .isPresent());
+ assertEquals(true, processInfo.user()
+ .isPresent());
+ }
+
+ @Test
+ public void givenSpawnProcess_whenInvokeGetInfo_thenSuccess() throws IOException {
+
+ String javaCmd = ProcessUtils.getJavaCmd()
+ .getAbsolutePath();
+ ProcessBuilder processBuilder = new ProcessBuilder(javaCmd, "-version");
+ Process process = processBuilder.inheritIO()
+ .start();
+ ProcessHandle processHandle = process.toHandle();
+ ProcessHandle.Info processInfo = processHandle.info();
+ assertNotNull(processHandle.getPid());
+ assertEquals(false, processInfo.arguments()
+ .isPresent());
+ assertEquals(true, processInfo.command()
+ .isPresent());
+ assertTrue(processInfo.command()
+ .get()
+ .contains("java"));
+ assertEquals(true, processInfo.startInstant()
+ .isPresent());
+ assertEquals(true, processInfo.totalCpuDuration()
+ .isPresent());
+ assertEquals(true, processInfo.user()
+ .isPresent());
+ }
+
+ @Test
+ public void givenLiveProcesses_whenInvokeGetInfo_thenSuccess() {
+ Stream liveProcesses = ProcessHandle.allProcesses();
+ liveProcesses.filter(ProcessHandle::isAlive)
+ .forEach(ph -> {
+ assertNotNull(ph.getPid());
+ assertEquals(true, ph.info()
+ .command()
+ .isPresent());
+ assertEquals(true, ph.info()
+ .startInstant()
+ .isPresent());
+ assertEquals(true, ph.info()
+ .totalCpuDuration()
+ .isPresent());
+ assertEquals(true, ph.info()
+ .user()
+ .isPresent());
+ });
+ }
+
+ @Test
+ public void givenProcess_whenGetChildProcess_thenSuccess() throws IOException {
+ int childProcessCount = 5;
+ for (int i = 0; i < childProcessCount; i++) {
+ String javaCmd = ProcessUtils.getJavaCmd()
+ .getAbsolutePath();
+ ProcessBuilder processBuilder
+ = new ProcessBuilder(javaCmd, "-version");
+ processBuilder.inheritIO().start();
+ }
+
+ Stream children = ProcessHandle.current()
+ .children();
+ children.filter(ProcessHandle::isAlive)
+ .forEach(ph -> log.info("PID: {}, Cmd: {}", ph.getPid(), ph.info()
+ .command()));
+ Stream descendants = ProcessHandle.current()
+ .descendants();
+ descendants.filter(ProcessHandle::isAlive)
+ .forEach(ph -> log.info("PID: {}, Cmd: {}", ph.getPid(), ph.info()
+ .command()));
+ }
+
+ @Test
+ public void givenProcess_whenAddExitCallback_thenSuccess() throws Exception {
+ String javaCmd = ProcessUtils.getJavaCmd()
+ .getAbsolutePath();
+ ProcessBuilder processBuilder
+ = new ProcessBuilder(javaCmd, "-version");
+ Process process = processBuilder.inheritIO()
+ .start();
+ ProcessHandle processHandle = process.toHandle();
+
+ log.info("PID: {} has started", processHandle.getPid());
+ CompletableFuture onProcessExit = processHandle.onExit();
+ onProcessExit.get();
+ assertEquals(false, processHandle.isAlive());
+ onProcessExit.thenAccept(ph -> {
+ log.info("PID: {} has stopped", ph.getPid());
+ });
+ }
+
+}
diff --git a/core-java/0.004102810554955205 b/core-java/0.004102810554955205
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/core-java/0.04832801936270381 b/core-java/0.04832801936270381
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/core-java/0.5633433244738808 b/core-java/0.5633433244738808
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/core-java/0.6256429734439612 b/core-java/0.6256429734439612
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/core-java/0.9799201796740292 b/core-java/0.9799201796740292
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/core-java/README.md b/core-java/README.md
index 341dbdf910..a34908d8ae 100644
--- a/core-java/README.md
+++ b/core-java/README.md
@@ -58,3 +58,24 @@
- [Guide to java.util.concurrent.BlockingQueue](http://www.baeldung.com/java-blocking-queue)
- [Guide to CountDownLatch in Java](http://www.baeldung.com/java-countdown-latch)
- [How to Design a Genetic Algorithm in Java](http://www.baeldung.com/java-genetic-algorithm)
+- [A Guide to ConcurrentMap](http://www.baeldung.com/java-concurrent-map)
+- [Guide to PriorityBlockingQueue in Java](http://www.baeldung.com/java-priority-blocking-queue)
+- [Guide to Java 8 groupingBy Collector](http://www.baeldung.com/java-groupingby-collector)
+- [Avoiding the ConcurrentModificationException in Java](http://www.baeldung.com/java-concurrentmodificationexception)
+- [Guide to WeakHashMap in Java](http://www.baeldung.com/java-weakhashmap)
+- [Strategy Design Pattern in Java 8](http://www.baeldung.com/java-strategy-pattern)
+- [Java 8 and Infinite Streams](http://www.baeldung.com/java-inifinite-streams)
+- [Custom Thread Pools In Java 8 Parallel Streams](http://www.baeldung.com/java-8-parallel-streams-custom-threadpool)
+- [String Operations with Java Streams](http://www.baeldung.com/java-stream-operations-on-strings)
+- [Spring Security – Cache Control Headers](http://www.baeldung.com/spring-security-cache-control-headers)
+- [Basic Introduction to JMX](http://www.baeldung.com/java-management-extensions)
+- [AWS Lambda With Java](http://www.baeldung.com/java-aws-lambda)
+- [Introduction to Nashorn](http://www.baeldung.com/java-nashorn)
+- [Exceptions in Java 8 Lambda Expressions](http://www.baeldung.com/java-lambda-exceptions)
+- [Guide to the Guava BiMap](http://www.baeldung.com/guava-bimap)
+- [Iterable to Stream in Java](http://www.baeldung.com/java-iterable-to-stream)
+- [Java 8 Stream findFirst() vs. findAny()](http://www.baeldung.com/java-stream-findfirst-vs-findany)
+- [Chained Exceptions in Java](http://www.baeldung.com/java-chained-exceptions)
+- [The Java HashMap Under the Hood](http://www.baeldung.com/java-hashmap)
+- [A Guide to LinkedHashMap in Java](http://www.baeldung.com/java-linked-hashmap)
+- [A Guide to TreeMap in Java](http://www.baeldung.com/java-treemap)
diff --git a/core-java/src/main/java/com/baeldung/algorithms/RunAlgorithm.java b/core-java/src/main/java/com/baeldung/algorithms/RunAlgorithm.java
index 3f7c8bf4b3..22c5776293 100644
--- a/core-java/src/main/java/com/baeldung/algorithms/RunAlgorithm.java
+++ b/core-java/src/main/java/com/baeldung/algorithms/RunAlgorithm.java
@@ -2,7 +2,8 @@ package com.baeldung.algorithms;
import java.util.Scanner;
-import com.baeldung.algorithms.annealing.SimulatedAnnealing;
+import com.baeldung.algorithms.ga.annealing.SimulatedAnnealing;
+import com.baeldung.algorithms.ga.ant_colony.AntColonyOptimization;
import com.baeldung.algorithms.ga.binary.SimpleGeneticAlgorithm;
import com.baeldung.algorithms.slope_one.SlopeOne;
@@ -14,6 +15,7 @@ public class RunAlgorithm {
System.out.println("1 - Simulated Annealing");
System.out.println("2 - Slope One");
System.out.println("3 - Simple Genetic Algorithm");
+ System.out.println("4 - Ant Colony");
int decision = in.nextInt();
switch (decision) {
case 1:
@@ -27,6 +29,10 @@ public class RunAlgorithm {
SimpleGeneticAlgorithm ga = new SimpleGeneticAlgorithm();
ga.runAlgorithm(50, "1011000100000100010000100000100111001000000100000100000000001111");
break;
+ case 4:
+ AntColonyOptimization antColony = new AntColonyOptimization(21);
+ antColony.startAntOptimization();
+ break;
default:
System.out.println("Unknown option");
break;
diff --git a/core-java/src/main/java/com/baeldung/algorithms/annealing/City.java b/core-java/src/main/java/com/baeldung/algorithms/ga/annealing/City.java
similarity index 90%
rename from core-java/src/main/java/com/baeldung/algorithms/annealing/City.java
rename to core-java/src/main/java/com/baeldung/algorithms/ga/annealing/City.java
index 77e8652df0..cb5647f4d2 100644
--- a/core-java/src/main/java/com/baeldung/algorithms/annealing/City.java
+++ b/core-java/src/main/java/com/baeldung/algorithms/ga/annealing/City.java
@@ -1,4 +1,4 @@
-package com.baeldung.algorithms.annealing;
+package com.baeldung.algorithms.ga.annealing;
import lombok.Data;
diff --git a/core-java/src/main/java/com/baeldung/algorithms/annealing/SimulatedAnnealing.java b/core-java/src/main/java/com/baeldung/algorithms/ga/annealing/SimulatedAnnealing.java
similarity index 96%
rename from core-java/src/main/java/com/baeldung/algorithms/annealing/SimulatedAnnealing.java
rename to core-java/src/main/java/com/baeldung/algorithms/ga/annealing/SimulatedAnnealing.java
index a7dc974e97..bff64fc239 100644
--- a/core-java/src/main/java/com/baeldung/algorithms/annealing/SimulatedAnnealing.java
+++ b/core-java/src/main/java/com/baeldung/algorithms/ga/annealing/SimulatedAnnealing.java
@@ -1,4 +1,4 @@
-package com.baeldung.algorithms.annealing;
+package com.baeldung.algorithms.ga.annealing;
public class SimulatedAnnealing {
diff --git a/core-java/src/main/java/com/baeldung/algorithms/annealing/Travel.java b/core-java/src/main/java/com/baeldung/algorithms/ga/annealing/Travel.java
similarity index 97%
rename from core-java/src/main/java/com/baeldung/algorithms/annealing/Travel.java
rename to core-java/src/main/java/com/baeldung/algorithms/ga/annealing/Travel.java
index 9bf341fbbe..3139b49586 100644
--- a/core-java/src/main/java/com/baeldung/algorithms/annealing/Travel.java
+++ b/core-java/src/main/java/com/baeldung/algorithms/ga/annealing/Travel.java
@@ -1,4 +1,4 @@
-package com.baeldung.algorithms.annealing;
+package com.baeldung.algorithms.ga.annealing;
import java.util.ArrayList;
import java.util.Collections;
diff --git a/core-java/src/main/java/com/baeldung/algorithms/ga/ant_colony/Ant.java b/core-java/src/main/java/com/baeldung/algorithms/ga/ant_colony/Ant.java
new file mode 100644
index 0000000000..4ea23b799f
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/algorithms/ga/ant_colony/Ant.java
@@ -0,0 +1,37 @@
+package com.baeldung.algorithms.ga.ant_colony;
+
+public class Ant {
+
+ protected int trailSize;
+ protected int trail[];
+ protected boolean visited[];
+
+ public Ant(int tourSize) {
+ this.trailSize = tourSize;
+ this.trail = new int[tourSize];
+ this.visited = new boolean[tourSize];
+ }
+
+ protected void visitCity(int currentIndex, int city) {
+ trail[currentIndex + 1] = city;
+ visited[city] = true;
+ }
+
+ protected boolean visited(int i) {
+ return visited[i];
+ }
+
+ protected double trailLength(double graph[][]) {
+ double length = graph[trail[trailSize - 1]][trail[0]];
+ for (int i = 0; i < trailSize - 1; i++) {
+ length += graph[trail[i]][trail[i + 1]];
+ }
+ return length;
+ }
+
+ protected void clear() {
+ for (int i = 0; i < trailSize; i++)
+ visited[i] = false;
+ }
+
+}
diff --git a/core-java/src/main/java/com/baeldung/algorithms/ga/ant_colony/AntColonyOptimization.java b/core-java/src/main/java/com/baeldung/algorithms/ga/ant_colony/AntColonyOptimization.java
new file mode 100644
index 0000000000..e46ac77e84
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/algorithms/ga/ant_colony/AntColonyOptimization.java
@@ -0,0 +1,212 @@
+package com.baeldung.algorithms.ga.ant_colony;
+
+import java.util.Arrays;
+import java.util.Random;
+
+public class AntColonyOptimization {
+
+ private double c = 1.0;
+ private double alpha = 1;
+ private double beta = 5;
+ private double evaporation = 0.5;
+ private double Q = 500;
+ private double antFactor = 0.8;
+ private double randomFactor = 0.01;
+
+ private int maxIterations = 1000;
+
+ public int numberOfCities;
+ public int numberOfAnts;
+ private double graph[][];
+ private double trails[][];
+ private Ant ants[];
+ private Random random = new Random();
+ private double probabilities[];
+
+ private int currentIndex;
+
+ public int[] bestTourOrder;
+ public double bestTourLength;
+
+ public AntColonyOptimization(int noOfCities) {
+ graph = generateRandomMatrix(noOfCities);
+ numberOfCities = graph.length;
+ numberOfAnts = (int) (numberOfCities * antFactor);
+
+ trails = new double[numberOfCities][numberOfCities];
+ probabilities = new double[numberOfCities];
+ ants = new Ant[numberOfAnts];
+ for (int j = 0; j < numberOfAnts; j++) {
+ ants[j] = new Ant(numberOfCities);
+ }
+ }
+
+ /**
+ * Generate initial solution
+ * @param n
+ * @return
+ */
+ public double[][] generateRandomMatrix(int n) {
+ double[][] randomMatrix = new double[n][n];
+ random.setSeed(System.currentTimeMillis());
+ for (int i = 0; i < n; i++) {
+ for (int j = 0; j < n; j++) {
+ Integer r = random.nextInt(100) + 1;
+ randomMatrix[i][j] = Math.abs(r);
+ }
+ }
+ return randomMatrix;
+ }
+
+ /**
+ * Perform ant optimization
+ * @return
+ */
+ public int[] startAntOptimization() {
+ int[] finalResult = null;
+ for (int i = 1; i <= 3; i++) {
+ System.out.println("Attempt #" + i);
+ finalResult = solve();
+ }
+ return finalResult;
+ }
+
+ /**
+ * Use this method to run the main logic
+ * @return
+ */
+ private int[] solve() {
+ setupAnts();
+ clearTrails();
+ int iteration = 0;
+ while (iteration < maxIterations) {
+ moveAnts();
+ updateTrails();
+ updateBest();
+ iteration++;
+ }
+ System.out.println("Best tour length: " + (bestTourLength - numberOfCities));
+ System.out.println("Best tour order: " + Arrays.toString(bestTourOrder));
+ return bestTourOrder.clone();
+ }
+
+ /**
+ * Prepare ants for the simulation
+ */
+ private void setupAnts() {
+ currentIndex = -1;
+ for (int i = 0; i < numberOfAnts; i++) {
+ ants[i].clear();
+ ants[i].visitCity(currentIndex, random.nextInt(numberOfCities));
+ }
+ currentIndex++;
+ }
+
+ /**
+ * At each iteration, move ants
+ */
+ private void moveAnts() {
+ while (currentIndex < numberOfCities - 1) {
+ for (Ant a : ants)
+ a.visitCity(currentIndex, selectNextCity(a));
+ currentIndex++;
+ }
+ }
+
+ /**
+ * Select next city for each ant
+ * @param ant
+ * @return
+ */
+ private int selectNextCity(Ant ant) {
+ if (random.nextDouble() < randomFactor) {
+ int t = random.nextInt(numberOfCities - currentIndex);
+ int j = -1;
+ for (int i = 0; i < numberOfCities; i++) {
+ if (!ant.visited(i)) {
+ j++;
+ }
+ if (j == t) {
+ return i;
+ }
+ }
+ }
+ calculateProbabilities(ant);
+ double r = random.nextDouble();
+ double total = 0;
+ for (int i = 0; i < numberOfCities; i++) {
+ total += probabilities[i];
+ if (total >= r) {
+ return i;
+ }
+ }
+
+ throw new RuntimeException("There are no other cities");
+ }
+
+ /**
+ * Calculate the next city picks probabilites
+ * @param ant
+ */
+ private void calculateProbabilities(Ant ant) {
+ int i = ant.trail[currentIndex];
+ double pheromone = 0.0;
+ for (int l = 0; l < numberOfCities; l++) {
+ if (!ant.visited(l)) {
+ pheromone += Math.pow(trails[i][l], alpha) * Math.pow(1.0 / graph[i][l], beta);
+ }
+ }
+ for (int j = 0; j < numberOfCities; j++) {
+ if (ant.visited(j)) {
+ probabilities[j] = 0.0;
+ } else {
+ double numerator = Math.pow(trails[i][j], alpha) * Math.pow(1.0 / graph[i][j], beta);
+ probabilities[j] = numerator / pheromone;
+ }
+ }
+ }
+
+ /**
+ * Update trails that ants used
+ */
+ private void updateTrails() {
+ for (int i = 0; i < numberOfCities; i++) {
+ for (int j = 0; j < numberOfCities; j++) {
+ trails[i][j] *= evaporation;
+ }
+ }
+ for (Ant a : ants) {
+ double contribution = Q / a.trailLength(graph);
+ for (int i = 0; i < numberOfCities - 1; i++) {
+ trails[a.trail[i]][a.trail[i + 1]] += contribution;
+ }
+ trails[a.trail[numberOfCities - 1]][a.trail[0]] += contribution;
+ }
+ }
+
+ /**
+ * Update the best solution
+ */
+ private void updateBest() {
+ if (bestTourOrder == null) {
+ bestTourOrder = ants[0].trail;
+ bestTourLength = ants[0].trailLength(graph);
+ }
+ for (Ant a : ants) {
+ if (a.trailLength(graph) < bestTourLength) {
+ bestTourLength = a.trailLength(graph);
+ bestTourOrder = a.trail.clone();
+ }
+ }
+ }
+
+ /**
+ * Clear trails after simulation
+ */
+ private void clearTrails() {
+ for (int i = 0; i < numberOfCities; i++)
+ for (int j = 0; j < numberOfCities; j++)
+ trails[i][j] = c;
+ }
+
+}
diff --git a/core-java/src/main/java/com/baeldung/concurrent/locks/ReentrantLockWithCondition.java b/core-java/src/main/java/com/baeldung/concurrent/locks/ReentrantLockWithCondition.java
new file mode 100644
index 0000000000..4f061d2efd
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/concurrent/locks/ReentrantLockWithCondition.java
@@ -0,0 +1,83 @@
+package com.baeldung.concurrent.locks;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Stack;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
+
+import static java.lang.Thread.sleep;
+
+public class ReentrantLockWithCondition {
+
+ static Logger logger = LoggerFactory.getLogger(ReentrantLockWithCondition.class);
+
+ Stack stack = new Stack<>();
+ int CAPACITY = 5;
+
+ ReentrantLock lock = new ReentrantLock();
+ Condition stackEmptyCondition = lock.newCondition();
+ Condition stackFullCondition = lock.newCondition();
+
+ public void pushToStack(String item) throws InterruptedException {
+ try {
+ lock.lock();
+ if (stack.size() == CAPACITY) {
+ logger.info(Thread.currentThread().getName() + " wait on stack full");
+ stackFullCondition.await();
+ }
+ logger.info("Pushing the item " + item);
+ stack.push(item);
+ stackEmptyCondition.signalAll();
+ } finally {
+ lock.unlock();
+ }
+
+ }
+
+ public String popFromStack() throws InterruptedException {
+ try {
+ lock.lock();
+ if (stack.size() == 0) {
+ logger.info(Thread.currentThread().getName() + " wait on stack empty");
+ stackEmptyCondition.await();
+ }
+ return stack.pop();
+ } finally {
+ stackFullCondition.signalAll();
+ lock.unlock();
+ }
+ }
+
+ public static void main(String[] args) {
+ final int threadCount = 2;
+ ReentrantLockWithCondition object = new ReentrantLockWithCondition();
+ final ExecutorService service = Executors.newFixedThreadPool(threadCount);
+ service.execute(() -> {
+ for (int i = 0; i < 10; i++) {
+ try {
+ object.pushToStack("Item " + i);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ });
+
+ service.execute(() -> {
+ for (int i = 0; i < 10; i++) {
+ try {
+ logger.info("Item popped " + object.popFromStack());
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ });
+
+ service.shutdown();
+ }
+}
diff --git a/core-java/src/main/java/com/baeldung/concurrent/locks/SharedObjectWithLock.java b/core-java/src/main/java/com/baeldung/concurrent/locks/SharedObjectWithLock.java
new file mode 100644
index 0000000000..b6a4615638
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/concurrent/locks/SharedObjectWithLock.java
@@ -0,0 +1,92 @@
+package com.baeldung.concurrent.locks;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.ReentrantLock;
+
+import static java.lang.Thread.sleep;
+
+public class SharedObjectWithLock {
+
+ Logger logger = LoggerFactory.getLogger(SharedObjectWithLock.class);
+
+ ReentrantLock lock = new ReentrantLock(true);
+
+ int counter = 0;
+
+ public void perform() {
+
+ lock.lock();
+ logger.info("Thread - " + Thread.currentThread().getName() + " acquired the lock");
+ try {
+ logger.info("Thread - " + Thread.currentThread().getName() + " processing");
+ counter++;
+ } catch (Exception exception) {
+ logger.error(" Interrupted Exception ", exception);
+ } finally {
+ lock.unlock();
+ logger.info("Thread - " + Thread.currentThread().getName() + " released the lock");
+ }
+ }
+
+ public void performTryLock() {
+
+ logger.info("Thread - " + Thread.currentThread().getName() + " attempting to acquire the lock");
+ try {
+ boolean isLockAcquired = lock.tryLock(2, TimeUnit.SECONDS);
+ if (isLockAcquired) {
+ try {
+ logger.info("Thread - " + Thread.currentThread().getName() + " acquired the lock");
+
+ logger.info("Thread - " + Thread.currentThread().getName() + " processing");
+ sleep(1000);
+ } finally {
+ lock.unlock();
+ logger.info("Thread - " + Thread.currentThread().getName() + " released the lock");
+
+ }
+ }
+ } catch (InterruptedException exception) {
+ logger.error(" Interrupted Exception ", exception);
+ }
+ logger.info("Thread - " + Thread.currentThread().getName() + " could not acquire the lock");
+ }
+
+ public ReentrantLock getLock() {
+ return lock;
+ }
+
+ boolean isLocked() {
+ return lock.isLocked();
+ }
+
+ boolean hasQueuedThreads() {
+ return lock.hasQueuedThreads();
+ }
+
+ int getCounter() {
+ return counter;
+ }
+
+ public static void main(String[] args) {
+
+ final int threadCount = 2;
+ final ExecutorService service = Executors.newFixedThreadPool(threadCount);
+ final SharedObjectWithLock object = new SharedObjectWithLock();
+
+ service.execute(() -> {
+ object.perform();
+ });
+ service.execute(() -> {
+ object.performTryLock();
+ });
+
+ service.shutdown();
+
+ }
+
+}
diff --git a/core-java/src/main/java/com/baeldung/concurrent/locks/StampedLockDemo.java b/core-java/src/main/java/com/baeldung/concurrent/locks/StampedLockDemo.java
new file mode 100644
index 0000000000..0b0dbc72cb
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/concurrent/locks/StampedLockDemo.java
@@ -0,0 +1,104 @@
+package com.baeldung.concurrent.locks;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.locks.StampedLock;
+
+import static java.lang.Thread.sleep;
+
+public class StampedLockDemo {
+ Map map = new HashMap<>();
+ Logger logger = LoggerFactory.getLogger(StampedLockDemo.class);
+
+ private final StampedLock lock = new StampedLock();
+
+ public void put(String key, String value) throws InterruptedException {
+ long stamp = lock.writeLock();
+
+ try {
+ logger.info(Thread.currentThread().getName() + " acquired the write lock with stamp " + stamp);
+ map.put(key, value);
+ } finally {
+ lock.unlockWrite(stamp);
+ logger.info(Thread.currentThread().getName() + " unlocked the write lock with stamp " + stamp);
+ }
+ }
+
+ public String get(String key) throws InterruptedException {
+ long stamp = lock.readLock();
+ logger.info(Thread.currentThread().getName() + " acquired the read lock with stamp " + stamp);
+ try {
+ sleep(5000);
+ return map.get(key);
+
+ } finally {
+ lock.unlockRead(stamp);
+ logger.info(Thread.currentThread().getName() + " unlocked the read lock with stamp " + stamp);
+
+ }
+
+ }
+
+ public String readWithOptimisticLock(String key) throws InterruptedException {
+ long stamp = lock.tryOptimisticRead();
+ String value = map.get(key);
+
+ if (!lock.validate(stamp)) {
+ stamp = lock.readLock();
+ try {
+ sleep(5000);
+ return map.get(key);
+
+ } finally {
+ lock.unlock(stamp);
+ logger.info(Thread.currentThread().getName() + " unlocked the read lock with stamp " + stamp);
+
+ }
+ }
+ return value;
+ }
+
+ public static void main(String[] args) {
+ final int threadCount = 4;
+ final ExecutorService service = Executors.newFixedThreadPool(threadCount);
+ StampedLockDemo object = new StampedLockDemo();
+
+ Runnable writeTask = () -> {
+
+ try {
+ object.put("key1", "value1");
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ };
+ Runnable readTask = () -> {
+
+ try {
+ object.get("key1");
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ };
+ Runnable readOptimisticTask = () -> {
+
+ try {
+ object.readWithOptimisticLock("key1");
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ };
+ service.submit(writeTask);
+ service.submit(writeTask);
+ service.submit(readTask);
+ service.submit(readOptimisticTask);
+
+ service.shutdown();
+
+ }
+
+}
diff --git a/core-java/src/main/java/com/baeldung/concurrent/locks/SynchronizedHashMapWithRWLock.java b/core-java/src/main/java/com/baeldung/concurrent/locks/SynchronizedHashMapWithRWLock.java
new file mode 100644
index 0000000000..83b8b34fe9
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/concurrent/locks/SynchronizedHashMapWithRWLock.java
@@ -0,0 +1,120 @@
+package com.baeldung.concurrent.locks;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+import static java.lang.Thread.sleep;
+
+public class SynchronizedHashMapWithRWLock {
+
+ static Map syncHashMap = new HashMap<>();
+ Logger logger = LoggerFactory.getLogger(SynchronizedHashMapWithRWLock.class);
+
+ private final ReadWriteLock lock = new ReentrantReadWriteLock();
+ private final Lock readLock = lock.readLock();
+ private final Lock writeLock = lock.writeLock();
+
+ public void put(String key, String value) throws InterruptedException {
+
+ try {
+ writeLock.lock();
+ logger.info(Thread.currentThread().getName() + " writing");
+ syncHashMap.put(key, value);
+ sleep(1000);
+ } finally {
+ writeLock.unlock();
+ }
+
+ }
+
+ public String get(String key) {
+ try {
+ readLock.lock();
+ logger.info(Thread.currentThread().getName() + " reading");
+ return syncHashMap.get(key);
+ } finally {
+ readLock.unlock();
+ }
+ }
+
+ public String remove(String key) {
+ try {
+ writeLock.lock();
+ return syncHashMap.remove(key);
+ } finally {
+ writeLock.unlock();
+ }
+ }
+
+ public boolean containsKey(String key) {
+ try {
+ readLock.lock();
+ return syncHashMap.containsKey(key);
+ } finally {
+ readLock.unlock();
+ }
+ }
+
+ boolean isReadLockAvailable() {
+ return readLock.tryLock();
+ }
+
+ public static void main(String[] args) throws InterruptedException {
+
+ final int threadCount = 3;
+ final ExecutorService service = Executors.newFixedThreadPool(threadCount);
+ SynchronizedHashMapWithRWLock object = new SynchronizedHashMapWithRWLock();
+
+ service.execute(new Thread(new Writer(object), "Writer"));
+ service.execute(new Thread(new Reader(object), "Reader1"));
+ service.execute(new Thread(new Reader(object), "Reader2"));
+
+ service.shutdown();
+ }
+
+ private static class Reader implements Runnable {
+
+ SynchronizedHashMapWithRWLock object;
+
+ public Reader(SynchronizedHashMapWithRWLock object) {
+ this.object = object;
+ }
+
+ @Override
+ public void run() {
+ for (int i = 0; i < 10; i++) {
+ object.get("key" + i);
+ }
+ }
+ }
+
+ private static class Writer implements Runnable {
+
+ SynchronizedHashMapWithRWLock object;
+
+ public Writer(SynchronizedHashMapWithRWLock object) {
+ this.object = object;
+ }
+
+ @Override
+ public void run() {
+ for (int i = 0; i < 10; i++) {
+ try {
+ object.put("key" + i, "value" + i);
+ sleep(1000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+}
diff --git a/core-java/src/main/java/com/baeldung/list/listoflist/Pen.java b/core-java/src/main/java/com/baeldung/list/listoflist/Pen.java
new file mode 100644
index 0000000000..efbd88d0b1
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/list/listoflist/Pen.java
@@ -0,0 +1,18 @@
+package com.baeldung.list.listoflist;
+
+public class Pen implements Stationery {
+
+ public String name;
+
+ public Pen(String name) {
+ this.name = name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+}
\ No newline at end of file
diff --git a/core-java/src/main/java/com/baeldung/list/listoflist/Pencil.java b/core-java/src/main/java/com/baeldung/list/listoflist/Pencil.java
new file mode 100644
index 0000000000..7dfa119703
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/list/listoflist/Pencil.java
@@ -0,0 +1,18 @@
+package com.baeldung.list.listoflist;
+
+public class Pencil implements Stationery{
+
+ public String name;
+
+ public Pencil(String name) {
+ this.name = name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+}
\ No newline at end of file
diff --git a/core-java/src/main/java/com/baeldung/list/listoflist/Rubber.java b/core-java/src/main/java/com/baeldung/list/listoflist/Rubber.java
new file mode 100644
index 0000000000..7511139e14
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/list/listoflist/Rubber.java
@@ -0,0 +1,18 @@
+package com.baeldung.list.listoflist;
+
+public class Rubber implements Stationery {
+
+ public String name;
+
+ public Rubber(String name) {
+ this.name = name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+}
\ No newline at end of file
diff --git a/core-java/src/main/java/com/baeldung/list/listoflist/Stationery.java b/core-java/src/main/java/com/baeldung/list/listoflist/Stationery.java
new file mode 100644
index 0000000000..d914397cb8
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/list/listoflist/Stationery.java
@@ -0,0 +1,5 @@
+package com.baeldung.list.listoflist;
+
+public interface Stationery {
+
+}
diff --git a/core-java/src/test/java/com/baeldung/algorithms/AntColonyOptimizationTest.java b/core-java/src/test/java/com/baeldung/algorithms/AntColonyOptimizationTest.java
new file mode 100644
index 0000000000..cd8efaa106
--- /dev/null
+++ b/core-java/src/test/java/com/baeldung/algorithms/AntColonyOptimizationTest.java
@@ -0,0 +1,22 @@
+package com.baeldung.algorithms;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.baeldung.algorithms.ga.ant_colony.AntColonyOptimization;
+
+public class AntColonyOptimizationTest {
+
+ @Test
+ public void testGenerateRandomMatrix() {
+ AntColonyOptimization antTSP = new AntColonyOptimization(5);
+ Assert.assertNotNull(antTSP.generateRandomMatrix(5));
+ }
+
+ @Test
+ public void testStartAntOptimization() {
+ AntColonyOptimization antTSP = new AntColonyOptimization(5);
+ Assert.assertNotNull(antTSP.startAntOptimization());
+ }
+
+}
diff --git a/core-java/src/test/java/com/baeldung/algorithms/SimulatedAnnealingTest.java b/core-java/src/test/java/com/baeldung/algorithms/SimulatedAnnealingTest.java
index 2fc7ea9b92..6822bae990 100644
--- a/core-java/src/test/java/com/baeldung/algorithms/SimulatedAnnealingTest.java
+++ b/core-java/src/test/java/com/baeldung/algorithms/SimulatedAnnealingTest.java
@@ -3,7 +3,7 @@ package com.baeldung.algorithms;
import org.junit.Assert;
import org.junit.Test;
-import com.baeldung.algorithms.annealing.SimulatedAnnealing;
+import com.baeldung.algorithms.ga.annealing.SimulatedAnnealing;
public class SimulatedAnnealingTest {
diff --git a/core-java/src/test/java/com/baeldung/concurrent/locks/SharedObjectWithLockManualTest.java b/core-java/src/test/java/com/baeldung/concurrent/locks/SharedObjectWithLockManualTest.java
new file mode 100644
index 0000000000..9b82ced642
--- /dev/null
+++ b/core-java/src/test/java/com/baeldung/concurrent/locks/SharedObjectWithLockManualTest.java
@@ -0,0 +1,75 @@
+package com.baeldung.concurrent.locks;
+
+import org.junit.Test;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import static junit.framework.TestCase.assertEquals;
+
+public class SharedObjectWithLockManualTest {
+
+ @Test
+ public void whenLockAcquired_ThenLockedIsTrue() {
+ final SharedObjectWithLock object = new SharedObjectWithLock();
+
+ final int threadCount = 2;
+ final ExecutorService service = Executors.newFixedThreadPool(threadCount);
+
+ executeThreads(object, threadCount, service);
+
+ assertEquals(true, object.isLocked());
+
+ service.shutdown();
+ }
+
+ @Test
+ public void whenLocked_ThenQueuedThread() {
+ final int threadCount = 4;
+ final ExecutorService service = Executors.newFixedThreadPool(threadCount);
+ final SharedObjectWithLock object = new SharedObjectWithLock();
+
+ executeThreads(object, threadCount, service);
+
+ assertEquals(object.hasQueuedThreads(), true);
+
+ service.shutdown();
+
+ }
+
+ public void whenTryLock_ThenQueuedThread() {
+ final SharedObjectWithLock object = new SharedObjectWithLock();
+
+ final int threadCount = 2;
+ final ExecutorService service = Executors.newFixedThreadPool(threadCount);
+
+ executeThreads(object, threadCount, service);
+
+ assertEquals(true, object.isLocked());
+
+ service.shutdown();
+ }
+
+ @Test
+ public void whenGetCount_ThenCorrectCount() throws InterruptedException {
+ final int threadCount = 4;
+ final ExecutorService service = Executors.newFixedThreadPool(threadCount);
+ final SharedObjectWithLock object = new SharedObjectWithLock();
+
+ executeThreads(object, threadCount, service);
+ Thread.sleep(1000);
+ assertEquals(object.getCounter(), 4);
+
+ service.shutdown();
+
+ }
+
+ private void executeThreads(SharedObjectWithLock object, int threadCount, ExecutorService service) {
+ for (int i = 0; i < threadCount; i++) {
+ service.execute(() -> {
+ object.perform();
+ });
+ }
+ }
+
+}
diff --git a/core-java/src/test/java/com/baeldung/concurrent/locks/SynchronizedHashMapWithRWLockManualTest.java b/core-java/src/test/java/com/baeldung/concurrent/locks/SynchronizedHashMapWithRWLockManualTest.java
new file mode 100644
index 0000000000..fd6cf08442
--- /dev/null
+++ b/core-java/src/test/java/com/baeldung/concurrent/locks/SynchronizedHashMapWithRWLockManualTest.java
@@ -0,0 +1,58 @@
+package com.baeldung.concurrent.locks;
+
+import jdk.nashorn.internal.ir.annotations.Ignore;
+import org.junit.Test;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import static junit.framework.TestCase.assertEquals;
+
+public class SynchronizedHashMapWithRWLockManualTest {
+
+ @Test
+ public void whenWriting_ThenNoReading() {
+ SynchronizedHashMapWithRWLock object = new SynchronizedHashMapWithRWLock();
+ final int threadCount = 3;
+ final ExecutorService service = Executors.newFixedThreadPool(threadCount);
+
+ executeWriterThreads(object, threadCount, service);
+
+ assertEquals(object.isReadLockAvailable(), false);
+
+ service.shutdown();
+ }
+
+ @Test
+ public void whenReading_ThenMultipleReadingAllowed() {
+ SynchronizedHashMapWithRWLock object = new SynchronizedHashMapWithRWLock();
+ final int threadCount = 5;
+ final ExecutorService service = Executors.newFixedThreadPool(threadCount);
+
+ executeReaderThreads(object, threadCount, service);
+
+ assertEquals(object.isReadLockAvailable(), true);
+
+ service.shutdown();
+ }
+
+ private void executeWriterThreads(SynchronizedHashMapWithRWLock object, int threadCount, ExecutorService service) {
+ for (int i = 0; i < threadCount; i++) {
+ service.execute(() -> {
+ try {
+ object.put("key" + threadCount, "value" + threadCount);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ });
+ }
+ }
+
+ private void executeReaderThreads(SynchronizedHashMapWithRWLock object, int threadCount, ExecutorService service) {
+ for (int i = 0; i < threadCount; i++)
+ service.execute(() -> {
+ object.get("key" + threadCount);
+ });
+ }
+
+}
diff --git a/core-java/src/test/java/com/baeldung/java/map/README.md b/core-java/src/test/java/com/baeldung/java/map/README.md
deleted file mode 100644
index 0bba153763..0000000000
--- a/core-java/src/test/java/com/baeldung/java/map/README.md
+++ /dev/null
@@ -1,2 +0,0 @@
-### Relevant Articles:
-- [The Java HashMap Under the Hood](http://www.baeldung.com/java-hashmap)
diff --git a/core-java/src/test/java/com/baeldung/test/comparison/DivisibilityTest.java b/core-java/src/test/java/com/baeldung/junit4vstestng/DivisibilityTest.java
similarity index 74%
rename from core-java/src/test/java/com/baeldung/test/comparison/DivisibilityTest.java
rename to core-java/src/test/java/com/baeldung/junit4vstestng/DivisibilityTest.java
index 9ae13f5934..dec7dbe6aa 100644
--- a/core-java/src/test/java/com/baeldung/test/comparison/DivisibilityTest.java
+++ b/core-java/src/test/java/com/baeldung/junit4vstestng/DivisibilityTest.java
@@ -1,4 +1,4 @@
-package com.baeldung.test.comparison;
+package com.baeldung.junit4vstestng;
import static org.junit.Assert.assertEquals;
@@ -15,7 +15,7 @@ public class DivisibilityTest {
}
@Test
- public void givenNumber_whenDivisiblebyTwo_thenCorrect() {
+ public void givenNumber_whenDivisibleByTwo_thenCorrect() {
assertEquals(number % 2, 0);
}
}
diff --git a/core-java/src/test/java/com/baeldung/junit4vstestng/ParametrizedTests.java b/core-java/src/test/java/com/baeldung/junit4vstestng/ParametrizedTests.java
new file mode 100644
index 0000000000..e9a9c6a07a
--- /dev/null
+++ b/core-java/src/test/java/com/baeldung/junit4vstestng/ParametrizedTests.java
@@ -0,0 +1,34 @@
+package com.baeldung.junit4vstestng;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+@RunWith(value = Parameterized.class)
+public class ParametrizedTests {
+
+ private int value;
+ private boolean isEven;
+
+ public ParametrizedTests(int value, boolean isEven) {
+ this.value = value;
+ this.isEven = isEven;
+ }
+
+ @Parameters
+ public static Collection
-
diff --git a/spring-hibernate4/README.md b/spring-hibernate4/README.md
index 7888e8b4ee..02888c4ad0 100644
--- a/spring-hibernate4/README.md
+++ b/spring-hibernate4/README.md
@@ -12,6 +12,7 @@
- [Hibernate: save, persist, update, merge, saveOrUpdate](http://www.baeldung.com/hibernate-save-persist-update-merge-saveorupdate/)
- [Eager/Lazy Loading In Hibernate](http://www.baeldung.com/hibernate-lazy-eager-loading)
- [Hibernate Criteria Queries](http://www.baeldung.com/hibernate-criteria-queries)
+- [Hibernate One to Many Annotation Tutorial](http://www.baeldung.com/hibernate-one-to-many)
### Quick Start
@@ -22,3 +23,4 @@ mvn install
mvn cargo:run
```
- **note**: starts on port `8082`
+
diff --git a/spring-hibernate5/.gitignore b/spring-hibernate5/.gitignore
new file mode 100644
index 0000000000..83c05e60c8
--- /dev/null
+++ b/spring-hibernate5/.gitignore
@@ -0,0 +1,13 @@
+*.class
+
+#folders#
+/target
+/neoDb*
+/data
+/src/main/webapp/WEB-INF/classes
+*/META-INF/*
+
+# Packaged files #
+*.jar
+*.war
+*.ear
\ No newline at end of file
diff --git a/spring-hibernate5/pom.xml b/spring-hibernate5/pom.xml
new file mode 100644
index 0000000000..81f8084d74
--- /dev/null
+++ b/spring-hibernate5/pom.xml
@@ -0,0 +1,239 @@
+
+ 4.0.0
+ com.baeldung
+ spring-hibernate5
+ 0.1-SNAPSHOT
+
+ spring-hibernate5
+
+
+
+
+
+
+ org.springframework
+ spring-context
+ ${org.springframework.version}
+
+
+ org.springframework
+ spring-aspects
+ ${org.springframework.version}
+
+
+ org.springframework.security
+ spring-security-core
+ ${org.springframework.security.version}
+
+
+
+
+
+ org.springframework
+ spring-orm
+ ${org.springframework.version}
+
+
+ org.springframework.data
+ spring-data-jpa
+ ${org.springframework.data.version}
+
+
+ org.hibernate
+ hibernate-core
+ ${hibernate.version}
+
+
+ org.hibernate
+ hibernate-envers
+ ${hibernate-envers.version}
+
+
+ javax.transaction
+ jta
+ ${jta.version}
+
+
+ mysql
+ mysql-connector-java
+ ${mysql-connector-java.version}
+
+
+
+ org.apache.tomcat
+ tomcat-dbcp
+ ${tomcat-dbcp.version}
+
+
+
+
+
+ org.hibernate
+ hibernate-validator
+ ${hibernate-validator.version}
+
+
+ javax.el
+ javax.el-api
+ ${javax.el-api.version}
+
+
+
+
+
+ com.google.guava
+ guava
+ ${guava.version}
+
+
+
+
+
+ org.apache.commons
+ commons-lang3
+ ${commons-lang3.version}
+ test
+
+
+
+ org.springframework
+ spring-test
+ ${org.springframework.version}
+ test
+
+
+
+ junit
+ junit
+ ${junit.version}
+ test
+
+
+
+ org.springframework.security
+ spring-security-test
+ ${org.springframework.security.version}
+ test
+
+
+
+ org.hamcrest
+ hamcrest-core
+ ${org.hamcrest.version}
+ test
+
+
+
+ junit
+ junit-dep
+ 4.11
+ test
+
+
+
+ org.hamcrest
+ hamcrest-library
+ ${org.hamcrest.version}
+ test
+
+
+
+ org.mockito
+ mockito-core
+ ${mockito.version}
+ test
+
+
+
+ org.hsqldb
+ hsqldb
+ ${hsqldb.version}
+ test
+
+
+
+
+
+ spring-hibernate5
+
+
+ src/main/resources
+ true
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ ${maven-compiler-plugin.version}
+
+
+ 1.8
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ ${maven-surefire-plugin.version}
+
+
+ **/*IntegrationTest.java
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 4.3.5.RELEASE
+ 4.2.1.RELEASE
+ 1.10.6.RELEASE
+
+
+ 5.2.8.Final
+ ${hibernate.version}
+ 6.0.5
+ 8.5.11
+ 1.1
+ 2.3.4
+
+
+ 1.7.21
+ 1.1.7
+
+
+ 5.4.0.Final
+ 2.2.5
+
+
+ 21.0
+ 3.5
+
+
+ 1.3
+ 4.12
+ 2.6.8
+
+ 4.4.1
+ 4.5
+
+ 2.9.0
+
+
+ 3.6.0
+ 2.19.1
+ 2.7
+ 1.6.1
+
+
+
+
diff --git a/spring-hibernate5/src/main/java/com/baeldung/hibernate/criteria/model/Item.java b/spring-hibernate5/src/main/java/com/baeldung/hibernate/criteria/model/Item.java
new file mode 100644
index 0000000000..957207b7e6
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/hibernate/criteria/model/Item.java
@@ -0,0 +1,81 @@
+package com.baeldung.hibernate.criteria.model;
+
+import java.io.Serializable;
+
+public class Item implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+ private Integer itemId;
+ private String itemName;
+ private String itemDescription;
+ private Integer itemPrice;
+
+ // constructors
+ public Item() {
+
+ }
+
+ public Item(final Integer itemId, final String itemName, final String itemDescription) {
+ super();
+ this.itemId = itemId;
+ this.itemName = itemName;
+ this.itemDescription = itemDescription;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((itemId == null) ? 0 : itemId.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final Item other = (Item) obj;
+ if (itemId == null) {
+ if (other.itemId != null)
+ return false;
+ } else if (!itemId.equals(other.itemId))
+ return false;
+ return true;
+ }
+
+ public Integer getItemId() {
+ return itemId;
+ }
+
+ public void setItemId(final Integer itemId) {
+ this.itemId = itemId;
+ }
+
+ public String getItemName() {
+ return itemName;
+ }
+
+ public void setItemName(final String itemName) {
+ this.itemName = itemName;
+ }
+
+ public String getItemDescription() {
+ return itemDescription;
+ }
+
+ public Integer getItemPrice() {
+ return itemPrice;
+ }
+
+ public void setItemPrice(final Integer itemPrice) {
+ this.itemPrice = itemPrice;
+ }
+
+ public void setItemDescription(final String itemDescription) {
+ this.itemDescription = itemDescription;
+ }
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/hibernate/criteria/util/HibernateUtil.java b/spring-hibernate5/src/main/java/com/baeldung/hibernate/criteria/util/HibernateUtil.java
new file mode 100644
index 0000000000..9024ba9e4b
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/hibernate/criteria/util/HibernateUtil.java
@@ -0,0 +1,17 @@
+package com.baeldung.hibernate.criteria.util;
+
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.cfg.Configuration;
+
+public class HibernateUtil {
+
+ public static Session getHibernateSession() {
+
+ final SessionFactory sf = new Configuration().configure("criteria.cfg.xml").buildSessionFactory();
+
+ final Session session = sf.openSession();
+ return session;
+ }
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/hibernate/criteria/view/ApplicationView.java b/spring-hibernate5/src/main/java/com/baeldung/hibernate/criteria/view/ApplicationView.java
new file mode 100644
index 0000000000..a854b51753
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/hibernate/criteria/view/ApplicationView.java
@@ -0,0 +1,284 @@
+/**
+ * ApplicationViewer is the class that starts the application
+ * First it creates the session object and then creates the
+ * criteria query.
+ *
+ * @author Sandeep Kumar
+ * @version 1.0
+ * @since 01/13/2017
+ */
+
+package com.baeldung.hibernate.criteria.view;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.Tuple;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Order;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
+
+import org.hibernate.Session;
+import org.hibernate.Transaction;
+
+import com.baeldung.hibernate.criteria.model.Item;
+import com.baeldung.hibernate.criteria.util.HibernateUtil;
+
+public class ApplicationView {
+
+ public ApplicationView() {
+
+ }
+
+ @SuppressWarnings("unchecked")
+ public boolean checkIfCriteriaTimeLower() {
+ final Session session = HibernateUtil.getHibernateSession();
+ CriteriaBuilder builder = session.getCriteriaBuilder();
+ CriteriaQuery- criteriaItem = builder.createQuery(Item.class);
+ Root
- rootItem = criteriaItem.from(Item.class);
+ Transaction tx = null;
+
+ // calculate the time taken by criteria
+ final long startTimeCriteria = System.nanoTime();
+ criteriaItem.select(rootItem).where(builder.like(rootItem.get("itemName"), "%item One%"));
+ final List
- results = session.createQuery(criteriaItem).getResultList();
+ final long endTimeCriteria = System.nanoTime();
+ final long durationCriteria = (endTimeCriteria - startTimeCriteria) / 1000;
+
+ // calculate the time taken by HQL
+ final long startTimeHQL = System.nanoTime();
+ tx = session.beginTransaction();
+ final List
- items = session.createQuery("FROM Item where itemName like '%item One%'").getResultList();
+ final long endTimeHQL = System.nanoTime();
+ final long durationHQL = (endTimeHQL - startTimeHQL) / 1000;
+
+ if (durationCriteria > durationHQL) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ // To get items having price more than 1000
+ public String[] greaterThanCriteria() {
+ final Session session = HibernateUtil.getHibernateSession();
+ CriteriaBuilder builder = session.getCriteriaBuilder();
+ CriteriaQuery
- criteriaItem = builder.createQuery(Item.class);
+ Root
- rootItem = criteriaItem.from(Item.class);
+ criteriaItem.select(rootItem).where(builder.greaterThan(rootItem.get("itemPrice"), 1000));
+ final List
- greaterThanItemsList = session.createQuery(criteriaItem).getResultList();
+ final String greaterThanItems[] = new String[greaterThanItemsList.size()];
+ for (int i = 0; i < greaterThanItemsList.size(); i++) {
+ greaterThanItems[i] = greaterThanItemsList.get(i).getItemName();
+ }
+ session.close();
+ return greaterThanItems;
+ }
+
+ // To get items having price less than 1000
+ public String[] lessThanCriteria() {
+ final Session session = HibernateUtil.getHibernateSession();
+ CriteriaBuilder builder = session.getCriteriaBuilder();
+ CriteriaQuery
- criteriaItem = builder.createQuery(Item.class);
+ Root
- rootItem = criteriaItem.from(Item.class);
+ criteriaItem.select(rootItem).where(builder.lessThan(rootItem.get("itemPrice"), 1000));
+ final List
- lessThanItemsList = session.createQuery(criteriaItem).getResultList();
+ final String lessThanItems[] = new String[lessThanItemsList.size()];
+ for (int i = 0; i < lessThanItemsList.size(); i++) {
+ lessThanItems[i] = lessThanItemsList.get(i).getItemName();
+ }
+ session.close();
+ return lessThanItems;
+ }
+
+ // To get items whose Name start with Chair
+ public String[] likeCriteria() {
+ final Session session = HibernateUtil.getHibernateSession();
+
+ CriteriaBuilder builder = session.getCriteriaBuilder();
+ CriteriaQuery
- criteriaItem = builder.createQuery(Item.class);
+ Root
- rootItem = criteriaItem.from(Item.class);
+ criteriaItem.select(rootItem).where(builder.like(rootItem.get("itemName"), "%chair%"));
+ final List
- likeItemsList = session.createQuery(criteriaItem).getResultList();
+ final String likeItems[] = new String[likeItemsList.size()];
+ for (int i = 0; i < likeItemsList.size(); i++) {
+ likeItems[i] = likeItemsList.get(i).getItemName();
+ }
+ session.close();
+ return likeItems;
+ }
+
+ // Case sensitive search
+ public String[] likeCaseCriteria() {
+ final Session session = HibernateUtil.getHibernateSession();
+ CriteriaBuilder builder = session.getCriteriaBuilder();
+ CriteriaQuery
- criteriaItem = builder.createQuery(Item.class);
+ Root
- rootItem = criteriaItem.from(Item.class);
+ criteriaItem.select(rootItem).where(builder.like(rootItem.get("itemName"), "%Chair%"));
+ final List
- ilikeItemsList = session.createQuery(criteriaItem).getResultList();
+ final String ilikeItems[] = new String[ilikeItemsList.size()];
+ for (int i = 0; i < ilikeItemsList.size(); i++) {
+ ilikeItems[i] = ilikeItemsList.get(i).getItemName();
+ }
+ session.close();
+ return ilikeItems;
+ }
+
+ // To get records having itemPrice in between 100 and 200
+ public String[] betweenCriteria() {
+ final Session session = HibernateUtil.getHibernateSession();
+ CriteriaBuilder builder = session.getCriteriaBuilder();
+ CriteriaQuery
- criteriaItem = builder.createQuery(Item.class);
+ Root
- rootItem = criteriaItem.from(Item.class);
+ // To get items having price more than 1000
+ criteriaItem.select(rootItem).where(builder.between(rootItem.get("itemPrice"), 100, 200));
+ final List
- betweenItemsList = session.createQuery(criteriaItem).getResultList();
+ final String betweenItems[] = new String[betweenItemsList.size()];
+ for (int i = 0; i < betweenItemsList.size(); i++) {
+ betweenItems[i] = betweenItemsList.get(i).getItemName();
+ }
+ session.close();
+ return betweenItems;
+ }
+
+ // To check if the given property is null
+ public String[] nullCriteria() {
+ final Session session = HibernateUtil.getHibernateSession();
+ CriteriaBuilder builder = session.getCriteriaBuilder();
+ CriteriaQuery
- criteriaItem = builder.createQuery(Item.class);
+ Root
- rootItem = criteriaItem.from(Item.class);
+ criteriaItem.select(rootItem).where(builder.isNull(rootItem.get("itemDescription")));
+ final List
- nullItemsList = session.createQuery(criteriaItem).getResultList();
+ final String nullDescItems[] = new String[nullItemsList.size()];
+ for (int i = 0; i < nullItemsList.size(); i++) {
+ nullDescItems[i] = nullItemsList.get(i).getItemName();
+ }
+ session.close();
+ return nullDescItems;
+ }
+
+ // To check if the given property is not null
+ public String[] notNullCriteria() {
+ final Session session = HibernateUtil.getHibernateSession();
+ CriteriaBuilder builder = session.getCriteriaBuilder();
+ CriteriaQuery
- criteriaItem = builder.createQuery(Item.class);
+ Root
- rootItem = criteriaItem.from(Item.class);
+ criteriaItem.select(rootItem).where(builder.isNotNull(rootItem.get("itemDescription")));
+ final List
- notNullItemsList = session.createQuery(criteriaItem).getResultList();
+ final String notNullDescItems[] = new String[notNullItemsList.size()];
+ for (int i = 0; i < notNullItemsList.size(); i++) {
+ notNullDescItems[i] = notNullItemsList.get(i).getItemName();
+ }
+ session.close();
+ return notNullDescItems;
+ }
+
+ // Adding more than one expression in one cr
+ public String[] twoCriteria() {
+ final Session session = HibernateUtil.getHibernateSession();
+ CriteriaBuilder builder = session.getCriteriaBuilder();
+ CriteriaQuery
- criteriaItem = builder.createQuery(Item.class);
+ Root
- rootItem = criteriaItem.from(Item.class);
+ criteriaItem.select(rootItem).where(builder.isNull(rootItem.get("itemDescription")))
+ .where(builder.like(rootItem.get("itemName"), "chair%"));
+ final List
- notNullItemsList = session.createQuery(criteriaItem).getResultList();
+ final String notNullDescItems[] = new String[notNullItemsList.size()];
+ for (int i = 0; i < notNullItemsList.size(); i++) {
+ notNullDescItems[i] = notNullItemsList.get(i).getItemName();
+ }
+ session.close();
+ return notNullDescItems;
+ }
+
+ // To get items matching with the above defined conditions joined
+ // with Logical AND
+ public String[] andLogicalCriteria() {
+ List predicates = new ArrayList();
+ final Session session = HibernateUtil.getHibernateSession();
+ CriteriaBuilder builder = session.getCriteriaBuilder();
+ CriteriaQuery
- criteriaItem = builder.createQuery(Item.class);
+ Root
- rootItem = criteriaItem.from(Item.class);
+ predicates.add(builder.greaterThan(rootItem.get("itemPrice"), 1000));
+ predicates.add(builder.like(rootItem.get("itemName"), "Chair%"));
+ Predicate andPredicate = builder.and(predicates.toArray(new Predicate[] {}));
+ criteriaItem.select(rootItem).where(andPredicate);
+ final List
- andItemsList = session.createQuery(criteriaItem).getResultList();
+ final String andItems[] = new String[andItemsList.size()];
+ for (int i = 0; i < andItemsList.size(); i++) {
+ andItems[i] = andItemsList.get(i).getItemName();
+ }
+ session.close();
+ return andItems;
+ }
+
+ // To get items matching with the above defined conditions joined
+ // with Logical OR
+ public String[] orLogicalCriteria() {
+ List predicates = new ArrayList();
+ final Session session = HibernateUtil.getHibernateSession();
+ CriteriaBuilder builder = session.getCriteriaBuilder();
+ CriteriaQuery
- criteriaItem = builder.createQuery(Item.class);
+ Root
- rootItem = criteriaItem.from(Item.class);
+ predicates.add(builder.greaterThan(rootItem.get("itemPrice"), 1000));
+ predicates.add(builder.like(rootItem.get("itemName"), "Chair%"));
+ Predicate orPredicate = builder.or(predicates.toArray(new Predicate[] {}));
+ criteriaItem.select(rootItem).where(orPredicate);
+ final List
- orItemsList = session.createQuery(criteriaItem).getResultList();
+ final String orItems[] = new String[orItemsList.size()];
+ for (int i = 0; i < orItemsList.size(); i++) {
+ orItems[i] = orItemsList.get(i).getItemName();
+ }
+ session.close();
+ return orItems;
+ }
+
+ // Sorting example
+ public String[] sortingCriteria() {
+ List listOrders = new ArrayList();
+ final Session session = HibernateUtil.getHibernateSession();
+ CriteriaBuilder builder = session.getCriteriaBuilder();
+ CriteriaQuery
- criteriaItem = builder.createQuery(Item.class);
+ Root
- rootItem = criteriaItem.from(Item.class);
+ listOrders.add(builder.asc(rootItem.get("itemName")));
+ listOrders.add(builder.desc(rootItem.get("itemPrice")));
+ criteriaItem.orderBy(listOrders.toArray(new Order[] {}));
+ final List
- sortedItemsList = session.createQuery(criteriaItem).getResultList();
+ final String sortedItems[] = new String[sortedItemsList.size()];
+ for (int i = 0; i < sortedItemsList.size(); i++) {
+ sortedItems[i] = sortedItemsList.get(i).getItemName();
+ }
+ session.close();
+ return sortedItems;
+ }
+
+ // Set projections Row Count
+ public Long[] projectionRowCount() {
+ final Session session = HibernateUtil.getHibernateSession();
+ CriteriaBuilder builder = session.getCriteriaBuilder();
+ CriteriaQuery criteriaItem = builder.createQuery(Tuple.class);
+ Root
- rootItem = criteriaItem.from(Item.class);
+ criteriaItem.multiselect(builder.count(rootItem));
+ final List itemProjected = session.createQuery(criteriaItem).getResultList();
+ final Long projectedRowCount[] = new Long[1];
+ projectedRowCount[0] = (long) itemProjected.get(0).get(0);
+ session.close();
+ return projectedRowCount;
+ }
+
+ // Set projections average of itemPrice
+ public Double[] projectionAverage() {
+ final Session session = HibernateUtil.getHibernateSession();
+ CriteriaBuilder builder = session.getCriteriaBuilder();
+ CriteriaQuery criteriaItem = builder.createQuery(Tuple.class);
+ Root
- rootItem = criteriaItem.from(Item.class);
+ criteriaItem.multiselect(builder.avg(rootItem.get("itemPrice")));
+ final List itemProjected = session.createQuery(criteriaItem).getResultList();
+ Double avgItemPrice[] = new Double[1];
+ avgItemPrice[0] = Double.valueOf(itemProjected.get(0).get(0).toString());
+ session.close();
+ return avgItemPrice;
+ }
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/hibernate/fetching/model/OrderDetail.java b/spring-hibernate5/src/main/java/com/baeldung/hibernate/fetching/model/OrderDetail.java
new file mode 100644
index 0000000000..f4a9b8a678
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/hibernate/fetching/model/OrderDetail.java
@@ -0,0 +1,58 @@
+package com.baeldung.hibernate.fetching.model;
+
+import javax.persistence.*;
+import java.io.Serializable;
+import java.sql.Date;
+
+@Entity
+@Table(name = "USER_ORDER")
+public class OrderDetail implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @Id
+ @GeneratedValue
+ @Column(name = "ORDER_ID")
+ private Long orderId;
+
+ public OrderDetail() {
+ }
+
+ public OrderDetail(Date orderDate, String orderDesc) {
+ super();
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((orderId == null) ? 0 : orderId.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ OrderDetail other = (OrderDetail) obj;
+ if (orderId == null) {
+ if (other.orderId != null)
+ return false;
+ } else if (!orderId.equals(other.orderId))
+ return false;
+
+ return true;
+ }
+
+ public Long getOrderId() {
+ return orderId;
+ }
+
+ public void setOrderId(Long orderId) {
+ this.orderId = orderId;
+ }
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/hibernate/fetching/model/UserEager.java b/spring-hibernate5/src/main/java/com/baeldung/hibernate/fetching/model/UserEager.java
new file mode 100644
index 0000000000..a1aa746399
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/hibernate/fetching/model/UserEager.java
@@ -0,0 +1,71 @@
+package com.baeldung.hibernate.fetching.model;
+
+import javax.persistence.*;
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Set;
+
+@Entity
+@Table(name = "USER")
+public class UserEager implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @Id
+ @GeneratedValue
+ @Column(name = "USER_ID")
+ private Long userId;
+
+ @OneToMany(fetch = FetchType.EAGER, mappedBy = "user")
+ private Set orderDetail = new HashSet();
+
+ public UserEager() {
+ }
+
+ public UserEager(final Long userId) {
+ super();
+ this.userId = userId;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((userId == null) ? 0 : userId.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final UserEager other = (UserEager) obj;
+ if (userId == null) {
+ if (other.userId != null)
+ return false;
+ } else if (!userId.equals(other.userId))
+ return false;
+ return true;
+ }
+
+ public Long getUserId() {
+ return userId;
+ }
+
+ public void setUserId(final Long userId) {
+ this.userId = userId;
+ }
+
+ public Set getOrderDetail() {
+ return orderDetail;
+ }
+
+ public void setOrderDetail(Set orderDetail) {
+ this.orderDetail = orderDetail;
+ }
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/hibernate/fetching/model/UserLazy.java b/spring-hibernate5/src/main/java/com/baeldung/hibernate/fetching/model/UserLazy.java
new file mode 100644
index 0000000000..e1354b5d24
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/hibernate/fetching/model/UserLazy.java
@@ -0,0 +1,71 @@
+package com.baeldung.hibernate.fetching.model;
+
+import javax.persistence.*;
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Set;
+
+@Entity
+@Table(name = "USER")
+public class UserLazy implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @Id
+ @GeneratedValue
+ @Column(name = "USER_ID")
+ private Long userId;
+
+ @OneToMany(fetch = FetchType.LAZY, mappedBy = "user")
+ private Set orderDetail = new HashSet();
+
+ public UserLazy() {
+ }
+
+ public UserLazy(final Long userId) {
+ super();
+ this.userId = userId;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((userId == null) ? 0 : userId.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final UserLazy other = (UserLazy) obj;
+ if (userId == null) {
+ if (other.userId != null)
+ return false;
+ } else if (!userId.equals(other.userId))
+ return false;
+ return true;
+ }
+
+ public Long getUserId() {
+ return userId;
+ }
+
+ public void setUserId(final Long userId) {
+ this.userId = userId;
+ }
+
+ public Set getOrderDetail() {
+ return orderDetail;
+ }
+
+ public void setOrderDetail(Set orderDetail) {
+ this.orderDetail = orderDetail;
+ }
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/hibernate/fetching/util/HibernateUtil.java b/spring-hibernate5/src/main/java/com/baeldung/hibernate/fetching/util/HibernateUtil.java
new file mode 100644
index 0000000000..422de2ea93
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/hibernate/fetching/util/HibernateUtil.java
@@ -0,0 +1,28 @@
+package com.baeldung.hibernate.fetching.util;
+
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.cfg.Configuration;
+
+public class HibernateUtil {
+
+ public static Session getHibernateSession(String fetchMethod) {
+ // two config files are there
+ // one with lazy loading enabled
+ // another lazy = false
+ SessionFactory sf;
+ if ("lazy".equals(fetchMethod)) {
+ sf = new Configuration().configure("fetchingLazy.cfg.xml").buildSessionFactory();
+ } else {
+ sf = new Configuration().configure("fetching.cfg.xml").buildSessionFactory();
+ }
+
+ // fetching.cfg.xml is used for this example
+ return sf.openSession();
+ }
+
+ public static Session getHibernateSession() {
+ return new Configuration().configure("fetching.cfg.xml").buildSessionFactory().openSession();
+ }
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/hibernate/fetching/view/FetchingAppView.java b/spring-hibernate5/src/main/java/com/baeldung/hibernate/fetching/view/FetchingAppView.java
new file mode 100644
index 0000000000..7fc543f693
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/hibernate/fetching/view/FetchingAppView.java
@@ -0,0 +1,68 @@
+package com.baeldung.hibernate.fetching.view;
+
+import com.baeldung.hibernate.fetching.model.OrderDetail;
+import com.baeldung.hibernate.fetching.model.UserEager;
+import com.baeldung.hibernate.fetching.model.UserLazy;
+import com.baeldung.hibernate.fetching.util.HibernateUtil;
+import org.hibernate.Session;
+import org.hibernate.Transaction;
+
+import java.util.List;
+import java.util.Set;
+
+public class FetchingAppView {
+
+ public FetchingAppView() {
+
+ }
+
+ // lazily loaded
+ public Set lazyLoaded() {
+ final Session sessionLazy = HibernateUtil.getHibernateSession("lazy");
+ List users = sessionLazy.createQuery("From UserLazy").getResultList();
+ UserLazy userLazyLoaded = users.get(3);
+ // since data is lazyloaded so data won't be initialized
+ return (userLazyLoaded.getOrderDetail());
+ }
+
+ // eagerly loaded
+ public Set eagerLoaded() {
+ final Session sessionEager = HibernateUtil.getHibernateSession();
+ // data should be loaded in the following line
+ // also note the queries generated
+ List user = sessionEager.createQuery("From UserEager").getResultList();
+ UserEager userEagerLoaded = user.get(3);
+ return userEagerLoaded.getOrderDetail();
+ }
+
+ // creates test data
+ // call this method to create the data in the database
+ public void createTestData() {
+
+ final Session session = HibernateUtil.getHibernateSession("lazy");
+ Transaction tx = session.beginTransaction();
+ final UserLazy user1 = new UserLazy();
+ final UserLazy user2 = new UserLazy();
+ final UserLazy user3 = new UserLazy();
+
+ session.save(user1);
+ session.save(user2);
+ session.save(user3);
+
+ final OrderDetail order1 = new OrderDetail();
+ final OrderDetail order2 = new OrderDetail();
+ final OrderDetail order3 = new OrderDetail();
+ final OrderDetail order4 = new OrderDetail();
+ final OrderDetail order5 = new OrderDetail();
+
+ session.saveOrUpdate(order1);
+ session.saveOrUpdate(order2);
+ session.saveOrUpdate(order3);
+ session.saveOrUpdate(order4);
+ session.saveOrUpdate(order5);
+
+ tx.commit();
+ session.close();
+
+ }
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IBarAuditableDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IBarAuditableDao.java
new file mode 100644
index 0000000000..182b493592
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IBarAuditableDao.java
@@ -0,0 +1,8 @@
+package com.baeldung.persistence.dao;
+
+import com.baeldung.persistence.dao.common.IAuditOperations;
+import com.baeldung.persistence.model.Bar;
+
+public interface IBarAuditableDao extends IBarDao, IAuditOperations {
+ //
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IBarCrudRepository.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IBarCrudRepository.java
new file mode 100644
index 0000000000..4d7db64240
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IBarCrudRepository.java
@@ -0,0 +1,10 @@
+package com.baeldung.persistence.dao;
+
+import java.io.Serializable;
+
+import com.baeldung.persistence.model.Bar;
+import org.springframework.data.repository.CrudRepository;
+
+public interface IBarCrudRepository extends CrudRepository {
+ //
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IBarDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IBarDao.java
new file mode 100644
index 0000000000..7896a2a84a
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IBarDao.java
@@ -0,0 +1,8 @@
+package com.baeldung.persistence.dao;
+
+import com.baeldung.persistence.dao.common.IOperations;
+import com.baeldung.persistence.model.Bar;
+
+public interface IBarDao extends IOperations {
+ //
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IChildDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IChildDao.java
new file mode 100644
index 0000000000..a55a0b0598
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IChildDao.java
@@ -0,0 +1,8 @@
+package com.baeldung.persistence.dao;
+
+import com.baeldung.persistence.model.Child;
+import com.baeldung.persistence.dao.common.IOperations;
+
+public interface IChildDao extends IOperations {
+ //
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IFooAuditableDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IFooAuditableDao.java
new file mode 100644
index 0000000000..ddbb685988
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IFooAuditableDao.java
@@ -0,0 +1,8 @@
+package com.baeldung.persistence.dao;
+
+import com.baeldung.persistence.dao.common.IAuditOperations;
+import com.baeldung.persistence.model.Foo;
+
+public interface IFooAuditableDao extends IFooDao, IAuditOperations {
+ //
+}
\ No newline at end of file
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IFooDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IFooDao.java
new file mode 100644
index 0000000000..0935772dbd
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IFooDao.java
@@ -0,0 +1,8 @@
+package com.baeldung.persistence.dao;
+
+import com.baeldung.persistence.model.Foo;
+import com.baeldung.persistence.dao.common.IOperations;
+
+public interface IFooDao extends IOperations {
+ //
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IParentDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IParentDao.java
new file mode 100644
index 0000000000..03680158bb
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IParentDao.java
@@ -0,0 +1,8 @@
+package com.baeldung.persistence.dao;
+
+import com.baeldung.persistence.model.Parent;
+import com.baeldung.persistence.dao.common.IOperations;
+
+public interface IParentDao extends IOperations {
+ //
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/AbstractDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/AbstractDao.java
new file mode 100644
index 0000000000..5a6c76a93a
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/AbstractDao.java
@@ -0,0 +1,14 @@
+package com.baeldung.persistence.dao.common;
+
+import java.io.Serializable;
+
+import com.google.common.base.Preconditions;
+
+public abstract class AbstractDao implements IOperations {
+
+ protected Class clazz;
+
+ protected final void setClazz(final Class clazzToSet) {
+ clazz = Preconditions.checkNotNull(clazzToSet);
+ }
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/AbstractHibernateAuditableDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/AbstractHibernateAuditableDao.java
new file mode 100644
index 0000000000..41184669ad
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/AbstractHibernateAuditableDao.java
@@ -0,0 +1,37 @@
+package com.baeldung.persistence.dao.common;
+
+import java.io.Serializable;
+import java.util.List;
+
+import org.hibernate.envers.AuditReader;
+import org.hibernate.envers.AuditReaderFactory;
+import org.hibernate.envers.query.AuditQuery;
+
+@SuppressWarnings("unchecked")
+public class AbstractHibernateAuditableDao extends AbstractHibernateDao implements IAuditOperations {
+
+ @Override
+ public List getEntitiesAtRevision(final Number revision) {
+ final AuditReader auditReader = AuditReaderFactory.get(getCurrentSession());
+ final AuditQuery query = auditReader.createQuery().forEntitiesAtRevision(clazz, revision);
+ final List resultList = query.getResultList();
+ return resultList;
+ }
+
+ @Override
+ public List getEntitiesModifiedAtRevision(final Number revision) {
+ final AuditReader auditReader = AuditReaderFactory.get(getCurrentSession());
+ final AuditQuery query = auditReader.createQuery().forEntitiesModifiedAtRevision(clazz, revision);
+ final List resultList = query.getResultList();
+ return resultList;
+ }
+
+ @Override
+ public List getRevisions() {
+ final AuditReader auditReader = AuditReaderFactory.get(getCurrentSession());
+ final AuditQuery query = auditReader.createQuery().forRevisionsOfEntity(clazz, true, true);
+ final List resultList = query.getResultList();
+ return resultList;
+ }
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/AbstractHibernateDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/AbstractHibernateDao.java
new file mode 100644
index 0000000000..f34866d883
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/AbstractHibernateDao.java
@@ -0,0 +1,59 @@
+package com.baeldung.persistence.dao.common;
+
+import java.io.Serializable;
+import java.util.List;
+
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.google.common.base.Preconditions;
+
+@SuppressWarnings("unchecked")
+public abstract class AbstractHibernateDao extends AbstractDao implements IOperations {
+
+ @Autowired
+ protected SessionFactory sessionFactory;
+
+ // API
+
+ @Override
+ public T findOne(final long id) {
+ return (T) getCurrentSession().get(clazz, id);
+ }
+
+ @Override
+ public List findAll() {
+ return getCurrentSession().createQuery("from " + clazz.getName()).getResultList();
+ }
+
+ @Override
+ public void create(final T entity) {
+ Preconditions.checkNotNull(entity);
+ getCurrentSession().saveOrUpdate(entity);
+ }
+
+ @Override
+ public T update(final T entity) {
+ Preconditions.checkNotNull(entity);
+ return (T) getCurrentSession().merge(entity);
+ }
+
+ @Override
+ public void delete(final T entity) {
+ Preconditions.checkNotNull(entity);
+ getCurrentSession().delete(entity);
+ }
+
+ @Override
+ public void deleteById(final long entityId) {
+ final T entity = findOne(entityId);
+ Preconditions.checkState(entity != null);
+ delete(entity);
+ }
+
+ protected Session getCurrentSession() {
+ return sessionFactory.getCurrentSession();
+ }
+
+}
\ No newline at end of file
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/AbstractJpaDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/AbstractJpaDao.java
new file mode 100644
index 0000000000..69f8e58c25
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/AbstractJpaDao.java
@@ -0,0 +1,56 @@
+package com.baeldung.persistence.dao.common;
+
+import java.io.Serializable;
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import javax.persistence.TypedQuery;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Root;
+
+public class AbstractJpaDao extends AbstractDao implements IOperations {
+
+ @PersistenceContext
+ private EntityManager em;
+
+ // API
+
+ @Override
+ public T findOne(final long id) {
+ return em.find(clazz, Long.valueOf(id).intValue());
+ }
+
+ @Override
+ public List findAll() {
+ final CriteriaBuilder cb = em.getCriteriaBuilder();
+ final CriteriaQuery cq = cb.createQuery(clazz);
+ final Root rootEntry = cq.from(clazz);
+ final CriteriaQuery all = cq.select(rootEntry);
+ final TypedQuery allQuery = em.createQuery(all);
+ return allQuery.getResultList();
+ }
+
+ @Override
+ public void create(final T entity) {
+ em.persist(entity);
+ }
+
+ @Override
+ public T update(final T entity) {
+ em.merge(entity);
+ return entity;
+ }
+
+ @Override
+ public void delete(final T entity) {
+ em.remove(entity);
+ }
+
+ @Override
+ public void deleteById(final long entityId) {
+ delete(findOne(entityId));
+ }
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/GenericHibernateDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/GenericHibernateDao.java
new file mode 100644
index 0000000000..18b16fa033
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/GenericHibernateDao.java
@@ -0,0 +1,13 @@
+package com.baeldung.persistence.dao.common;
+
+import java.io.Serializable;
+
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Repository;
+
+@Repository
+@Scope(BeanDefinition.SCOPE_PROTOTYPE)
+public class GenericHibernateDao extends AbstractHibernateDao implements IGenericDao {
+ //
+}
\ No newline at end of file
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/IAuditOperations.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/IAuditOperations.java
new file mode 100644
index 0000000000..169d3fed72
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/IAuditOperations.java
@@ -0,0 +1,14 @@
+package com.baeldung.persistence.dao.common;
+
+import java.io.Serializable;
+import java.util.List;
+
+public interface IAuditOperations {
+
+ List getEntitiesAtRevision(Number revision);
+
+ List getEntitiesModifiedAtRevision(Number revision);
+
+ List getRevisions();
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/IGenericDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/IGenericDao.java
new file mode 100644
index 0000000000..8d8af18394
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/IGenericDao.java
@@ -0,0 +1,7 @@
+package com.baeldung.persistence.dao.common;
+
+import java.io.Serializable;
+
+public interface IGenericDao extends IOperations {
+ //
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/IOperations.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/IOperations.java
new file mode 100644
index 0000000000..4ef99221ab
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/IOperations.java
@@ -0,0 +1,20 @@
+package com.baeldung.persistence.dao.common;
+
+import java.io.Serializable;
+import java.util.List;
+
+public interface IOperations {
+
+ T findOne(final long id);
+
+ List findAll();
+
+ void create(final T entity);
+
+ T update(final T entity);
+
+ void delete(final T entity);
+
+ void deleteById(final long entityId);
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/BarAuditableDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/BarAuditableDao.java
new file mode 100644
index 0000000000..e12b6ae2da
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/BarAuditableDao.java
@@ -0,0 +1,28 @@
+package com.baeldung.persistence.dao.impl;
+
+import java.util.List;
+
+import com.baeldung.persistence.dao.IBarAuditableDao;
+import com.baeldung.persistence.dao.common.AbstractHibernateAuditableDao;
+import com.baeldung.persistence.model.Bar;
+
+public class BarAuditableDao extends AbstractHibernateAuditableDao implements IBarAuditableDao {
+
+ public BarAuditableDao() {
+ super();
+
+ setClazz(Bar.class);
+ }
+
+ // API
+
+ @Override
+ public List getRevisions() {
+ final List resultList = super.getRevisions();
+ for (final Bar bar : resultList) {
+ bar.getFooSet().size(); // force FooSet initialization
+ }
+ return resultList;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/BarDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/BarDao.java
new file mode 100644
index 0000000000..0ead802dc5
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/BarDao.java
@@ -0,0 +1,19 @@
+package com.baeldung.persistence.dao.impl;
+
+import com.baeldung.persistence.dao.common.AbstractHibernateDao;
+import com.baeldung.persistence.dao.IBarDao;
+import com.baeldung.persistence.model.Bar;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public class BarDao extends AbstractHibernateDao implements IBarDao {
+
+ public BarDao() {
+ super();
+
+ setClazz(Bar.class);
+ }
+
+ // API
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/BarJpaDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/BarJpaDao.java
new file mode 100644
index 0000000000..e0fa382d41
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/BarJpaDao.java
@@ -0,0 +1,19 @@
+package com.baeldung.persistence.dao.impl;
+
+import com.baeldung.persistence.dao.IBarDao;
+import com.baeldung.persistence.dao.common.AbstractJpaDao;
+import com.baeldung.persistence.model.Bar;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public class BarJpaDao extends AbstractJpaDao implements IBarDao {
+
+ public BarJpaDao() {
+ super();
+
+ setClazz(Bar.class);
+ }
+
+ // API
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/ChildDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/ChildDao.java
new file mode 100644
index 0000000000..b55da6e43a
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/ChildDao.java
@@ -0,0 +1,19 @@
+package com.baeldung.persistence.dao.impl;
+
+import com.baeldung.persistence.dao.common.AbstractHibernateDao;
+import com.baeldung.persistence.model.Child;
+import com.baeldung.persistence.dao.IChildDao;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public class ChildDao extends AbstractHibernateDao implements IChildDao {
+
+ public ChildDao() {
+ super();
+
+ setClazz(Child.class);
+ }
+
+ // API
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/FooAuditableDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/FooAuditableDao.java
new file mode 100644
index 0000000000..05064c1478
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/FooAuditableDao.java
@@ -0,0 +1,17 @@
+package com.baeldung.persistence.dao.impl;
+
+import com.baeldung.persistence.dao.common.AbstractHibernateAuditableDao;
+import com.baeldung.persistence.model.Foo;
+import com.baeldung.persistence.dao.IFooAuditableDao;
+
+public class FooAuditableDao extends AbstractHibernateAuditableDao implements IFooAuditableDao {
+
+ public FooAuditableDao() {
+ super();
+
+ setClazz(Foo.class);
+ }
+
+ // API
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/FooDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/FooDao.java
new file mode 100644
index 0000000000..787c449b1d
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/FooDao.java
@@ -0,0 +1,19 @@
+package com.baeldung.persistence.dao.impl;
+
+import com.baeldung.persistence.dao.common.AbstractHibernateDao;
+import com.baeldung.persistence.dao.IFooDao;
+import com.baeldung.persistence.model.Foo;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public class FooDao extends AbstractHibernateDao implements IFooDao {
+
+ public FooDao() {
+ super();
+
+ setClazz(Foo.class);
+ }
+
+ // API
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/ParentDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/ParentDao.java
new file mode 100644
index 0000000000..4602b5f30e
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/ParentDao.java
@@ -0,0 +1,19 @@
+package com.baeldung.persistence.dao.impl;
+
+import com.baeldung.persistence.dao.IParentDao;
+import com.baeldung.persistence.dao.common.AbstractHibernateDao;
+import com.baeldung.persistence.model.Parent;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public class ParentDao extends AbstractHibernateDao implements IParentDao {
+
+ public ParentDao() {
+ super();
+
+ setClazz(Parent.class);
+ }
+
+ // API
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/model/Bar.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/model/Bar.java
new file mode 100644
index 0000000000..c7f05254cc
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/model/Bar.java
@@ -0,0 +1,242 @@
+package com.baeldung.persistence.model;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.Set;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EntityListeners;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.NamedQuery;
+import javax.persistence.OneToMany;
+import javax.persistence.PrePersist;
+import javax.persistence.PreRemove;
+import javax.persistence.PreUpdate;
+
+import org.hibernate.annotations.OrderBy;
+import org.hibernate.envers.Audited;
+import org.jboss.logging.Logger;
+import org.springframework.data.annotation.CreatedBy;
+import org.springframework.data.annotation.CreatedDate;
+import org.springframework.data.annotation.LastModifiedBy;
+import org.springframework.data.annotation.LastModifiedDate;
+import org.springframework.data.jpa.domain.support.AuditingEntityListener;
+
+import com.google.common.collect.Sets;
+
+@Entity
+@NamedQuery(name = "Bar.findAll", query = "SELECT b FROM Bar b")
+@Audited
+@EntityListeners(AuditingEntityListener.class)
+public class Bar implements Serializable {
+
+ private static Logger logger = Logger.getLogger(Bar.class);
+
+ public enum OPERATION {
+ INSERT, UPDATE, DELETE;
+ private String value;
+
+ OPERATION() {
+ value = toString();
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public static OPERATION parse(final String value) {
+ OPERATION operation = null;
+ for (final OPERATION op : OPERATION.values()) {
+ if (op.getValue().equals(value)) {
+ operation = op;
+ break;
+ }
+ }
+ return operation;
+ }
+ };
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ @Column(name = "id")
+ private int id;
+
+ @Column(name = "name")
+ private String name;
+
+ @OneToMany(mappedBy = "bar", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
+ @OrderBy(clause = "NAME DESC")
+ // @NotAudited
+ private Set fooSet = Sets.newHashSet();
+
+ @Column(name = "operation")
+ private String operation;
+
+ @Column(name = "timestamp")
+ private long timestamp;
+
+ @Column(name = "created_date", updatable = false, nullable = false)
+ @CreatedDate
+ private long createdDate;
+
+ @Column(name = "modified_date")
+ @LastModifiedDate
+ private long modifiedDate;
+
+ @Column(name = "created_by")
+ @CreatedBy
+ private String createdBy;
+
+ @Column(name = "modified_by")
+ @LastModifiedBy
+ private String modifiedBy;
+
+ public Bar() {
+ super();
+ }
+
+ public Bar(final String name) {
+ super();
+
+ this.name = name;
+ }
+
+ // API
+
+ public Set getFooSet() {
+ return fooSet;
+ }
+
+ public void setFooSet(final Set fooSet) {
+ this.fooSet = fooSet;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(final int id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ public OPERATION getOperation() {
+ return OPERATION.parse(operation);
+ }
+
+ public void setOperation(final OPERATION operation) {
+ this.operation = operation.getValue();
+ }
+
+ public long getTimestamp() {
+ return timestamp;
+ }
+
+ public void setTimestamp(final long timestamp) {
+ this.timestamp = timestamp;
+ }
+
+ public long getCreatedDate() {
+ return createdDate;
+ }
+
+ public void setCreatedDate(final long createdDate) {
+ this.createdDate = createdDate;
+ }
+
+ public long getModifiedDate() {
+ return modifiedDate;
+ }
+
+ public void setModifiedDate(final long modifiedDate) {
+ this.modifiedDate = modifiedDate;
+ }
+
+ public String getCreatedBy() {
+ return createdBy;
+ }
+
+ public void setCreatedBy(final String createdBy) {
+ this.createdBy = createdBy;
+ }
+
+ public String getModifiedBy() {
+ return modifiedBy;
+ }
+
+ public void setModifiedBy(final String modifiedBy) {
+ this.modifiedBy = modifiedBy;
+ }
+
+ public void setOperation(final String operation) {
+ this.operation = operation;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final Bar other = (Bar) obj;
+ if (name == null) {
+ if (other.name != null)
+ return false;
+ } else if (!name.equals(other.name))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("Bar [name=").append(name).append("]");
+ return builder.toString();
+ }
+
+ @PrePersist
+ public void onPrePersist() {
+ logger.info("@PrePersist");
+ audit(OPERATION.INSERT);
+ }
+
+ @PreUpdate
+ public void onPreUpdate() {
+ logger.info("@PreUpdate");
+ audit(OPERATION.UPDATE);
+ }
+
+ @PreRemove
+ public void onPreRemove() {
+ logger.info("@PreRemove");
+ audit(OPERATION.DELETE);
+ }
+
+ private void audit(final OPERATION operation) {
+ setOperation(operation);
+ setTimestamp((new Date()).getTime());
+ }
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/model/Child.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/model/Child.java
new file mode 100644
index 0000000000..19cfb2e237
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/model/Child.java
@@ -0,0 +1,51 @@
+package com.baeldung.persistence.model;
+
+import java.io.Serializable;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.OneToOne;
+
+@Entity
+public class Child implements Serializable {
+
+ @Id
+ @GeneratedValue
+ private long id;
+
+ @OneToOne(mappedBy = "child")
+ private Parent parent;
+
+ public Child() {
+ super();
+ }
+
+ // API
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(final long id) {
+ this.id = id;
+ }
+
+ public Parent getParent() {
+ return parent;
+ }
+
+ public void setParent(final Parent parent) {
+ this.parent = parent;
+ }
+
+ //
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("Child [id=").append(id).append("]");
+ return builder.toString();
+ }
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/model/Foo.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/model/Foo.java
new file mode 100644
index 0000000000..d36a1e58cf
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/model/Foo.java
@@ -0,0 +1,105 @@
+package com.baeldung.persistence.model;
+
+import java.io.Serializable;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedNativeQueries;
+import javax.persistence.NamedNativeQuery;
+
+import org.hibernate.envers.Audited;
+
+@NamedNativeQueries({ @NamedNativeQuery(name = "callGetAllFoos", query = "CALL GetAllFoos()", resultClass = Foo.class), @NamedNativeQuery(name = "callGetFoosByName", query = "CALL GetFoosByName(:fooName)", resultClass = Foo.class) })
+@Entity
+@Audited
+// @Proxy(lazy = false)
+public class Foo implements Serializable {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ @Column(name = "id")
+ private long id;
+
+ @Column(name = "name")
+ private String name;
+
+ @ManyToOne(targetEntity = Bar.class, cascade = CascadeType.ALL, fetch = FetchType.EAGER)
+ @JoinColumn(name = "BAR_ID")
+ private Bar bar = new Bar();
+
+ public Foo() {
+ super();
+ }
+
+ public Foo(final String name) {
+ super();
+ this.name = name;
+ }
+
+ //
+
+ public Bar getBar() {
+ return bar;
+ }
+
+ public void setBar(final Bar bar) {
+ this.bar = bar;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(final long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ //
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final Foo other = (Foo) obj;
+ if (name == null) {
+ if (other.name != null)
+ return false;
+ } else if (!name.equals(other.name))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("Foo [name=").append(name).append("]");
+ return builder.toString();
+ }
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/model/Parent.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/model/Parent.java
new file mode 100644
index 0000000000..fa6948990b
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/model/Parent.java
@@ -0,0 +1,60 @@
+package com.baeldung.persistence.model;
+
+import java.io.Serializable;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToOne;
+
+@Entity
+public class Parent implements Serializable {
+
+ @Id
+ @GeneratedValue
+ private long id;
+
+ @OneToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH, CascadeType.DETACH })
+ @JoinColumn(name = "child_fk")
+ private Child child;
+
+ public Parent() {
+ super();
+ }
+
+ public Parent(final Child child) {
+ super();
+
+ this.child = child;
+ }
+
+ // API
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(final long id) {
+ this.id = id;
+ }
+
+ public Child getChild() {
+ return child;
+ }
+
+ public void setChild(final Child child) {
+ this.child = child;
+ }
+
+ //
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("Parent [id=").append(id).append("]");
+ return builder.toString();
+ }
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/model/Person.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/model/Person.java
new file mode 100644
index 0000000000..6a95a7acf5
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/model/Person.java
@@ -0,0 +1,31 @@
+package com.baeldung.persistence.model;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+
+@Entity
+public class Person {
+
+ @Id
+ @GeneratedValue
+ private Long id;
+
+ private String name;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IBarAuditableService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IBarAuditableService.java
new file mode 100644
index 0000000000..33e5634d12
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IBarAuditableService.java
@@ -0,0 +1,8 @@
+package com.baeldung.persistence.service;
+
+import com.baeldung.persistence.dao.common.IAuditOperations;
+import com.baeldung.persistence.model.Bar;
+
+public interface IBarAuditableService extends IBarService, IAuditOperations {
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IBarService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IBarService.java
new file mode 100644
index 0000000000..21185b5990
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IBarService.java
@@ -0,0 +1,8 @@
+package com.baeldung.persistence.service;
+
+import com.baeldung.persistence.dao.common.IOperations;
+import com.baeldung.persistence.model.Bar;
+
+public interface IBarService extends IOperations {
+ //
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IChildService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IChildService.java
new file mode 100644
index 0000000000..afe67a70c2
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IChildService.java
@@ -0,0 +1,8 @@
+package com.baeldung.persistence.service;
+
+import com.baeldung.persistence.model.Child;
+import com.baeldung.persistence.dao.common.IOperations;
+
+public interface IChildService extends IOperations {
+ //
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IFooAuditableService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IFooAuditableService.java
new file mode 100644
index 0000000000..b787e7fe91
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IFooAuditableService.java
@@ -0,0 +1,8 @@
+package com.baeldung.persistence.service;
+
+import com.baeldung.persistence.dao.common.IAuditOperations;
+import com.baeldung.persistence.model.Foo;
+
+public interface IFooAuditableService extends IFooService, IAuditOperations {
+ //
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IFooService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IFooService.java
new file mode 100644
index 0000000000..ffdb53964a
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IFooService.java
@@ -0,0 +1,8 @@
+package com.baeldung.persistence.service;
+
+import com.baeldung.persistence.model.Foo;
+import com.baeldung.persistence.dao.common.IOperations;
+
+public interface IFooService extends IOperations {
+ //
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IParentService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IParentService.java
new file mode 100644
index 0000000000..f941416aac
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IParentService.java
@@ -0,0 +1,8 @@
+package com.baeldung.persistence.service;
+
+import com.baeldung.persistence.model.Parent;
+import com.baeldung.persistence.dao.common.IOperations;
+
+public interface IParentService extends IOperations {
+ //
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractHibernateAuditableService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractHibernateAuditableService.java
new file mode 100644
index 0000000000..8e2df15519
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractHibernateAuditableService.java
@@ -0,0 +1,31 @@
+package com.baeldung.persistence.service.common;
+
+import java.io.Serializable;
+import java.util.List;
+
+import com.baeldung.persistence.dao.common.IAuditOperations;
+import com.baeldung.persistence.dao.common.IOperations;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional(value = "hibernateTransactionManager")
+public abstract class AbstractHibernateAuditableService extends AbstractHibernateService
+ implements IOperations, IAuditOperations {
+
+ @Override
+ public List getEntitiesAtRevision(final Number revision) {
+ return getAuditableDao().getEntitiesAtRevision(revision);
+ }
+
+ @Override
+ public List getEntitiesModifiedAtRevision(final Number revision) {
+ return getAuditableDao().getEntitiesModifiedAtRevision(revision);
+ }
+
+ @Override
+ public List getRevisions() {
+ return getAuditableDao().getRevisions();
+ }
+
+ abstract protected IAuditOperations getAuditableDao();
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractHibernateService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractHibernateService.java
new file mode 100644
index 0000000000..5da2f299f1
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractHibernateService.java
@@ -0,0 +1,43 @@
+package com.baeldung.persistence.service.common;
+
+import java.io.Serializable;
+import java.util.List;
+
+import com.baeldung.persistence.dao.common.IOperations;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional(value = "hibernateTransactionManager")
+public abstract class AbstractHibernateService extends AbstractService implements
+ IOperations {
+
+ @Override
+ public T findOne(final long id) {
+ return super.findOne(id);
+ }
+
+ @Override
+ public List findAll() {
+ return super.findAll();
+ }
+
+ @Override
+ public void create(final T entity) {
+ super.create(entity);
+ }
+
+ @Override
+ public T update(final T entity) {
+ return super.update(entity);
+ }
+
+ @Override
+ public void delete(final T entity) {
+ super.delete(entity);
+ }
+
+ @Override
+ public void deleteById(final long entityId) {
+ super.deleteById(entityId);
+ }
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractJpaService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractJpaService.java
new file mode 100644
index 0000000000..a1c6fe9edf
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractJpaService.java
@@ -0,0 +1,42 @@
+package com.baeldung.persistence.service.common;
+
+import java.io.Serializable;
+import java.util.List;
+
+import com.baeldung.persistence.dao.common.IOperations;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional(value = "jpaTransactionManager")
+public abstract class AbstractJpaService extends AbstractService implements IOperations {
+
+ @Override
+ public T findOne(final long id) {
+ return super.findOne(id);
+ }
+
+ @Override
+ public List findAll() {
+ return super.findAll();
+ }
+
+ @Override
+ public void create(final T entity) {
+ super.create(entity);
+ }
+
+ @Override
+ public T update(final T entity) {
+ return super.update(entity);
+ }
+
+ @Override
+ public void delete(final T entity) {
+ super.delete(entity);
+ }
+
+ @Override
+ public void deleteById(final long entityId) {
+ super.deleteById(entityId);
+ }
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractService.java
new file mode 100644
index 0000000000..9b001b1fac
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractService.java
@@ -0,0 +1,42 @@
+package com.baeldung.persistence.service.common;
+
+import java.io.Serializable;
+import java.util.List;
+
+import com.baeldung.persistence.dao.common.IOperations;
+
+public abstract class AbstractService implements IOperations {
+
+ @Override
+ public T findOne(final long id) {
+ return getDao().findOne(id);
+ }
+
+ @Override
+ public List findAll() {
+ return getDao().findAll();
+ }
+
+ @Override
+ public void create(final T entity) {
+ getDao().create(entity);
+ }
+
+ @Override
+ public T update(final T entity) {
+ return getDao().update(entity);
+ }
+
+ @Override
+ public void delete(final T entity) {
+ getDao().delete(entity);
+ }
+
+ @Override
+ public void deleteById(final long entityId) {
+ getDao().deleteById(entityId);
+ }
+
+ protected abstract IOperations getDao();
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractSpringDataJpaService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractSpringDataJpaService.java
new file mode 100644
index 0000000000..cef483e6bf
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractSpringDataJpaService.java
@@ -0,0 +1,46 @@
+package com.baeldung.persistence.service.common;
+
+import java.io.Serializable;
+import java.util.List;
+
+import com.baeldung.persistence.dao.common.IOperations;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.google.common.collect.Lists;
+
+@Transactional(value = "jpaTransactionManager")
+public abstract class AbstractSpringDataJpaService implements IOperations {
+
+ @Override
+ public T findOne(final long id) {
+ return getDao().findOne(Long.valueOf(id));
+ }
+
+ @Override
+ public List findAll() {
+ return Lists.newArrayList(getDao().findAll());
+ }
+
+ @Override
+ public void create(final T entity) {
+ getDao().save(entity);
+ }
+
+ @Override
+ public T update(final T entity) {
+ return getDao().save(entity);
+ }
+
+ @Override
+ public void delete(final T entity) {
+ getDao().delete(entity);
+ }
+
+ @Override
+ public void deleteById(final long entityId) {
+ getDao().delete(Long.valueOf(entityId));
+ }
+
+ protected abstract CrudRepository getDao();
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/BarAuditableService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/BarAuditableService.java
new file mode 100644
index 0000000000..d84c28caa5
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/BarAuditableService.java
@@ -0,0 +1,41 @@
+package com.baeldung.persistence.service.impl;
+
+import com.baeldung.persistence.dao.common.IAuditOperations;
+import com.baeldung.persistence.service.common.AbstractHibernateAuditableService;
+import com.baeldung.persistence.dao.IBarAuditableDao;
+import com.baeldung.persistence.dao.IBarDao;
+import com.baeldung.persistence.dao.common.IOperations;
+import com.baeldung.persistence.model.Bar;
+import com.baeldung.persistence.service.IBarAuditableService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Service;
+
+@Service
+public class BarAuditableService extends AbstractHibernateAuditableService implements IBarAuditableService {
+
+ @Autowired
+ @Qualifier("barHibernateDao")
+ private IBarDao dao;
+
+ @Autowired
+ @Qualifier("barHibernateAuditableDao")
+ private IBarAuditableDao auditDao;
+
+ public BarAuditableService() {
+ super();
+ }
+
+ // API
+
+ @Override
+ protected IOperations getDao() {
+ return dao;
+ }
+
+ @Override
+ protected IAuditOperations getAuditableDao() {
+ return auditDao;
+ }
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/BarJpaService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/BarJpaService.java
new file mode 100644
index 0000000000..1c1b7a2274
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/BarJpaService.java
@@ -0,0 +1,30 @@
+package com.baeldung.persistence.service.impl;
+
+import com.baeldung.persistence.dao.IBarDao;
+import com.baeldung.persistence.dao.common.IOperations;
+import com.baeldung.persistence.model.Bar;
+import com.baeldung.persistence.service.IBarService;
+import com.baeldung.persistence.service.common.AbstractJpaService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Service;
+
+@Service
+public class BarJpaService extends AbstractJpaService implements IBarService {
+
+ @Autowired
+ @Qualifier("barJpaDao")
+ private IBarDao dao;
+
+ public BarJpaService() {
+ super();
+ }
+
+ // API
+
+ @Override
+ protected IOperations getDao() {
+ return dao;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/BarService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/BarService.java
new file mode 100644
index 0000000000..32d1f919c5
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/BarService.java
@@ -0,0 +1,30 @@
+package com.baeldung.persistence.service.impl;
+
+import com.baeldung.persistence.dao.IBarDao;
+import com.baeldung.persistence.dao.common.IOperations;
+import com.baeldung.persistence.model.Bar;
+import com.baeldung.persistence.service.IBarService;
+import com.baeldung.persistence.service.common.AbstractHibernateService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Service;
+
+@Service
+public class BarService extends AbstractHibernateService implements IBarService {
+
+ @Autowired
+ @Qualifier("barHibernateDao")
+ private IBarDao dao;
+
+ public BarService() {
+ super();
+ }
+
+ // API
+
+ @Override
+ protected IOperations getDao() {
+ return dao;
+ }
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/BarSpringDataJpaService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/BarSpringDataJpaService.java
new file mode 100644
index 0000000000..4a55d08a35
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/BarSpringDataJpaService.java
@@ -0,0 +1,26 @@
+package com.baeldung.persistence.service.impl;
+
+import java.io.Serializable;
+
+import com.baeldung.persistence.service.common.AbstractSpringDataJpaService;
+import com.baeldung.persistence.dao.IBarCrudRepository;
+import com.baeldung.persistence.model.Bar;
+import com.baeldung.persistence.service.IBarService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.repository.CrudRepository;
+
+public class BarSpringDataJpaService extends AbstractSpringDataJpaService implements IBarService {
+
+ @Autowired
+ private IBarCrudRepository dao;
+
+ public BarSpringDataJpaService() {
+ super();
+ }
+
+ @Override
+ protected CrudRepository getDao() {
+ return dao;
+ }
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/ChildService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/ChildService.java
new file mode 100644
index 0000000000..417fe2c49a
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/ChildService.java
@@ -0,0 +1,28 @@
+package com.baeldung.persistence.service.impl;
+
+import com.baeldung.persistence.model.Child;
+import com.baeldung.persistence.service.IChildService;
+import com.baeldung.persistence.dao.IChildDao;
+import com.baeldung.persistence.dao.common.IOperations;
+import com.baeldung.persistence.service.common.AbstractHibernateService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class ChildService extends AbstractHibernateService implements IChildService {
+
+ @Autowired
+ private IChildDao dao;
+
+ public ChildService() {
+ super();
+ }
+
+ // API
+
+ @Override
+ protected IOperations getDao() {
+ return dao;
+ }
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/FooAuditableService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/FooAuditableService.java
new file mode 100644
index 0000000000..45ad315c42
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/FooAuditableService.java
@@ -0,0 +1,41 @@
+package com.baeldung.persistence.service.impl;
+
+import com.baeldung.persistence.dao.common.IAuditOperations;
+import com.baeldung.persistence.service.IFooAuditableService;
+import com.baeldung.persistence.service.common.AbstractHibernateAuditableService;
+import com.baeldung.persistence.dao.IFooAuditableDao;
+import com.baeldung.persistence.dao.IFooDao;
+import com.baeldung.persistence.dao.common.IOperations;
+import com.baeldung.persistence.model.Foo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Service;
+
+@Service
+public class FooAuditableService extends AbstractHibernateAuditableService implements IFooAuditableService {
+
+ @Autowired
+ @Qualifier("fooHibernateDao")
+ private IFooDao dao;
+
+ @Autowired
+ @Qualifier("fooHibernateAuditableDao")
+ private IFooAuditableDao auditDao;
+
+ public FooAuditableService() {
+ super();
+ }
+
+ // API
+
+ @Override
+ protected IOperations getDao() {
+ return dao;
+ }
+
+ @Override
+ protected IAuditOperations getAuditableDao() {
+ return auditDao;
+ }
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/FooService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/FooService.java
new file mode 100644
index 0000000000..84cf018fee
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/FooService.java
@@ -0,0 +1,30 @@
+package com.baeldung.persistence.service.impl;
+
+import com.baeldung.persistence.dao.IFooDao;
+import com.baeldung.persistence.dao.common.IOperations;
+import com.baeldung.persistence.model.Foo;
+import com.baeldung.persistence.service.IFooService;
+import com.baeldung.persistence.service.common.AbstractHibernateService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Service;
+
+@Service
+public class FooService extends AbstractHibernateService implements IFooService {
+
+ @Autowired
+ @Qualifier("fooHibernateDao")
+ private IFooDao dao;
+
+ public FooService() {
+ super();
+ }
+
+ // API
+
+ @Override
+ protected IOperations getDao() {
+ return dao;
+ }
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/ParentService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/ParentService.java
new file mode 100644
index 0000000000..078acfc369
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/ParentService.java
@@ -0,0 +1,28 @@
+package com.baeldung.persistence.service.impl;
+
+import com.baeldung.persistence.model.Parent;
+import com.baeldung.persistence.service.IParentService;
+import com.baeldung.persistence.dao.IParentDao;
+import com.baeldung.persistence.dao.common.IOperations;
+import com.baeldung.persistence.service.common.AbstractHibernateService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class ParentService extends AbstractHibernateService implements IParentService {
+
+ @Autowired
+ private IParentDao dao;
+
+ public ParentService() {
+ super();
+ }
+
+ // API
+
+ @Override
+ protected IOperations getDao() {
+ return dao;
+ }
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/spring/PersistenceConfig.java b/spring-hibernate5/src/main/java/com/baeldung/spring/PersistenceConfig.java
new file mode 100644
index 0000000000..67ab97e516
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/spring/PersistenceConfig.java
@@ -0,0 +1,173 @@
+package com.baeldung.spring;
+
+import java.util.Properties;
+
+import javax.sql.DataSource;
+
+import org.apache.tomcat.dbcp.dbcp2.BasicDataSource;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.core.env.Environment;
+import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
+import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+import org.springframework.orm.hibernate5.HibernateTransactionManager;
+import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
+import org.springframework.orm.jpa.JpaTransactionManager;
+import org.springframework.orm.jpa.JpaVendorAdapter;
+import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
+import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+import com.baeldung.persistence.dao.IBarAuditableDao;
+import com.baeldung.persistence.dao.IBarDao;
+import com.baeldung.persistence.dao.IFooAuditableDao;
+import com.baeldung.persistence.dao.IFooDao;
+import com.baeldung.persistence.dao.impl.BarAuditableDao;
+import com.baeldung.persistence.dao.impl.BarDao;
+import com.baeldung.persistence.dao.impl.BarJpaDao;
+import com.baeldung.persistence.dao.impl.FooAuditableDao;
+import com.baeldung.persistence.dao.impl.FooDao;
+import com.baeldung.persistence.service.IBarAuditableService;
+import com.baeldung.persistence.service.IBarService;
+import com.baeldung.persistence.service.IFooAuditableService;
+import com.baeldung.persistence.service.IFooService;
+import com.baeldung.persistence.service.impl.BarAuditableService;
+import com.baeldung.persistence.service.impl.BarJpaService;
+import com.baeldung.persistence.service.impl.BarSpringDataJpaService;
+import com.baeldung.persistence.service.impl.FooAuditableService;
+import com.baeldung.persistence.service.impl.FooService;
+import com.google.common.base.Preconditions;
+
+@Configuration
+@EnableTransactionManagement
+@EnableJpaRepositories(basePackages = { "com.baeldung.persistence" }, transactionManagerRef = "jpaTransactionManager")
+@EnableJpaAuditing
+@PropertySource({ "classpath:persistence-mysql.properties" })
+@ComponentScan({ "com.baeldung.persistence" })
+public class PersistenceConfig {
+
+ @Autowired
+ private Environment env;
+
+ @Bean
+ public LocalSessionFactoryBean sessionFactory() {
+ final LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
+ sessionFactory.setDataSource(restDataSource());
+ sessionFactory.setPackagesToScan(new String[] { "com.baeldung.persistence.model" });
+ sessionFactory.setHibernateProperties(hibernateProperties());
+
+ return sessionFactory;
+ }
+
+ @Bean
+ public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
+ final LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
+ emf.setDataSource(restDataSource());
+ emf.setPackagesToScan(new String[] { "com.baeldung.persistence.model" });
+
+ final JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
+ emf.setJpaVendorAdapter(vendorAdapter);
+ emf.setJpaProperties(hibernateProperties());
+
+ return emf;
+ }
+
+ @Bean
+ public DataSource restDataSource() {
+ final BasicDataSource dataSource = new BasicDataSource();
+ dataSource.setDriverClassName(Preconditions.checkNotNull(env.getProperty("jdbc.driverClassName")));
+ dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("jdbc.url")));
+ dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("jdbc.user")));
+ dataSource.setPassword(Preconditions.checkNotNull(env.getProperty("jdbc.pass")));
+
+ return dataSource;
+ }
+
+ @Bean
+ public PlatformTransactionManager hibernateTransactionManager() {
+ final HibernateTransactionManager transactionManager = new HibernateTransactionManager();
+ transactionManager.setSessionFactory(sessionFactory().getObject());
+ return transactionManager;
+ }
+
+ @Bean
+ public PlatformTransactionManager jpaTransactionManager() {
+ final JpaTransactionManager transactionManager = new JpaTransactionManager();
+ transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
+ return transactionManager;
+ }
+
+ @Bean
+ public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
+ return new PersistenceExceptionTranslationPostProcessor();
+ }
+
+ @Bean
+ public IBarService barJpaService() {
+ return new BarJpaService();
+ }
+
+ @Bean
+ public IBarService barSpringDataJpaService() {
+ return new BarSpringDataJpaService();
+ }
+
+ @Bean
+ public IFooService fooHibernateService() {
+ return new FooService();
+ }
+
+ @Bean
+ public IBarAuditableService barHibernateAuditableService() {
+ return new BarAuditableService();
+ }
+
+ @Bean
+ public IFooAuditableService fooHibernateAuditableService() {
+ return new FooAuditableService();
+ }
+
+ @Bean
+ public IBarDao barJpaDao() {
+ return new BarJpaDao();
+ }
+
+ @Bean
+ public IBarDao barHibernateDao() {
+ return new BarDao();
+ }
+
+ @Bean
+ public IBarAuditableDao barHibernateAuditableDao() {
+ return new BarAuditableDao();
+ }
+
+ @Bean
+ public IFooDao fooHibernateDao() {
+ return new FooDao();
+ }
+
+ @Bean
+ public IFooAuditableDao fooHibernateAuditableDao() {
+ return new FooAuditableDao();
+ }
+
+ private final Properties hibernateProperties() {
+ final Properties hibernateProperties = new Properties();
+ hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
+ hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
+
+ hibernateProperties.setProperty("hibernate.show_sql", "true");
+
+ // Envers properties
+ hibernateProperties.setProperty("org.hibernate.envers.audit_table_suffix", env.getProperty("envers.audit_table_suffix"));
+
+ return hibernateProperties;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-hibernate5/src/main/java/com/baeldung/spring/PersistenceXmlConfig.java b/spring-hibernate5/src/main/java/com/baeldung/spring/PersistenceXmlConfig.java
new file mode 100644
index 0000000000..e93fcca3e1
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/spring/PersistenceXmlConfig.java
@@ -0,0 +1,14 @@
+package com.baeldung.spring;
+
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.ImportResource;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+@Configuration
+@EnableTransactionManagement
+@ComponentScan({ "com.baeldung.persistence.dao", "com.baeldung.persistence.service" })
+@ImportResource({ "classpath:hibernate5Config.xml" })
+public class PersistenceXmlConfig {
+
+}
\ No newline at end of file
diff --git a/spring-hibernate5/src/main/resources/criteria.cfg.xml b/spring-hibernate5/src/main/resources/criteria.cfg.xml
new file mode 100644
index 0000000000..0b865fc4d1
--- /dev/null
+++ b/spring-hibernate5/src/main/resources/criteria.cfg.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+ com.mysql.jdbc.Driver
+ jdbc:mysql://localhost:3306/test
+ root
+ root
+ org.hibernate.dialect.MySQLDialect
+ true
+
+
+
\ No newline at end of file
diff --git a/spring-hibernate5/src/main/resources/criteria_create_queries.sql b/spring-hibernate5/src/main/resources/criteria_create_queries.sql
new file mode 100644
index 0000000000..3a627dd38c
--- /dev/null
+++ b/spring-hibernate5/src/main/resources/criteria_create_queries.sql
@@ -0,0 +1,7 @@
+CREATE TABLE `item` (
+ `ITEM_ID` int(11) NOT NULL AUTO_INCREMENT,
+ `ITEM_DESC` varchar(100) DEFAULT NULL,
+ `ITEM_PRICE` int(11) NOT NULL,
+ `ITEM_NAME` varchar(255) NOT NULL,
+ PRIMARY KEY (`ITEM_ID`)
+) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=latin1;
diff --git a/spring-hibernate5/src/main/resources/fetching.cfg.xml b/spring-hibernate5/src/main/resources/fetching.cfg.xml
new file mode 100644
index 0000000000..b1ffecafce
--- /dev/null
+++ b/spring-hibernate5/src/main/resources/fetching.cfg.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+ com.mysql.jdbc.Driver
+ jdbc:mysql://localhost:3306/test
+ root
+ root
+ org.hibernate.dialect.MySQLDialect
+ true
+ validate
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-hibernate5/src/main/resources/fetchingLazy.cfg.xml b/spring-hibernate5/src/main/resources/fetchingLazy.cfg.xml
new file mode 100644
index 0000000000..a18fdbfa99
--- /dev/null
+++ b/spring-hibernate5/src/main/resources/fetchingLazy.cfg.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+ com.mysql.jdbc.Driver
+ jdbc:mysql://localhost:3306/test
+ root
+ root
+ org.hibernate.dialect.MySQLDialect
+ true
+
+
+
+
\ No newline at end of file
diff --git a/spring-hibernate5/src/main/resources/fetching_create_queries.sql b/spring-hibernate5/src/main/resources/fetching_create_queries.sql
new file mode 100644
index 0000000000..b36d9828f1
--- /dev/null
+++ b/spring-hibernate5/src/main/resources/fetching_create_queries.sql
@@ -0,0 +1,14 @@
+CREATE TABLE `user` (
+ `user_id` int(10) NOT NULL AUTO_INCREMENT,
+ PRIMARY KEY (`user_id`)
+) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=latin1 ;
+
+
+CREATE TABLE `user_order` (
+ `ORDER_ID` int(10) NOT NULL AUTO_INCREMENT,
+ `USER_ID` int(10) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`ORDER_ID`,`USER_ID`),
+ KEY `USER_ID` (`USER_ID`),
+ CONSTRAINT `user_order_ibfk_1` FOREIGN KEY (`USER_ID`) REFERENCES `USER` (`user_id`)
+) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1;
+
diff --git a/spring-hibernate5/src/main/resources/hibernate5Config.xml b/spring-hibernate5/src/main/resources/hibernate5Config.xml
new file mode 100644
index 0000000000..55546a862a
--- /dev/null
+++ b/spring-hibernate5/src/main/resources/hibernate5Config.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+ ${hibernate.hbm2ddl.auto}
+ ${hibernate.dialect}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-hibernate5/src/main/resources/insert_statements.sql b/spring-hibernate5/src/main/resources/insert_statements.sql
new file mode 100644
index 0000000000..ae008f29bc
--- /dev/null
+++ b/spring-hibernate5/src/main/resources/insert_statements.sql
@@ -0,0 +1,31 @@
+insert into item (item_id, item_name, item_desc, item_price)
+values(1,'item One', 'test 1', 35.12);
+
+insert into item (item_id, item_name, item_desc, item_price)
+values(2,'Pogo stick', 'Pogo stick', 466.12);
+insert into item (item_id, item_name, item_desc, item_price)
+values(3,'Raft', 'Raft', 345.12);
+
+insert into item (item_id, item_name, item_desc, item_price)
+values(4,'Skate Board', 'Skating', 135.71);
+
+insert into item (item_id, item_name, item_desc, item_price)
+values(5,'Umbrella', 'Umbrella for Rain', 619.25);
+
+insert into item (item_id, item_name, item_desc, item_price)
+values(6,'Glue', 'Glue for home', 432.73);
+
+insert into item (item_id, item_name, item_desc, item_price)
+values(7,'Paint', 'Paint for Room', 1311.40);
+
+insert into item (item_id, item_name, item_desc, item_price)
+values(8,'Red paint', 'Red paint for room', 1135.71);
+
+insert into item (item_id, item_name, item_desc, item_price)
+values(9,'Household Chairs', 'Chairs for house', 25.71);
+
+insert into item (item_id, item_name, item_desc, item_price)
+values(10,'Office Chairs', 'Chairs for office', 395.98);
+
+insert into item (item_id, item_name, item_desc, item_price)
+values(11,'Outdoor Chairs', 'Chairs for outdoor activities', 1234.36);
diff --git a/spring-hibernate5/src/main/resources/logback.xml b/spring-hibernate5/src/main/resources/logback.xml
new file mode 100644
index 0000000000..71a6d50a58
--- /dev/null
+++ b/spring-hibernate5/src/main/resources/logback.xml
@@ -0,0 +1,22 @@
+
+
+
+
+ web - %date [%thread] %-5level %logger{36} - %message%n
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-hibernate5/src/main/resources/persistence-mysql.properties b/spring-hibernate5/src/main/resources/persistence-mysql.properties
new file mode 100644
index 0000000000..1180929b30
--- /dev/null
+++ b/spring-hibernate5/src/main/resources/persistence-mysql.properties
@@ -0,0 +1,13 @@
+# jdbc.X
+jdbc.driverClassName=com.mysql.cj.jdbc.Driver
+jdbc.url=jdbc:mysql://localhost:3306/spring_hibernate5_01?createDatabaseIfNotExist=true
+jdbc.user=tutorialuser
+jdbc.pass=tutorialmy5ql
+
+# hibernate.X
+hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
+hibernate.show_sql=false
+hibernate.hbm2ddl.auto=create-drop
+
+# envers.X
+envers.audit_table_suffix=_audit_log
diff --git a/spring-hibernate5/src/main/resources/stored_procedure.sql b/spring-hibernate5/src/main/resources/stored_procedure.sql
new file mode 100644
index 0000000000..9cedb75c37
--- /dev/null
+++ b/spring-hibernate5/src/main/resources/stored_procedure.sql
@@ -0,0 +1,20 @@
+DELIMITER //
+ CREATE PROCEDURE GetFoosByName(IN fooName VARCHAR(255))
+ LANGUAGE SQL
+ DETERMINISTIC
+ SQL SECURITY DEFINER
+ BEGIN
+ SELECT * FROM foo WHERE name = fooName;
+ END //
+DELIMITER ;
+
+
+DELIMITER //
+ CREATE PROCEDURE GetAllFoos()
+ LANGUAGE SQL
+ DETERMINISTIC
+ SQL SECURITY DEFINER
+ BEGIN
+ SELECT * FROM foo;
+ END //
+DELIMITER ;
\ No newline at end of file
diff --git a/spring-hibernate5/src/main/resources/webSecurityConfig.xml b/spring-hibernate5/src/main/resources/webSecurityConfig.xml
new file mode 100644
index 0000000000..e5c19a4ad7
--- /dev/null
+++ b/spring-hibernate5/src/main/resources/webSecurityConfig.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-hibernate5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaIntegrationTest.java b/spring-hibernate5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaIntegrationTest.java
new file mode 100644
index 0000000000..7caa02f156
--- /dev/null
+++ b/spring-hibernate5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaIntegrationTest.java
@@ -0,0 +1,194 @@
+package com.baeldung.hibernate.criteria;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.List;
+
+import org.hibernate.Session;
+import org.junit.Test;
+
+import com.baeldung.hibernate.criteria.model.Item;
+import com.baeldung.hibernate.criteria.util.HibernateUtil;
+import com.baeldung.hibernate.criteria.view.ApplicationView;
+
+public class HibernateCriteriaIntegrationTest {
+
+ final private ApplicationView av = new ApplicationView();
+
+ @Test
+ public void testPerformanceOfCriteria() {
+ assertTrue(av.checkIfCriteriaTimeLower());
+ }
+
+ @Test
+ public void testLikeCriteriaQuery() {
+ final Session session = HibernateUtil.getHibernateSession();
+ final List
- expectedLikeList = session.createQuery("From Item where itemName like '%chair%'")
+ .getResultList();
+ final String expectedLikeItems[] = new String[expectedLikeList.size()];
+ for (int i = 0; i < expectedLikeList.size(); i++) {
+ expectedLikeItems[i] = expectedLikeList.get(i).getItemName();
+ }
+ session.close();
+ assertArrayEquals(expectedLikeItems, av.likeCriteria());
+ }
+
+ @Test
+ public void testILikeCriteriaQuery() {
+ final Session session = HibernateUtil.getHibernateSession();
+ final List
- expectedChairCaseList = session.createQuery("From Item where itemName like '%Chair%'")
+ .getResultList();
+ final String expectedChairCaseItems[] = new String[expectedChairCaseList.size()];
+ for (int i = 0; i < expectedChairCaseList.size(); i++) {
+ expectedChairCaseItems[i] = expectedChairCaseList.get(i).getItemName();
+ }
+ session.close();
+ assertArrayEquals(expectedChairCaseItems, av.likeCaseCriteria());
+
+ }
+
+ @Test
+ public void testNullCriteriaQuery() {
+ final Session session = HibernateUtil.getHibernateSession();
+ final List
- expectedIsNullDescItemsList = session.createQuery("From Item where itemDescription is null")
+ .getResultList();
+ final String expectedIsNullDescItems[] = new String[expectedIsNullDescItemsList.size()];
+ for (int i = 0; i < expectedIsNullDescItemsList.size(); i++) {
+ expectedIsNullDescItems[i] = expectedIsNullDescItemsList.get(i).getItemName();
+ }
+ session.close();
+ assertArrayEquals(expectedIsNullDescItems, av.nullCriteria());
+ }
+
+ @Test
+ public void testIsNotNullCriteriaQuery() {
+ final Session session = HibernateUtil.getHibernateSession();
+ final List
- expectedIsNotNullDescItemsList = session.createQuery(
+ "From Item where itemDescription is not null").getResultList();
+ final String expectedIsNotNullDescItems[] = new String[expectedIsNotNullDescItemsList.size()];
+ for (int i = 0; i < expectedIsNotNullDescItemsList.size(); i++) {
+ expectedIsNotNullDescItems[i] = expectedIsNotNullDescItemsList.get(i).getItemName();
+ }
+ session.close();
+ assertArrayEquals(expectedIsNotNullDescItems, av.notNullCriteria());
+
+ }
+
+ @Test
+ public void testAverageProjection() {
+ final Session session = HibernateUtil.getHibernateSession();
+ final List expectedAvgProjItemsList = session.createQuery("Select avg(itemPrice) from Item item")
+ .getResultList();
+
+ final Double expectedAvgProjItems[] = new Double[expectedAvgProjItemsList.size()];
+ for (int i = 0; i < expectedAvgProjItemsList.size(); i++) {
+ expectedAvgProjItems[i] = expectedAvgProjItemsList.get(i);
+ }
+ session.close();
+ assertArrayEquals(expectedAvgProjItems, av.projectionAverage());
+
+ }
+
+ @Test
+ public void testRowCountProjection() {
+ final Session session = HibernateUtil.getHibernateSession();
+ final List expectedCountProjItemsList = session.createQuery("Select count(*) from Item").getResultList();
+ final Long expectedCountProjItems[] = new Long[expectedCountProjItemsList.size()];
+ for (int i = 0; i < expectedCountProjItemsList.size(); i++) {
+ expectedCountProjItems[i] = expectedCountProjItemsList.get(i);
+ }
+ session.close();
+ assertArrayEquals(expectedCountProjItems, av.projectionRowCount());
+ }
+
+ @Test
+ public void testOrCriteriaQuery() {
+ final Session session = HibernateUtil.getHibernateSession();
+ final List
- expectedOrCritItemsList = session.createQuery(
+ "From Item where itemPrice>1000 or itemName like 'Chair%'").getResultList();
+ final String expectedOrCritItems[] = new String[expectedOrCritItemsList.size()];
+ for (int i = 0; i < expectedOrCritItemsList.size(); i++) {
+ expectedOrCritItems[i] = expectedOrCritItemsList.get(i).getItemName();
+ }
+ session.close();
+ assertArrayEquals(expectedOrCritItems, av.orLogicalCriteria());
+ }
+
+ @Test
+ public void testAndCriteriaQuery() {
+ final Session session = HibernateUtil.getHibernateSession();
+ final List
- expectedAndCritItemsList = session.createQuery(
+ "From Item where itemPrice>1000 and itemName like 'Chair%'").getResultList();
+ final String expectedAndCritItems[] = new String[expectedAndCritItemsList.size()];
+ for (int i = 0; i < expectedAndCritItemsList.size(); i++) {
+ expectedAndCritItems[i] = expectedAndCritItemsList.get(i).getItemName();
+ }
+ session.close();
+ assertArrayEquals(expectedAndCritItems, av.andLogicalCriteria());
+ }
+
+ @Test
+ public void testMultiCriteriaQuery() {
+ final Session session = HibernateUtil.getHibernateSession();
+ final List
- expectedMultiCritItemsList = session.createQuery(
+ "From Item where itemDescription is null and itemName like'chair%'").getResultList();
+ final String expectedMultiCritItems[] = new String[expectedMultiCritItemsList.size()];
+ for (int i = 0; i < expectedMultiCritItemsList.size(); i++) {
+ expectedMultiCritItems[i] = expectedMultiCritItemsList.get(i).getItemName();
+ }
+ session.close();
+ assertArrayEquals(expectedMultiCritItems, av.twoCriteria());
+ }
+
+ @Test
+ public void testSortCriteriaQuery() {
+ final Session session = HibernateUtil.getHibernateSession();
+ final List
- expectedSortCritItemsList = session.createQuery(
+ "From Item order by itemName asc, itemPrice desc").getResultList();
+ final String expectedSortCritItems[] = new String[expectedSortCritItemsList.size()];
+ for (int i = 0; i < expectedSortCritItemsList.size(); i++) {
+ expectedSortCritItems[i] = expectedSortCritItemsList.get(i).getItemName();
+ }
+ session.close();
+ assertArrayEquals(expectedSortCritItems, av.sortingCriteria());
+ }
+
+ @Test
+ public void testGreaterThanCriteriaQuery() {
+ final Session session = HibernateUtil.getHibernateSession();
+ final List
- expectedGreaterThanList = session.createQuery("From Item where itemPrice>1000")
+ .getResultList();
+ final String expectedGreaterThanItems[] = new String[expectedGreaterThanList.size()];
+ for (int i = 0; i < expectedGreaterThanList.size(); i++) {
+ expectedGreaterThanItems[i] = expectedGreaterThanList.get(i).getItemName();
+ }
+ session.close();
+ assertArrayEquals(expectedGreaterThanItems, av.greaterThanCriteria());
+ }
+
+ @Test
+ public void testLessThanCriteriaQuery() {
+ final Session session = HibernateUtil.getHibernateSession();
+ final List
- expectedLessList = session.createQuery("From Item where itemPrice<1000").getResultList();
+ final String expectedLessThanItems[] = new String[expectedLessList.size()];
+ for (int i = 0; i < expectedLessList.size(); i++) {
+ expectedLessThanItems[i] = expectedLessList.get(i).getItemName();
+ }
+ session.close();
+ assertArrayEquals(expectedLessThanItems, av.lessThanCriteria());
+ }
+
+ @Test
+ public void betweenCriteriaQuery() {
+ final Session session = HibernateUtil.getHibernateSession();
+ final List
- expectedBetweenList = session.createQuery("From Item where itemPrice between 100 and 200")
+ .getResultList();
+ final String expectedPriceBetweenItems[] = new String[expectedBetweenList.size()];
+ for (int i = 0; i < expectedBetweenList.size(); i++) {
+ expectedPriceBetweenItems[i] = expectedBetweenList.get(i).getItemName();
+ }
+ session.close();
+ assertArrayEquals(expectedPriceBetweenItems, av.betweenCriteria());
+ }
+}
diff --git a/spring-hibernate5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaTestRunner.java b/spring-hibernate5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaTestRunner.java
new file mode 100644
index 0000000000..99164efb7a
--- /dev/null
+++ b/spring-hibernate5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaTestRunner.java
@@ -0,0 +1,15 @@
+package com.baeldung.hibernate.criteria;
+
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Result;
+import org.junit.runner.notification.Failure;
+
+public class HibernateCriteriaTestRunner {
+
+ public static void main(final String[] args) {
+ Result result = JUnitCore.runClasses(HibernateCriteriaTestSuite.class);
+ for (Failure failure : result.getFailures()) {
+
+ }
+ }
+}
diff --git a/spring-hibernate5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaTestSuite.java b/spring-hibernate5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaTestSuite.java
new file mode 100644
index 0000000000..dc1040734f
--- /dev/null
+++ b/spring-hibernate5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaTestSuite.java
@@ -0,0 +1,11 @@
+package com.baeldung.hibernate.criteria;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses({ HibernateCriteriaIntegrationTest.class })
+
+public class HibernateCriteriaTestSuite {
+
+}
diff --git a/spring-hibernate5/src/test/java/com/baeldung/hibernate/fetching/HibernateFetchingIntegrationTest.java b/spring-hibernate5/src/test/java/com/baeldung/hibernate/fetching/HibernateFetchingIntegrationTest.java
new file mode 100644
index 0000000000..65bf36f8bf
--- /dev/null
+++ b/spring-hibernate5/src/test/java/com/baeldung/hibernate/fetching/HibernateFetchingIntegrationTest.java
@@ -0,0 +1,42 @@
+package com.baeldung.hibernate.fetching;
+
+import com.baeldung.hibernate.fetching.model.OrderDetail;
+import com.baeldung.hibernate.fetching.view.FetchingAppView;
+import org.hibernate.Hibernate;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.Set;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class HibernateFetchingIntegrationTest {
+
+ // this loads sample data in the database
+ @Before
+ public void addFecthingTestData() {
+ FetchingAppView fav = new FetchingAppView();
+ fav.createTestData();
+ }
+
+ // testLazyFetching() tests the lazy loading
+ // Since it lazily loaded so orderDetalSetLazy won't
+ // be initialized
+ @Test
+ public void testLazyFetching() {
+ FetchingAppView fav = new FetchingAppView();
+ Set orderDetalSetLazy = fav.lazyLoaded();
+ assertFalse(Hibernate.isInitialized(orderDetalSetLazy));
+ }
+
+ // testEagerFetching() tests the eager loading
+ // Since it eagerly loaded so orderDetalSetLazy would
+ // be initialized
+ @Test
+ public void testEagerFetching() {
+ FetchingAppView fav = new FetchingAppView();
+ Set orderDetalSetEager = fav.eagerLoaded();
+ assertTrue(Hibernate.isInitialized(orderDetalSetEager));
+ }
+}
diff --git a/spring-hibernate5/src/test/java/com/baeldung/persistence/IntegrationTestSuite.java b/spring-hibernate5/src/test/java/com/baeldung/persistence/IntegrationTestSuite.java
new file mode 100644
index 0000000000..f5c45a5d6f
--- /dev/null
+++ b/spring-hibernate5/src/test/java/com/baeldung/persistence/IntegrationTestSuite.java
@@ -0,0 +1,25 @@
+package com.baeldung.persistence;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+import com.baeldung.persistence.audit.AuditTestSuite;
+import com.baeldung.persistence.hibernate.FooPaginationPersistenceIntegrationTest;
+import com.baeldung.persistence.hibernate.FooSortingPersistenceIntegrationTest;
+import com.baeldung.persistence.service.FooServiceBasicPersistenceIntegrationTest;
+import com.baeldung.persistence.service.FooServicePersistenceIntegrationTest;
+import com.baeldung.persistence.service.ParentServicePersistenceIntegrationTest;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses({ // @formatter:off
+ AuditTestSuite.class
+ ,FooServiceBasicPersistenceIntegrationTest.class
+ ,FooPaginationPersistenceIntegrationTest.class
+ ,FooServicePersistenceIntegrationTest.class
+ ,ParentServicePersistenceIntegrationTest.class
+ ,FooSortingPersistenceIntegrationTest.class
+
+}) // @formatter:on
+public class IntegrationTestSuite {
+ //
+}
diff --git a/spring-hibernate5/src/test/java/com/baeldung/persistence/audit/AuditTestSuite.java b/spring-hibernate5/src/test/java/com/baeldung/persistence/audit/AuditTestSuite.java
new file mode 100644
index 0000000000..34c725d62b
--- /dev/null
+++ b/spring-hibernate5/src/test/java/com/baeldung/persistence/audit/AuditTestSuite.java
@@ -0,0 +1,14 @@
+package com.baeldung.persistence.audit;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses({ // @formatter:off
+ EnversFooBarAuditIntegrationTest.class,
+ JPABarAuditIntegrationTest.class,
+ SpringDataJPABarAuditIntegrationTest.class
+}) // @formatter:on
+public class AuditTestSuite {
+ //
+}
\ No newline at end of file
diff --git a/spring-hibernate5/src/test/java/com/baeldung/persistence/audit/EnversFooBarAuditIntegrationTest.java b/spring-hibernate5/src/test/java/com/baeldung/persistence/audit/EnversFooBarAuditIntegrationTest.java
new file mode 100644
index 0000000000..ed2e111c8f
--- /dev/null
+++ b/spring-hibernate5/src/test/java/com/baeldung/persistence/audit/EnversFooBarAuditIntegrationTest.java
@@ -0,0 +1,142 @@
+package com.baeldung.persistence.audit;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.List;
+
+import com.baeldung.persistence.model.Foo;
+import com.baeldung.persistence.service.IBarAuditableService;
+import com.baeldung.persistence.service.IFooAuditableService;
+import com.baeldung.spring.PersistenceConfig;
+import com.baeldung.persistence.model.Bar;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+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.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.AnnotationConfigContextLoader;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class)
+public class EnversFooBarAuditIntegrationTest {
+
+ private static Logger logger = LoggerFactory.getLogger(EnversFooBarAuditIntegrationTest.class);
+
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ logger.info("setUpBeforeClass()");
+ }
+
+ @AfterClass
+ public static void tearDownAfterClass() throws Exception {
+ logger.info("tearDownAfterClass()");
+ }
+
+ @Autowired
+ @Qualifier("fooHibernateAuditableService")
+ private IFooAuditableService fooService;
+
+ @Autowired
+ @Qualifier("barHibernateAuditableService")
+ private IBarAuditableService barService;
+
+ @Autowired
+ private SessionFactory sessionFactory;
+
+ private Session session;
+
+ @Before
+ public void setUp() throws Exception {
+ logger.info("setUp()");
+ makeRevisions();
+ session = sessionFactory.openSession();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ logger.info("tearDown()");
+ session.close();
+ }
+
+ private void makeRevisions() {
+ final Bar bar = rev1();
+ rev2(bar);
+ rev3(bar);
+ rev4(bar);
+ }
+
+ // REV #1: insert BAR & FOO1
+ private Bar rev1() {
+ final Bar bar = new Bar("BAR");
+ final Foo foo1 = new Foo("FOO1");
+ foo1.setBar(bar);
+ fooService.create(foo1);
+ return bar;
+ }
+
+ // REV #2: insert FOO2 & update BAR
+ private void rev2(final Bar bar) {
+ final Foo foo2 = new Foo("FOO2");
+ foo2.setBar(bar);
+ fooService.create(foo2);
+ }
+
+ // REV #3: update BAR
+ private void rev3(final Bar bar) {
+
+ bar.setName("BAR1");
+ barService.update(bar);
+ }
+
+ // REV #4: insert FOO3 & update BAR
+ private void rev4(final Bar bar) {
+
+ final Foo foo3 = new Foo("FOO3");
+ foo3.setBar(bar);
+ fooService.create(foo3);
+ }
+
+ @Test
+ public final void whenFooBarsModified_thenFooBarsAudited() {
+
+ List barRevisionList;
+ List fooRevisionList;
+
+ // test Bar revisions
+
+ barRevisionList = barService.getRevisions();
+
+ assertNotNull(barRevisionList);
+ assertEquals(4, barRevisionList.size());
+
+ assertEquals("BAR", barRevisionList.get(0).getName());
+ assertEquals("BAR", barRevisionList.get(1).getName());
+ assertEquals("BAR1", barRevisionList.get(2).getName());
+ assertEquals("BAR1", barRevisionList.get(3).getName());
+
+ assertEquals(1, barRevisionList.get(0).getFooSet().size());
+ assertEquals(2, barRevisionList.get(1).getFooSet().size());
+ assertEquals(2, barRevisionList.get(2).getFooSet().size());
+ assertEquals(3, barRevisionList.get(3).getFooSet().size());
+
+ // test Foo revisions
+
+ fooRevisionList = fooService.getRevisions();
+ assertNotNull(fooRevisionList);
+ assertEquals(3, fooRevisionList.size());
+ assertEquals("FOO1", fooRevisionList.get(0).getName());
+ assertEquals("FOO2", fooRevisionList.get(1).getName());
+ assertEquals("FOO3", fooRevisionList.get(2).getName());
+ }
+
+}
diff --git a/spring-hibernate5/src/test/java/com/baeldung/persistence/audit/JPABarAuditIntegrationTest.java b/spring-hibernate5/src/test/java/com/baeldung/persistence/audit/JPABarAuditIntegrationTest.java
new file mode 100644
index 0000000000..b63a4b989b
--- /dev/null
+++ b/spring-hibernate5/src/test/java/com/baeldung/persistence/audit/JPABarAuditIntegrationTest.java
@@ -0,0 +1,102 @@
+package com.baeldung.persistence.audit;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+
+import com.baeldung.persistence.model.Bar;
+import com.baeldung.persistence.model.Bar.OPERATION;
+import com.baeldung.persistence.service.IBarService;
+import com.baeldung.spring.PersistenceConfig;
+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.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.AnnotationConfigContextLoader;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class)
+public class JPABarAuditIntegrationTest {
+
+ private static Logger logger = LoggerFactory.getLogger(JPABarAuditIntegrationTest.class);
+
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ logger.info("setUpBeforeClass()");
+ }
+
+ @AfterClass
+ public static void tearDownAfterClass() throws Exception {
+ logger.info("tearDownAfterClass()");
+ }
+
+ @Autowired
+ @Qualifier("barJpaService")
+ private IBarService barService;
+
+ @Autowired
+ private EntityManagerFactory entityManagerFactory;
+
+ private EntityManager em;
+
+ @Before
+ public void setUp() throws Exception {
+ logger.info("setUp()");
+ em = entityManagerFactory.createEntityManager();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ logger.info("tearDown()");
+ em.close();
+ }
+
+ @Test
+ public final void whenBarsModified_thenBarsAudited() {
+
+ // insert BAR1
+ Bar bar1 = new Bar("BAR1");
+ barService.create(bar1);
+
+ // update BAR1
+ bar1.setName("BAR1a");
+ barService.update(bar1);
+
+ // insert BAR2
+ Bar bar2 = new Bar("BAR2");
+ barService.create(bar2);
+
+ // update BAR1
+ bar1.setName("BAR1b");
+ barService.update(bar1);
+
+ // get BAR1 and BAR2 from the DB and check the audit values
+ // detach instances from persistence context to make sure we fire db
+ em.detach(bar1);
+ em.detach(bar2);
+ bar1 = barService.findOne(bar1.getId());
+ bar2 = barService.findOne(bar2.getId());
+
+ assertNotNull(bar1);
+ assertNotNull(bar2);
+ assertEquals(OPERATION.UPDATE, bar1.getOperation());
+ assertEquals(OPERATION.INSERT, bar2.getOperation());
+ assertTrue(bar1.getTimestamp() > bar2.getTimestamp());
+
+ barService.deleteById(bar1.getId());
+ barService.deleteById(bar2.getId());
+
+ }
+
+}
\ No newline at end of file
diff --git a/spring-hibernate5/src/test/java/com/baeldung/persistence/audit/SpringDataJPABarAuditIntegrationTest.java b/spring-hibernate5/src/test/java/com/baeldung/persistence/audit/SpringDataJPABarAuditIntegrationTest.java
new file mode 100644
index 0000000000..e794b282f6
--- /dev/null
+++ b/spring-hibernate5/src/test/java/com/baeldung/persistence/audit/SpringDataJPABarAuditIntegrationTest.java
@@ -0,0 +1,76 @@
+package com.baeldung.persistence.audit;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+
+import com.baeldung.persistence.model.Bar;
+import com.baeldung.persistence.service.IBarService;
+import com.baeldung.spring.PersistenceConfig;
+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.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.security.test.context.support.WithMockUser;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.AnnotationConfigContextLoader;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class)
+public class SpringDataJPABarAuditIntegrationTest {
+
+ private static Logger logger = LoggerFactory.getLogger(SpringDataJPABarAuditIntegrationTest.class);
+
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ logger.info("setUpBeforeClass()");
+ }
+
+ @AfterClass
+ public static void tearDownAfterClass() throws Exception {
+ logger.info("tearDownAfterClass()");
+ }
+
+ @Autowired
+ @Qualifier("barSpringDataJpaService")
+ private IBarService barService;
+
+ @Autowired
+ private EntityManagerFactory entityManagerFactory;
+
+ private EntityManager em;
+
+ @Before
+ public void setUp() throws Exception {
+ logger.info("setUp()");
+ em = entityManagerFactory.createEntityManager();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ logger.info("tearDown()");
+ em.close();
+ }
+
+ @Test
+ @WithMockUser(username = "tutorialuser")
+ public final void whenBarsModified_thenBarsAudited() {
+ Bar bar = new Bar("BAR1");
+ barService.create(bar);
+ assertEquals(bar.getCreatedDate(), bar.getModifiedDate());
+ assertEquals("tutorialuser", bar.getCreatedBy(), bar.getModifiedBy());
+ bar.setName("BAR2");
+ bar = barService.update(bar);
+ assertTrue(bar.getCreatedDate() < bar.getModifiedDate());
+ assertEquals("tutorialuser", bar.getCreatedBy(), bar.getModifiedBy());
+ }
+}
diff --git a/spring-hibernate5/src/test/java/com/baeldung/persistence/hibernate/FooFixtures.java b/spring-hibernate5/src/test/java/com/baeldung/persistence/hibernate/FooFixtures.java
new file mode 100644
index 0000000000..da840dc027
--- /dev/null
+++ b/spring-hibernate5/src/test/java/com/baeldung/persistence/hibernate/FooFixtures.java
@@ -0,0 +1,101 @@
+package com.baeldung.persistence.hibernate;
+
+import java.util.List;
+
+import com.baeldung.persistence.model.Foo;
+import com.baeldung.persistence.model.Bar;
+import org.hibernate.HibernateException;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.Transaction;
+
+import com.google.common.collect.Lists;
+
+public class FooFixtures {
+ private SessionFactory sessionFactory;
+
+ public FooFixtures(final SessionFactory sessionFactory) {
+ super();
+
+ this.sessionFactory = sessionFactory;
+ }
+
+ // API
+
+ public void createBars() {
+ Session session = null;
+ Transaction tx = null;
+ session = sessionFactory.openSession();
+ tx = session.getTransaction();
+ try {
+ tx.begin();
+ for (int i = 156; i < 160; i++) {
+ final Bar bar = new Bar();
+ bar.setName("Bar_" + i);
+ final Foo foo = new Foo("Foo_" + (i + 120));
+ foo.setBar(bar);
+ session.save(foo);
+ final Foo foo2 = new Foo(null);
+ if (i % 2 == 0)
+ foo2.setName("LuckyFoo" + (i + 120));
+ foo2.setBar(bar);
+ session.save(foo2);
+ bar.getFooSet().add(foo);
+ bar.getFooSet().add(foo2);
+ session.merge(bar);
+ }
+ tx.commit();
+ session.flush();
+ } catch (final HibernateException he) {
+ if (tx != null)
+ tx.rollback();
+ System.out.println("Not able to open session");
+ he.printStackTrace();
+ } catch (final Exception e) {
+ e.printStackTrace();
+ } finally {
+ if (session != null)
+ session.close();
+ }
+
+ }
+
+ public void createFoos() {
+ Session session = null;
+ Transaction tx = null;
+ session = sessionFactory.openSession();
+ tx = session.getTransaction();
+ final List fooList = Lists.newArrayList();
+ for (int i = 35; i < 46; i++) {
+
+ final Foo foo = new Foo();
+ foo.setName("Foo_" + (i + 120));
+ final Bar bar = new Bar("bar_" + i);
+ bar.getFooSet().add(foo);
+ foo.setBar(bar);
+ fooList.add(foo);
+
+ }
+ try {
+ tx.begin();
+ for (final Foo foo : fooList) {
+
+ session.save(foo.getBar());
+ session.save(foo);
+ }
+ tx.commit();
+ session.flush();
+ } catch (final HibernateException he) {
+ if (tx != null)
+ tx.rollback();
+ System.out.println("Not able to open session");
+ he.printStackTrace();
+ } catch (final Exception e) {
+ e.printStackTrace();
+ } finally {
+ if (session != null)
+ session.close();
+ }
+ }
+
+}
diff --git a/spring-hibernate5/src/test/java/com/baeldung/persistence/hibernate/FooPaginationPersistenceIntegrationTest.java b/spring-hibernate5/src/test/java/com/baeldung/persistence/hibernate/FooPaginationPersistenceIntegrationTest.java
new file mode 100644
index 0000000000..c9152b4d85
--- /dev/null
+++ b/spring-hibernate5/src/test/java/com/baeldung/persistence/hibernate/FooPaginationPersistenceIntegrationTest.java
@@ -0,0 +1,185 @@
+package com.baeldung.persistence.hibernate;
+
+import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
+import static org.hamcrest.Matchers.hasSize;
+import static org.hamcrest.Matchers.lessThan;
+import static org.junit.Assert.assertThat;
+
+import java.util.List;
+
+import javax.persistence.Tuple;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Root;
+
+import org.hibernate.ScrollMode;
+import org.hibernate.ScrollableResults;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.AnnotationConfigContextLoader;
+
+import com.baeldung.persistence.model.Foo;
+import com.baeldung.persistence.service.IFooService;
+import com.baeldung.spring.PersistenceConfig;
+import com.google.common.collect.Lists;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class)
+public class FooPaginationPersistenceIntegrationTest {
+
+ @Autowired
+ private IFooService fooService;
+
+ @Autowired
+ private SessionFactory sessionFactory;
+
+ private Session session;
+
+ // tests
+
+ @Before
+ public final void before() {
+ final int minimalNumberOfEntities = 25;
+ if (fooService.findAll().size() <= minimalNumberOfEntities) {
+ for (int i = 0; i < minimalNumberOfEntities; i++) {
+ fooService.create(new Foo(randomAlphabetic(6)));
+ }
+ }
+
+ session = sessionFactory.openSession();
+ }
+
+ @After
+ public final void after() {
+ session.close();
+ }
+
+ // tests
+
+ @Test
+ public final void whenContextIsBootstrapped_thenNoExceptions() {
+ //
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public final void whenRetrievingPaginatedEntities_thenCorrectSize() {
+ final int pageNumber = 1;
+ final int pageSize = 10;
+ final List fooList = session.createQuery("From Foo").setFirstResult((pageNumber - 1) * pageSize)
+ .setMaxResults(pageSize).getResultList();
+ assertThat(fooList, hasSize(pageSize));
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public final void whenRetrievingAllPages_thenCorrect() {
+ int pageNumber = 1;
+ final int pageSize = 10;
+
+ final String countQ = "Select count (f.id) from Foo f";
+ final Long countResult = (Long) session.createQuery(countQ).uniqueResult();
+
+ final List fooList = Lists.newArrayList();
+ int totalEntities = 0;
+ while (totalEntities < countResult) {
+ fooList.addAll(session.createQuery("From Foo").setFirstResult((pageNumber - 1) * pageSize)
+ .setMaxResults(pageSize).getResultList());
+ totalEntities = fooList.size();
+ pageNumber++;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public final void whenRetrievingLastPage_thenCorrectSize() {
+ final int pageSize = 10;
+
+ final String countQ = "Select count (f.id) from Foo f";
+ final Long countResults = (Long) session.createQuery(countQ).uniqueResult();
+ final int lastPageNumber = (int) ((countResults / pageSize) + 1);
+
+ final List lastPage = session.createQuery("From Foo").setFirstResult((lastPageNumber - 1) * pageSize)
+ .setMaxResults(pageSize).getResultList();
+
+ assertThat(lastPage, hasSize(lessThan(pageSize + 1)));
+ }
+
+ // testing - scrollable
+
+ @Test
+ public final void givenUsingTheScrollableApi_whenRetrievingPaginatedData_thenCorrect() {
+ final int pageSize = 10;
+ final String hql = "FROM Foo f order by f.name";
+
+ final ScrollableResults resultScroll = session.createQuery(hql).scroll(ScrollMode.FORWARD_ONLY);
+
+ // resultScroll.last();
+ // final int totalResults = resultScroll.getRowNumber() + 1;
+
+ resultScroll.first();
+ resultScroll.scroll(0);
+ final List fooPage = Lists.newArrayList();
+ int i = 0;
+ while (pageSize > i++) {
+ fooPage.add((Foo) resultScroll.get(0));
+ if (!resultScroll.next()) {
+ break;
+ }
+ }
+
+ assertThat(fooPage, hasSize(lessThan(10 + 1)));
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public final void givenUsingTheCriteriaApi_whenRetrievingFirstPage_thenCorrect() {
+ final int pageSize = 10;
+
+ CriteriaBuilder builder = session.getCriteriaBuilder();
+ CriteriaQuery criteriaItem = builder.createQuery(Foo.class);
+ Root rootItem = criteriaItem.from(Foo.class);
+ criteriaItem.select(rootItem);
+ final List firstPage = session.createQuery(criteriaItem).setFirstResult(0).setMaxResults(pageSize)
+ .getResultList();
+
+ assertThat(firstPage, hasSize(pageSize));
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public final void givenUsingTheCriteriaApi_whenRetrievingPaginatedData_thenCorrect() {
+
+ CriteriaBuilder builder = session.getCriteriaBuilder();
+ CriteriaQuery criteriaItem = builder.createQuery(Tuple.class);
+ Root rootItem = criteriaItem.from(Foo.class);
+ criteriaItem.multiselect(builder.count(rootItem));
+ final List itemProjected = session.createQuery(criteriaItem).getResultList();
+ final Long count = (Long) itemProjected.get(0).get(0);
+
+ int pageNumber = 1;
+ final int pageSize = 10;
+ final List fooList = Lists.newArrayList();
+
+ CriteriaBuilder builderFoo = session.getCriteriaBuilder();
+ CriteriaQuery criteriaFoo = builderFoo.createQuery(Foo.class);
+ Root rootFoo = criteriaFoo.from(Foo.class);
+ criteriaFoo.select(rootFoo);
+
+ int totalEntities = 0;
+ while (totalEntities < count.intValue()) {
+ fooList.addAll(session.createQuery(criteriaFoo).setFirstResult((pageNumber - 1) * pageSize)
+ .setMaxResults(pageSize).getResultList());
+ totalEntities = fooList.size();
+ pageNumber++;
+ }
+ }
+
+}
diff --git a/spring-hibernate5/src/test/java/com/baeldung/persistence/hibernate/FooSortingPersistenceIntegrationTest.java b/spring-hibernate5/src/test/java/com/baeldung/persistence/hibernate/FooSortingPersistenceIntegrationTest.java
new file mode 100644
index 0000000000..813fb65641
--- /dev/null
+++ b/spring-hibernate5/src/test/java/com/baeldung/persistence/hibernate/FooSortingPersistenceIntegrationTest.java
@@ -0,0 +1,179 @@
+package com.baeldung.persistence.hibernate;
+
+import static org.junit.Assert.assertNull;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Order;
+import javax.persistence.criteria.Root;
+
+import org.hibernate.Criteria;
+import org.hibernate.NullPrecedence;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.AnnotationConfigContextLoader;
+
+import com.baeldung.persistence.model.Bar;
+import com.baeldung.persistence.model.Foo;
+import com.baeldung.spring.PersistenceConfig;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class)
+@SuppressWarnings("unchecked")
+public class FooSortingPersistenceIntegrationTest {
+
+ @Autowired
+ private SessionFactory sessionFactory;
+
+ private Session session;
+
+ @Before
+ public void before() {
+ session = sessionFactory.openSession();
+
+ session.beginTransaction();
+
+ final FooFixtures fooData = new FooFixtures(sessionFactory);
+ fooData.createBars();
+ }
+
+ @After
+ public void after() {
+ session.getTransaction().commit();
+ session.close();
+ }
+
+ @Test
+ public final void whenHQlSortingByOneAttribute_thenPrintSortedResults() {
+ final String hql = "FROM Foo f ORDER BY f.name";
+ final List fooList = session.createQuery(hql).getResultList();
+ for (final Foo foo : fooList) {
+ System.out.println("Name: " + foo.getName() + ", Id: " + foo.getId());
+ }
+ }
+
+ @Test
+ public final void whenHQlSortingByStringNullLast_thenLastNull() {
+ final String hql = "FROM Foo f ORDER BY f.name NULLS LAST";
+ final List fooList = session.createQuery(hql).getResultList();
+
+ assertNull(fooList.get(fooList.toArray().length - 1).getName());
+ for (final Foo foo : fooList) {
+ System.out.println("Name: " + foo.getName() + ", Id: " + foo.getId());
+ }
+ }
+
+ @Test
+ public final void whenSortingByStringNullsFirst_thenReturnNullsFirst() {
+ final String hql = "FROM Foo f ORDER BY f.name NULLS FIRST";
+ final List fooList = session.createQuery(hql).getResultList();
+ assertNull(fooList.get(0).getName());
+ for (final Foo foo : fooList) {
+ System.out.println("Name:" + foo.getName());
+
+ }
+ }
+
+ @Test
+ public final void whenHQlSortingByOneAttribute_andOrderDirection_thenPrintSortedResults() {
+ final String hql = "FROM Foo f ORDER BY f.name ASC";
+ final List fooList = session.createQuery(hql).getResultList();
+ for (final Foo foo : fooList) {
+ System.out.println("Name: " + foo.getName() + ", Id: " + foo.getId());
+ }
+ }
+
+ @Test
+ public final void whenHQlSortingByMultipleAttributes_thenSortedResults() {
+ final String hql = "FROM Foo f ORDER BY f.name, f.id";
+ final List fooList = session.createQuery(hql).getResultList();
+ for (final Foo foo : fooList) {
+ System.out.println("Name: " + foo.getName() + ", Id: " + foo.getId());
+ }
+ }
+
+ @Test
+ public final void whenHQlSortingByMultipleAttributes_andOrderDirection_thenPrintSortedResults() {
+ final String hql = "FROM Foo f ORDER BY f.name DESC, f.id ASC";
+ final List fooList = session.createQuery(hql).getResultList();
+ for (final Foo foo : fooList) {
+ System.out.println("Name: " + foo.getName() + ", Id: " + foo.getId());
+ }
+ }
+
+ @Test
+ public final void whenHQLCriteriaSortingByOneAttr_thenPrintSortedResults() {
+ List listOrders = new ArrayList();
+ CriteriaBuilder builder = session.getCriteriaBuilder();
+ CriteriaQuery criteriaItem = builder.createQuery(Foo.class);
+ Root rootItem = criteriaItem.from(Foo.class);
+ listOrders.add(builder.asc(rootItem.get("id")));
+ criteriaItem.orderBy(listOrders.toArray(new Order[] {}));
+ final List fooList = session.createQuery(criteriaItem).getResultList();
+ for (final Foo foo : fooList) {
+ System.out.println("Id: " + foo.getId() + ", FirstName: " + foo.getName());
+ }
+ }
+
+ @Test
+ public final void whenHQLCriteriaSortingByMultipAttr_thenSortedResults() {
+ List listOrders = new ArrayList();
+ CriteriaBuilder builder = session.getCriteriaBuilder();
+ CriteriaQuery criteriaItem = builder.createQuery(Foo.class);
+ Root rootItem = criteriaItem.from(Foo.class);
+ listOrders.add(builder.asc(rootItem.get("name")));
+ listOrders.add(builder.asc(rootItem.get("id")));
+ criteriaItem.orderBy(listOrders.toArray(new Order[] {}));
+ final List fooList = session.createQuery(criteriaItem).getResultList();
+ for (final Foo foo : fooList) {
+ System.out.println("Id: " + foo.getId() + ", FirstName: " + foo.getName());
+ }
+ }
+
+ /*@Test
+ public final void whenCriteriaSortingStringNullsLastAsc_thenNullsLast() {
+ final Criteria criteria = session.createCriteria(Foo.class, "FOO");
+ criteria.addOrder(Order.asc("name").nulls(NullPrecedence.LAST));
+ final List fooList = criteria.list();
+ assertNull(fooList.get(fooList.toArray().length - 1).getName());
+ for (final Foo foo : fooList) {
+ System.out.println("Id: " + foo.getId() + ", FirstName: " + foo.getName());
+ }
+ }
+
+ @Test
+ public final void whenCriteriaSortingStringNullsFirstDesc_thenNullsFirst() {
+ final Criteria criteria = session.createCriteria(Foo.class, "FOO");
+ criteria.addOrder(Order.desc("name").nulls(NullPrecedence.FIRST));
+ final List fooList = criteria.list();
+ assertNull(fooList.get(0).getName());
+ for (final Foo foo : fooList) {
+ System.out.println("Id: " + foo.getId() + ", FirstName: " + foo.getName());
+ }
+ }*/
+
+ @Test
+ public final void whenSortingBars_thenBarsWithSortedFoos() {
+ final String hql = "FROM Bar b ORDER BY b.id";
+ final List barList = session.createQuery(hql).getResultList();
+ for (final Bar bar : barList) {
+ final Set fooSet = bar.getFooSet();
+ System.out.println("Bar Id:" + bar.getId());
+ for (final Foo foo : fooSet) {
+ System.out.println("FooName:" + foo.getName());
+ }
+ }
+ }
+
+}
diff --git a/spring-hibernate5/src/test/java/com/baeldung/persistence/save/SaveMethodsTest.java b/spring-hibernate5/src/test/java/com/baeldung/persistence/save/SaveMethodsTest.java
new file mode 100644
index 0000000000..b6cde868d3
--- /dev/null
+++ b/spring-hibernate5/src/test/java/com/baeldung/persistence/save/SaveMethodsTest.java
@@ -0,0 +1,285 @@
+package com.baeldung.persistence.save;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+
+import javax.persistence.PersistenceException;
+
+import org.hibernate.HibernateException;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.TransactionException;
+import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.dialect.HSQLDialect;
+import org.hibernate.service.ServiceRegistry;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.baeldung.persistence.model.Person;
+
+/**
+ * Testing specific implementation details for different methods: persist, save,
+ * merge, update, saveOrUpdate.
+ */
+public class SaveMethodsTest {
+
+ private static SessionFactory sessionFactory;
+
+ private Session session;
+
+ @BeforeClass
+ public static void beforeTests() {
+ Configuration configuration = new Configuration().addAnnotatedClass(Person.class)
+ .setProperty("hibernate.dialect", HSQLDialect.class.getName())
+ .setProperty("hibernate.connection.driver_class", org.hsqldb.jdbcDriver.class.getName())
+ .setProperty("hibernate.connection.url", "jdbc:hsqldb:mem:test")
+ .setProperty("hibernate.connection.username", "sa").setProperty("hibernate.connection.password", "")
+ .setProperty("hibernate.hbm2ddl.auto", "update");
+ ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(
+ configuration.getProperties()).build();
+ sessionFactory = configuration.buildSessionFactory(serviceRegistry);
+ }
+
+ @Before
+ public void setUp() {
+ session = sessionFactory.openSession();
+ session.beginTransaction();
+ }
+
+ @Test
+ public void whenPersistTransient_thenSavedToDatabaseOnCommit() {
+
+ Person person = new Person();
+ person.setName("John");
+ session.persist(person);
+
+ session.getTransaction().commit();
+ session.close();
+
+ session = sessionFactory.openSession();
+ session.beginTransaction();
+
+ assertNotNull(session.get(Person.class, person.getId()));
+
+ }
+
+ @Test
+ public void whenPersistPersistent_thenNothingHappens() {
+
+ Person person = new Person();
+ person.setName("John");
+
+ session.persist(person);
+ Long id1 = person.getId();
+
+ session.persist(person);
+ Long id2 = person.getId();
+
+ assertEquals(id1, id2);
+ }
+
+ @Test(expected = PersistenceException.class)
+ public void whenPersistDetached_thenThrowsException() {
+
+ Person person = new Person();
+ person.setName("John");
+ session.persist(person);
+ session.evict(person);
+
+ session.persist(person);
+
+ }
+
+ @Test
+ public void whenSaveTransient_thenIdGeneratedImmediately() {
+
+ Person person = new Person();
+ person.setName("John");
+
+ assertNull(person.getId());
+
+ Long id = (Long) session.save(person);
+
+ assertNotNull(id);
+
+ session.getTransaction().commit();
+ session.close();
+
+ assertEquals(id, person.getId());
+
+ session = sessionFactory.openSession();
+ session.beginTransaction();
+
+ assertNotNull(session.get(Person.class, person.getId()));
+
+ }
+
+ @Test
+ public void whenSavePersistent_thenNothingHappens() {
+
+ Person person = new Person();
+ person.setName("John");
+ Long id1 = (Long) session.save(person);
+ Long id2 = (Long) session.save(person);
+ assertEquals(id1, id2);
+
+ }
+
+ @Test
+ public void whenSaveDetached_thenNewInstancePersisted() {
+
+ Person person = new Person();
+ person.setName("John");
+ Long id1 = (Long) session.save(person);
+ session.evict(person);
+
+ Long id2 = (Long) session.save(person);
+ assertNotEquals(id1, id2);
+
+ }
+
+ @Test
+ public void whenMergeDetached_thenEntityUpdatedFromDatabase() {
+
+ Person person = new Person();
+ person.setName("John");
+ session.save(person);
+ session.flush();
+ session.evict(person);
+
+ person.setName("Mary");
+ Person mergedPerson = (Person) session.merge(person);
+
+ assertNotSame(person, mergedPerson);
+ assertEquals("Mary", mergedPerson.getName());
+
+ }
+
+ @Test
+ public void whenMergeTransient_thenNewEntitySavedToDatabase() {
+
+ Person person = new Person();
+ person.setName("John");
+ Person mergedPerson = (Person) session.merge(person);
+
+ session.getTransaction().commit();
+ session.beginTransaction();
+
+ assertNull(person.getId());
+ assertNotNull(mergedPerson.getId());
+
+ }
+
+ @Test
+ public void whenMergePersistent_thenReturnsSameObject() {
+
+ Person person = new Person();
+ person.setName("John");
+ session.save(person);
+
+ Person mergedPerson = (Person) session.merge(person);
+
+ assertSame(person, mergedPerson);
+
+ }
+
+ @Test
+ public void whenUpdateDetached_thenEntityUpdatedFromDatabase() {
+
+ Person person = new Person();
+ person.setName("John");
+ session.save(person);
+ session.evict(person);
+
+ person.setName("Mary");
+ session.update(person);
+ assertEquals("Mary", person.getName());
+
+ }
+
+ @Test(expected = HibernateException.class)
+ public void whenUpdateTransient_thenThrowsException() {
+
+ Person person = new Person();
+ person.setName("John");
+ session.update(person);
+
+ }
+
+ @Test
+ public void whenUpdatePersistent_thenNothingHappens() {
+
+ Person person = new Person();
+ person.setName("John");
+ session.save(person);
+
+ session.update(person);
+
+ }
+
+ @Test
+ public void whenSaveOrUpdateDetached_thenEntityUpdatedFromDatabase() {
+
+ Person person = new Person();
+ person.setName("John");
+ session.save(person);
+ session.evict(person);
+
+ person.setName("Mary");
+ session.saveOrUpdate(person);
+ assertEquals("Mary", person.getName());
+
+ }
+
+ @Test
+ public void whenSaveOrUpdateTransient_thenSavedToDatabaseOnCommit() {
+
+ Person person = new Person();
+ person.setName("John");
+ session.saveOrUpdate(person);
+
+ session.getTransaction().commit();
+ session.close();
+
+ session = sessionFactory.openSession();
+ session.beginTransaction();
+
+ assertNotNull(session.get(Person.class, person.getId()));
+
+ }
+
+ @Test
+ public void whenSaveOrUpdatePersistent_thenNothingHappens() {
+
+ Person person = new Person();
+ person.setName("John");
+ session.save(person);
+
+ session.saveOrUpdate(person);
+
+ }
+
+ @After
+ public void tearDown() {
+ try{
+ session.getTransaction().commit();
+ session.close();
+ }catch(TransactionException ex){
+ ex.printStackTrace();
+ }
+ }
+
+ @AfterClass
+ public static void afterTests() {
+ sessionFactory.close();
+ }
+
+}
diff --git a/spring-hibernate5/src/test/java/com/baeldung/persistence/service/FooServiceBasicPersistenceIntegrationTest.java b/spring-hibernate5/src/test/java/com/baeldung/persistence/service/FooServiceBasicPersistenceIntegrationTest.java
new file mode 100644
index 0000000000..c77f5dfb95
--- /dev/null
+++ b/spring-hibernate5/src/test/java/com/baeldung/persistence/service/FooServiceBasicPersistenceIntegrationTest.java
@@ -0,0 +1,54 @@
+package com.baeldung.persistence.service;
+
+import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
+
+import com.baeldung.persistence.model.Foo;
+import com.baeldung.spring.PersistenceConfig;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.AnnotationConfigContextLoader;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class)
+public class FooServiceBasicPersistenceIntegrationTest {
+
+ @Autowired
+ private SessionFactory sessionFactory;
+
+ @Autowired
+ private IFooService fooService;
+
+ private Session session;
+
+ // tests
+
+ @Before
+ public final void before() {
+ session = sessionFactory.openSession();
+ }
+
+ @After
+ public final void after() {
+ session.close();
+ }
+
+ // tests
+
+ @Test
+ public final void whenContextIsBootstrapped_thenNoExceptions() {
+ //
+ }
+
+ @Test
+ public final void whenEntityIsCreated_thenNoExceptions() {
+ fooService.create(new Foo(randomAlphabetic(6)));
+ }
+
+}
diff --git a/spring-hibernate5/src/test/java/com/baeldung/persistence/service/FooServicePersistenceIntegrationTest.java b/spring-hibernate5/src/test/java/com/baeldung/persistence/service/FooServicePersistenceIntegrationTest.java
new file mode 100644
index 0000000000..b82d4621ab
--- /dev/null
+++ b/spring-hibernate5/src/test/java/com/baeldung/persistence/service/FooServicePersistenceIntegrationTest.java
@@ -0,0 +1,63 @@
+package com.baeldung.persistence.service;
+
+import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
+
+import com.baeldung.persistence.model.Foo;
+import com.baeldung.spring.PersistenceConfig;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.dao.DataAccessException;
+import org.springframework.dao.DataIntegrityViolationException;
+import org.springframework.dao.InvalidDataAccessApiUsageException;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.AnnotationConfigContextLoader;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class)
+public class FooServicePersistenceIntegrationTest {
+
+ @Autowired
+ @Qualifier("fooHibernateService")
+ private IFooService service;
+
+ // tests
+
+ @Test
+ public final void whenContextIsBootstrapped_thenNoExceptions() {
+ //
+ }
+
+ @Test
+ public final void whenEntityIsCreated_thenNoExceptions() {
+ service.create(new Foo(randomAlphabetic(6)));
+ }
+
+ @Test(expected = DataIntegrityViolationException.class)
+ @Ignore("work in progress")
+ public final void whenInvalidEntityIsCreated_thenDataException() {
+ service.create(new Foo());
+ }
+
+ @Test(expected = DataIntegrityViolationException.class)
+ public final void whenEntityWithLongNameIsCreated_thenDataException() {
+ service.create(new Foo(randomAlphabetic(2048)));
+ }
+
+ @Test(expected = InvalidDataAccessApiUsageException.class)
+ @Ignore("Right now, persist has saveOrUpdate semantics, so this will no longer fail")
+ public final void whenSameEntityIsCreatedTwice_thenDataException() {
+ final Foo entity = new Foo(randomAlphabetic(8));
+ service.create(entity);
+ service.create(entity);
+ }
+
+ @Test(expected = DataAccessException.class)
+ public final void temp_whenInvalidEntityIsCreated_thenDataException() {
+ service.create(new Foo(randomAlphabetic(2048)));
+ }
+
+}
diff --git a/spring-hibernate5/src/test/java/com/baeldung/persistence/service/FooStoredProceduresIntegrationTest.java b/spring-hibernate5/src/test/java/com/baeldung/persistence/service/FooStoredProceduresIntegrationTest.java
new file mode 100644
index 0000000000..cfd3844079
--- /dev/null
+++ b/spring-hibernate5/src/test/java/com/baeldung/persistence/service/FooStoredProceduresIntegrationTest.java
@@ -0,0 +1,114 @@
+package com.baeldung.persistence.service;
+
+import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
+import static org.junit.Assert.assertEquals;
+
+import java.util.List;
+
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.exception.SQLGrammarException;
+import org.junit.After;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.AnnotationConfigContextLoader;
+
+import com.baeldung.persistence.model.Foo;
+import com.baeldung.spring.PersistenceConfig;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class)
+public class FooStoredProceduresIntegrationTest {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(FooStoredProceduresIntegrationTest.class);
+
+ @Autowired
+ private SessionFactory sessionFactory;
+
+ @Autowired
+ private IFooService fooService;
+
+ private Session session;
+
+ @Before
+ public final void before() {
+ session = sessionFactory.openSession();
+ Assume.assumeTrue(getAllFoosExists());
+ Assume.assumeTrue(getFoosByNameExists());
+ }
+
+ private boolean getFoosByNameExists() {
+ try {
+ session.createQuery("CALL GetAllFoos()", Foo.class).getResultList();
+ return true;
+ } catch (SQLGrammarException e) {
+ LOGGER.error("WARNING : GetFoosByName() Procedure is may be missing ", e);
+ return false;
+ }
+ }
+
+ private boolean getAllFoosExists() {
+ try {
+ session.createQuery("CALL GetAllFoos()", Foo.class).getResultList();
+ return true;
+ } catch (SQLGrammarException e) {
+ LOGGER.error("WARNING : GetAllFoos() Procedure is may be missing ", e);
+ return false;
+ }
+ }
+
+ @After
+ public final void after() {
+ session.close();
+ }
+
+ @Test
+ public final void getAllFoosUsingStoredProcedures() {
+
+ fooService.create(new Foo(randomAlphabetic(6)));
+
+ // Stored procedure getAllFoos using createSQLQuery
+ List allFoos = session.createQuery("CALL GetAllFoos()", Foo.class).getResultList();
+ for (Foo foo : allFoos) {
+ LOGGER.info("getAllFoos() SQL Query result : {}", foo.getName());
+ }
+ assertEquals(allFoos.size(), fooService.findAll().size());
+
+ // Stored procedure getAllFoos using a Named Query
+ @SuppressWarnings("unchecked")
+ List allFoos2 = session.getNamedQuery("callGetAllFoos").getResultList();
+ for (Foo foo : allFoos2) {
+ LOGGER.info("getAllFoos() NamedQuery result : {}", foo.getName());
+ }
+ assertEquals(allFoos2.size(), fooService.findAll().size());
+ }
+
+ @Test
+ public final void getFoosByNameUsingStoredProcedures() {
+
+ fooService.create(new Foo("NewFooName"));
+
+ // Stored procedure getFoosByName using createSQLQuery()
+ List allFoosByName = session.createQuery("CALL GetFoosByName(:fooName)", Foo.class)
+ .setParameter("fooName", "NewFooName").getResultList();
+ for (Foo foo : allFoosByName) {
+ LOGGER.info("getFoosByName() using SQL Query : found => {}", foo.toString());
+ }
+
+ // Stored procedure getFoosByName using getNamedQuery()
+ @SuppressWarnings("unchecked")
+ List allFoosByName2 = session.getNamedQuery("callGetFoosByName").setParameter("fooName", "NewFooName")
+ .getResultList();
+ for (Foo foo : allFoosByName2) {
+ LOGGER.info("getFoosByName() using Native Query : found => {}", foo.toString());
+ }
+
+ }
+}
diff --git a/spring-hibernate5/src/test/java/com/baeldung/persistence/service/ParentServicePersistenceIntegrationTest.java b/spring-hibernate5/src/test/java/com/baeldung/persistence/service/ParentServicePersistenceIntegrationTest.java
new file mode 100644
index 0000000000..9e8c4aba92
--- /dev/null
+++ b/spring-hibernate5/src/test/java/com/baeldung/persistence/service/ParentServicePersistenceIntegrationTest.java
@@ -0,0 +1,69 @@
+package com.baeldung.persistence.service;
+
+import com.baeldung.persistence.model.Child;
+import com.baeldung.persistence.model.Parent;
+import com.baeldung.spring.PersistenceConfig;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.dao.DataIntegrityViolationException;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.AnnotationConfigContextLoader;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class)
+public class ParentServicePersistenceIntegrationTest {
+
+ @Autowired
+ private IParentService service;
+
+ @Autowired
+ private IChildService childService;
+
+ // tests
+
+ @Test
+ public final void whenContextIsBootstrapped_thenNoExceptions() {
+ //
+ }
+
+ @Test
+ public final void whenOneToOneEntitiesAreCreated_thenNoExceptions() {
+ final Child childEntity = new Child();
+ childService.create(childEntity);
+
+ final Parent parentEntity = new Parent(childEntity);
+ service.create(parentEntity);
+
+ System.out.println("Child = " + childService.findOne(childEntity.getId()));
+ System.out.println("Child - parent = " + childService.findOne(childEntity.getId()).getParent());
+
+ System.out.println("Parent = " + service.findOne(parentEntity.getId()));
+ System.out.println("Parent - child = " + service.findOne(parentEntity.getId()).getChild());
+ }
+
+ @Test(expected = DataIntegrityViolationException.class)
+ public final void whenChildIsDeletedWhileParentStillHasForeignKeyToIt_thenDataException() {
+ final Child childEntity = new Child();
+ childService.create(childEntity);
+
+ final Parent parentEntity = new Parent(childEntity);
+ service.create(parentEntity);
+
+ childService.delete(childEntity);
+ }
+
+ @Test
+ public final void whenChildIsDeletedAfterTheParent_thenNoExceptions() {
+ final Child childEntity = new Child();
+ childService.create(childEntity);
+
+ final Parent parentEntity = new Parent(childEntity);
+ service.create(parentEntity);
+
+ service.delete(parentEntity);
+ childService.delete(childEntity);
+ }
+
+}
diff --git a/spring-hibernate5/src/test/resources/.gitignore b/spring-hibernate5/src/test/resources/.gitignore
new file mode 100644
index 0000000000..83c05e60c8
--- /dev/null
+++ b/spring-hibernate5/src/test/resources/.gitignore
@@ -0,0 +1,13 @@
+*.class
+
+#folders#
+/target
+/neoDb*
+/data
+/src/main/webapp/WEB-INF/classes
+*/META-INF/*
+
+# Packaged files #
+*.jar
+*.war
+*.ear
\ No newline at end of file
diff --git a/spring-hibernate5/src/test/resources/com/baeldung/hibernate/criteria/model/Item.hbm.xml b/spring-hibernate5/src/test/resources/com/baeldung/hibernate/criteria/model/Item.hbm.xml
new file mode 100644
index 0000000000..9e0109aae2
--- /dev/null
+++ b/spring-hibernate5/src/test/resources/com/baeldung/hibernate/criteria/model/Item.hbm.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-hibernate5/src/test/resources/criteria.cfg.xml b/spring-hibernate5/src/test/resources/criteria.cfg.xml
new file mode 100644
index 0000000000..5bc3a32077
--- /dev/null
+++ b/spring-hibernate5/src/test/resources/criteria.cfg.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+ com.mysql.jdbc.Driver
+ jdbc:mysql://localhost:3306/test
+ root
+ root
+ org.hibernate.dialect.MySQLDialect
+ true
+
+
+
\ No newline at end of file
diff --git a/spring-hibernate5/src/test/resources/fetching.cfg.xml b/spring-hibernate5/src/test/resources/fetching.cfg.xml
new file mode 100644
index 0000000000..c47b062a2f
--- /dev/null
+++ b/spring-hibernate5/src/test/resources/fetching.cfg.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+ com.mysql.jdbc.Driver
+ jdbc:mysql://localhost:3306/test
+ root
+ root
+ org.hibernate.dialect.MySQLDialect
+ true
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-hibernate5/src/test/resources/fetchingLazy.cfg.xml b/spring-hibernate5/src/test/resources/fetchingLazy.cfg.xml
new file mode 100644
index 0000000000..2e252e9307
--- /dev/null
+++ b/spring-hibernate5/src/test/resources/fetchingLazy.cfg.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+ com.mysql.jdbc.Driver
+ jdbc:mysql://localhost:3306/test
+ root
+ root
+ org.hibernate.dialect.MySQLDialect
+ true
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-jersey/README.md b/spring-jersey/README.md
index 2767ceb9a7..8b2eecc0e1 100644
--- a/spring-jersey/README.md
+++ b/spring-jersey/README.md
@@ -1,3 +1,5 @@
=========
## REST API with Jersey & Spring Example Project
+- [REST API with Jersey and Spring](http://www.baeldung.com/jersey-rest-api-with-spring)
+- [JAX-RS Client with Jersey](http://www.baeldung.com/jersey-jax-rs-client)
diff --git a/spring-mobile/README.md b/spring-mobile/README.md
new file mode 100644
index 0000000000..e3d23bcda6
--- /dev/null
+++ b/spring-mobile/README.md
@@ -0,0 +1,4 @@
+## Relevant articles:
+
+- [A Guide to Spring Mobile](http://www.baeldung.com/spring-mobile)
+
diff --git a/spring-mvc-email/README.md b/spring-mvc-email/README.md
index 0de6532393..aa880188d7 100644
--- a/spring-mvc-email/README.md
+++ b/spring-mvc-email/README.md
@@ -1,3 +1,7 @@
+## Relevant articles:
+
+- [Guide to Spring Email](http://www.baeldung.com/spring-email)
+
## Spring MVC Email
Example Spring MVC project to send email from web form.
@@ -10,4 +14,4 @@ Type http://localhost:8080 in your browser to open the application.
### Sending test emails
-Follow UI links to send simple email, email using template or email with attachment.
\ No newline at end of file
+Follow UI links to send simple email, email using template or email with attachment.
diff --git a/spring-mvc-java/README.md b/spring-mvc-java/README.md
index 0f267c5ec9..4d3e58558b 100644
--- a/spring-mvc-java/README.md
+++ b/spring-mvc-java/README.md
@@ -18,3 +18,6 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
- [Spring MVC Content Negotiation](http://www.baeldung.com/spring-mvc-content-negotiation-json-xml)
- [Circular Dependencies in Spring](http://www.baeldung.com/circular-dependencies-in-spring)
- [Introduction to HtmlUnit](http://www.baeldung.com/htmlunit)
+- [Spring @RequestMapping New Shortcut Annotations](http://www.baeldung.com/spring-new-requestmapping-shortcuts)
+- [Guide to Spring Handler Mappings](http://www.baeldung.com/spring-handler-mappings)
+- [Uploading and Displaying Excel Files with Spring MVC](http://www.baeldung.com/spring-mvc-excel-files)
diff --git a/spring-mvc-java/persons.xls b/spring-mvc-java/persons.xls
new file mode 100644
index 0000000000..ea270f69cc
Binary files /dev/null and b/spring-mvc-java/persons.xls differ
diff --git a/spring-mvc-java/persons.xlsx b/spring-mvc-java/persons.xlsx
new file mode 100644
index 0000000000..1f58606532
Binary files /dev/null and b/spring-mvc-java/persons.xlsx differ
diff --git a/spring-mvc-java/pom.xml b/spring-mvc-java/pom.xml
index 9513c81064..ef18cef3e0 100644
--- a/spring-mvc-java/pom.xml
+++ b/spring-mvc-java/pom.xml
@@ -161,26 +161,11 @@
-
- org.apache.poi
- poi
- ${poi.version}
-
org.apache.poi
poi-ooxml
${poi.version}
-
- org.apache.poi
- poi-ooxml-schemas
- ${poi.version}
-
-
- org.jxls
- jxls-jexcel
- ${jexcel.version}
-
@@ -395,7 +380,6 @@
3.16-beta1
- 1.0.6
diff --git a/spring-mvc-java/src/main/java/com/baeldung/excel/ExcelPOIHelper.java b/spring-mvc-java/src/main/java/com/baeldung/excel/ExcelPOIHelper.java
index 5cf74aff63..0519a8f3c7 100644
--- a/spring-mvc-java/src/main/java/com/baeldung/excel/ExcelPOIHelper.java
+++ b/spring-mvc-java/src/main/java/com/baeldung/excel/ExcelPOIHelper.java
@@ -1,140 +1,185 @@
package com.baeldung.excel;
import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CellType;
-import org.apache.poi.ss.usermodel.CellStyle;
-import org.apache.poi.ss.usermodel.IndexedColors;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.apache.poi.xssf.usermodel.XSSFCell;
+import org.apache.poi.xssf.usermodel.XSSFCellStyle;
+import org.apache.poi.xssf.usermodel.XSSFColor;
import org.apache.poi.xssf.usermodel.XSSFFont;
+import org.apache.poi.xssf.usermodel.XSSFRow;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.hssf.usermodel.HSSFCellStyle;
+import org.apache.poi.hssf.usermodel.HSSFFont;
+import org.apache.poi.hssf.usermodel.HSSFRow;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.DateUtil;
-import org.apache.poi.ss.usermodel.FillPatternType;
+
import java.io.File;
-import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
-import java.io.InputStream;
import java.util.Map;
import java.util.HashMap;
import java.util.ArrayList;
-import org.springframework.stereotype.Service;
+import java.util.List;
+import java.util.stream.IntStream;
-@Service
public class ExcelPOIHelper {
- public Map> readExcel(String fileLocation) throws IOException {
+ public Map> readExcel(String fileLocation) throws IOException {
- Map> data = new HashMap>();
- FileInputStream file = new FileInputStream(new File(fileLocation));
- Workbook workbook = new XSSFWorkbook(file);
- Sheet sheet = workbook.getSheetAt(0);
- int i = 0;
- for (Row row : sheet) {
- data.put(i, new ArrayList());
- for (Cell cell : row) {
- switch (cell.getCellTypeEnum()) {
- case STRING:
- data.get(i)
- .add(cell.getRichStringCellValue()
- .getString());
- break;
- case NUMERIC:
- if (DateUtil.isCellDateFormatted(cell)) {
- data.get(i)
- .add(cell.getDateCellValue() + "");
- } else {
- data.get(i)
- .add(cell.getNumericCellValue() + "");
+ Map> data = new HashMap<>();
+ FileInputStream fis = new FileInputStream(new File(fileLocation));
+
+ if (fileLocation.endsWith(".xls")) {
+ data = readHSSFWorkbook(fis);
+ } else if (fileLocation.endsWith(".xlsx")) {
+ data = readXSSFWorkbook(fis);
+ }
+
+ int maxNrCols = data.values().stream()
+ .mapToInt(List::size)
+ .max()
+ .orElse(0);
+
+ data.values().stream()
+ .filter(ls -> ls.size() < maxNrCols)
+ .forEach(ls -> {
+ IntStream.range(ls.size(), maxNrCols)
+ .forEach(i -> ls.add(new MyCell("")));
+ });
+
+ return data;
+ }
+
+ private String readCellContent(Cell cell) {
+ String content;
+ switch (cell.getCellTypeEnum()) {
+ case STRING:
+ content = cell.getStringCellValue();
+ break;
+ case NUMERIC:
+ if (DateUtil.isCellDateFormatted(cell)) {
+ content = cell.getDateCellValue() + "";
+ } else {
+ content = cell.getNumericCellValue() + "";
+ }
+ break;
+ case BOOLEAN:
+ content = cell.getBooleanCellValue() + "";
+ break;
+ case FORMULA:
+ content = cell.getCellFormula() + "";
+ break;
+ default:
+ content = "";
+ }
+ return content;
+ }
+
+ private Map> readHSSFWorkbook(FileInputStream fis) throws IOException {
+ Map> data = new HashMap<>();
+ HSSFWorkbook workbook = null;
+ try {
+ workbook = new HSSFWorkbook(fis);
+
+ HSSFSheet sheet = workbook.getSheetAt(0);
+ for (int i = sheet.getFirstRowNum(); i <= sheet.getLastRowNum(); i++) {
+ HSSFRow row = sheet.getRow(i);
+ data.put(i, new ArrayList<>());
+ if (row != null) {
+ for (int j = 0; j < row.getLastCellNum(); j++) {
+ HSSFCell cell = row.getCell(j);
+ if (cell != null) {
+ HSSFCellStyle cellStyle = cell.getCellStyle();
+
+ MyCell myCell = new MyCell();
+
+ HSSFColor bgColor = cellStyle.getFillForegroundColorColor();
+ if (bgColor != null) {
+ short[] rgbColor = bgColor.getTriplet();
+ myCell.setBgColor("rgb(" + rgbColor[0] + "," + rgbColor[1] + "," + rgbColor[2] + ")");
+ }
+ HSSFFont font = cell.getCellStyle()
+ .getFont(workbook);
+ myCell.setTextSize(font.getFontHeightInPoints() + "");
+ if (font.getBold()) {
+ myCell.setTextWeight("bold");
+ }
+ HSSFColor textColor = font.getHSSFColor(workbook);
+ if (textColor != null) {
+ short[] rgbColor = textColor.getTriplet();
+ myCell.setTextColor("rgb(" + rgbColor[0] + "," + rgbColor[1] + "," + rgbColor[2] + ")");
+ }
+ myCell.setContent(readCellContent(cell));
+ data.get(i)
+ .add(myCell);
+ } else {
+ data.get(i)
+ .add(new MyCell(""));
+ }
}
- break;
- case BOOLEAN:
- data.get(i)
- .add(cell.getBooleanCellValue() + "");
- break;
- case FORMULA:
- data.get(i)
- .add(cell.getCellFormula() + "");
- break;
- default:
- data.get(i)
- .add(" ");
}
}
- i++;
- }
- if (workbook != null){
- workbook.close();
+ } finally {
+ if (workbook != null) {
+ workbook.close();
+ }
}
return data;
}
- public void writeExcel() throws IOException {
- Workbook workbook = new XSSFWorkbook();
-
+ private Map> readXSSFWorkbook(FileInputStream fis) throws IOException {
+ XSSFWorkbook workbook = null;
+ Map> data = new HashMap<>();
try {
- Sheet sheet = workbook.createSheet("Persons");
- sheet.setColumnWidth(0, 6000);
- sheet.setColumnWidth(1, 4000);
- Row header = sheet.createRow(0);
+ workbook = new XSSFWorkbook(fis);
+ XSSFSheet sheet = workbook.getSheetAt(0);
- CellStyle headerStyle = workbook.createCellStyle();
+ for (int i = sheet.getFirstRowNum(); i <= sheet.getLastRowNum(); i++) {
+ XSSFRow row = sheet.getRow(i);
+ data.put(i, new ArrayList<>());
+ if (row != null) {
+ for (int j = 0; j < row.getLastCellNum(); j++) {
+ XSSFCell cell = row.getCell(j);
+ if (cell != null) {
+ XSSFCellStyle cellStyle = cell.getCellStyle();
- headerStyle.setFillForegroundColor(IndexedColors.LIGHT_BLUE.getIndex());
- headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
-
- XSSFFont font = ((XSSFWorkbook) workbook).createFont();
- font.setFontName("Arial");
- font.setFontHeightInPoints((short) 16);
- font.setBold(true);
- headerStyle.setFont(font);
-
- Cell headerCell = header.createCell(0);
- headerCell.setCellValue("Name");
- headerCell.setCellStyle(headerStyle);
-
- headerCell = header.createCell(1);
- headerCell.setCellValue("Age");
- headerCell.setCellStyle(headerStyle);
-
- CellStyle style = workbook.createCellStyle();
- style.setWrapText(true);
-
- Row row = sheet.createRow(2);
- Cell cell = row.createCell(0);
- cell.setCellValue("John Smith");
- cell.setCellStyle(style);
-
- cell = row.createCell(1);
- cell.setCellValue(20);
- cell.setCellStyle(style);
-
- row = sheet.createRow(3);
- cell = row.createCell(0);
- cell.setCellValue("Ana Johnson");
- cell.setCellStyle(style);
-
- cell = row.createCell(1);
- cell.setCellValue(30);
- cell.setCellStyle(style);
-
- File currDir = new File(".");
- String path = currDir.getAbsolutePath();
- String fileLocation = path.substring(0, path.length() - 1) + "temp.xlsx";
-
- FileOutputStream outputStream = new FileOutputStream(fileLocation);
- workbook.write(outputStream);
- } finally {
- if (workbook != null) {
- try {
- workbook.close();
- } catch (IOException e) {
- e.printStackTrace();
+ MyCell myCell = new MyCell();
+ XSSFColor bgColor = cellStyle.getFillForegroundColorColor();
+ if (bgColor != null) {
+ byte[] rgbColor = bgColor.getRGB();
+ myCell.setBgColor("rgb(" + (rgbColor[0] < 0 ? (rgbColor[0] + 0xff) : rgbColor[0]) + "," + (rgbColor[1] < 0 ? (rgbColor[1] + 0xff) : rgbColor[1]) + "," + (rgbColor[2] < 0 ? (rgbColor[2] + 0xff) : rgbColor[2]) + ")");
+ }
+ XSSFFont font = cellStyle.getFont();
+ myCell.setTextSize(font.getFontHeightInPoints() + "");
+ if (font.getBold()) {
+ myCell.setTextWeight("bold");
+ }
+ XSSFColor textColor = font.getXSSFColor();
+ if (textColor != null) {
+ byte[] rgbColor = textColor.getRGB();
+ myCell.setTextColor("rgb(" + (rgbColor[0] < 0 ? (rgbColor[0] + 0xff) : rgbColor[0]) + "," + (rgbColor[1] < 0 ? (rgbColor[1] + 0xff) : rgbColor[1]) + "," + (rgbColor[2] < 0 ? (rgbColor[2] + 0xff) : rgbColor[2]) + ")");
+ }
+ myCell.setContent(readCellContent(cell));
+ data.get(i)
+ .add(myCell);
+ } else {
+ data.get(i)
+ .add(new MyCell(""));
+ }
+ }
}
}
+ } finally {
+ if (workbook != null) {
+ workbook.close();
+ }
}
+ return data;
}
}
\ No newline at end of file
diff --git a/spring-mvc-java/src/main/java/com/baeldung/excel/JExcelHelper.java b/spring-mvc-java/src/main/java/com/baeldung/excel/JExcelHelper.java
deleted file mode 100644
index d0e33bf471..0000000000
--- a/spring-mvc-java/src/main/java/com/baeldung/excel/JExcelHelper.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package com.baeldung.excel;
-
-import jxl.Sheet;
-import jxl.Workbook;
-import jxl.format.Colour;
-import jxl.read.biff.BiffException;
-import jxl.write.*;
-import jxl.write.Number;
-import org.springframework.stereotype.Service;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Map;
-
-@Service
-public class JExcelHelper {
-
- public Map> readJExcel(String fileLocation) throws IOException, BiffException {
- Map> data = new HashMap<>();
-
- Workbook workbook = Workbook.getWorkbook(new File(fileLocation));
- Sheet sheet = workbook.getSheet(0);
- int rows = sheet.getRows();
- int columns = sheet.getColumns();
-
- for (int i = 0; i < rows; i++) {
- data.put(i, new ArrayList<>());
- for (int j = 0; j < columns; j++) {
- data.get(i).add(sheet.getCell(j, i).getContents());
- }
- }
- return data;
- }
-
- public void writeJExcel() throws IOException, WriteException {
- WritableWorkbook workbook = null;
- try {
- File currDir = new File(".");
- String path = currDir.getAbsolutePath();
- String fileLocation = path.substring(0, path.length() - 1) + "temp.xls";
-
- workbook = Workbook.createWorkbook(new File(fileLocation));
-
- WritableSheet sheet = workbook.createSheet("Sheet 1", 0);
-
- WritableCellFormat headerFormat = new WritableCellFormat();
- WritableFont font = new WritableFont(WritableFont.ARIAL, 16, WritableFont.BOLD);
- headerFormat.setFont(font);
- headerFormat.setBackground(Colour.LIGHT_BLUE);
- headerFormat.setWrap(true);
- Label headerLabel = new Label(0, 0, "Name", headerFormat);
- sheet.setColumnView(0, 60);
- sheet.addCell(headerLabel);
-
- headerLabel = new Label(1, 0, "Age", headerFormat);
- sheet.setColumnView(0, 40);
- sheet.addCell(headerLabel);
-
- WritableCellFormat cellFormat = new WritableCellFormat();
- cellFormat.setWrap(true);
-
- Label cellLabel = new Label(0, 2, "John Smith", cellFormat);
- sheet.addCell(cellLabel);
- Number cellNumber = new Number(1, 2, 20, cellFormat);
- sheet.addCell(cellNumber);
-
- cellLabel = new Label(0, 3, "Ana Johnson", cellFormat);
- sheet.addCell(cellLabel);
- cellNumber = new Number(1, 3, 30, cellFormat);
- sheet.addCell(cellNumber);
-
- workbook.write();
- } finally {
- if (workbook != null) {
- workbook.close();
- }
- }
-
- }
-}
\ No newline at end of file
diff --git a/spring-mvc-java/src/main/java/com/baeldung/excel/MyCell.java b/spring-mvc-java/src/main/java/com/baeldung/excel/MyCell.java
new file mode 100644
index 0000000000..409829bc35
--- /dev/null
+++ b/spring-mvc-java/src/main/java/com/baeldung/excel/MyCell.java
@@ -0,0 +1,57 @@
+package com.baeldung.excel;
+
+public class MyCell {
+ private String content;
+ private String textColor;
+ private String bgColor;
+ private String textSize;
+ private String textWeight;
+
+ public MyCell() {
+ }
+
+ public MyCell(String content) {
+ this.content = content;
+ }
+
+ public String getContent() {
+ return content;
+ }
+
+ public void setContent(String content) {
+ this.content = content;
+ }
+
+ public String getTextColor() {
+ return textColor;
+ }
+
+ public void setTextColor(String textColor) {
+ this.textColor = textColor;
+ }
+
+ public String getBgColor() {
+ return bgColor;
+ }
+
+ public void setBgColor(String bgColor) {
+ this.bgColor = bgColor;
+ }
+
+ public String getTextSize() {
+ return textSize;
+ }
+
+ public void setTextSize(String textSize) {
+ this.textSize = textSize;
+ }
+
+ public String getTextWeight() {
+ return textWeight;
+ }
+
+ public void setTextWeight(String textWeight) {
+ this.textWeight = textWeight;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebConfig.java b/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebConfig.java
index 9578303554..11be08a79d 100644
--- a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebConfig.java
+++ b/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebConfig.java
@@ -108,11 +108,6 @@ public class WebConfig extends WebMvcConfigurerAdapter {
configurer.setUrlPathHelper(urlPathHelper);
}
- @Bean
- public JExcelHelper jExcelHelper() {
- return new JExcelHelper();
- }
-
@Bean
public ExcelPOIHelper excelPOIHelper() {
return new ExcelPOIHelper();
diff --git a/spring-mvc-java/src/main/java/com/baeldung/web/controller/ExcelController.java b/spring-mvc-java/src/main/java/com/baeldung/web/controller/ExcelController.java
index 810282dd65..f76f7441a5 100644
--- a/spring-mvc-java/src/main/java/com/baeldung/web/controller/ExcelController.java
+++ b/spring-mvc-java/src/main/java/com/baeldung/web/controller/ExcelController.java
@@ -10,20 +10,15 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import com.baeldung.excel.*;
-import jxl.read.biff.BiffException;
import java.util.Map;
-import java.util.ArrayList;
+import java.util.List;
import javax.annotation.Resource;
-import jxl.write.WriteException;
@Controller
public class ExcelController {
private String fileLocation;
- @Resource(name = "jExcelHelper")
- private JExcelHelper jExcelHelper;
-
@Resource(name = "excelPOIHelper")
private ExcelPOIHelper excelPOIHelper;
@@ -45,36 +40,19 @@ public class ExcelController {
}
f.flush();
f.close();
- System.out.println(fileLocation);
model.addAttribute("message", "File: " + file.getOriginalFilename() + " has been uploaded successfully!");
return "excel";
}
- @RequestMapping(method = RequestMethod.GET, value = "/readJExcel")
- public String readJExcel(Model model) throws IOException, BiffException {
-
- if (fileLocation != null) {
- if (fileLocation.endsWith(".xls")) {
- Map> data = jExcelHelper.readJExcel(fileLocation);
- model.addAttribute("data", data);
- } else {
- model.addAttribute("message", "Not a valid .xls file!");
- }
- } else {
- model.addAttribute("message", "File missing! Please upload an excel file.");
- }
- return "excel";
- }
-
@RequestMapping(method = RequestMethod.GET, value = "/readPOI")
public String readPOI(Model model) throws IOException {
if (fileLocation != null) {
- if (fileLocation.endsWith(".xlsx")) {
- Map> data = excelPOIHelper.readExcel(fileLocation);
+ if (fileLocation.endsWith(".xlsx") || fileLocation.endsWith(".xls")) {
+ Map> data = excelPOIHelper.readExcel(fileLocation);
model.addAttribute("data", data);
} else {
- model.addAttribute("message", "Not a valid .xlsx file!");
+ model.addAttribute("message", "Not a valid excel file!");
}
} else {
model.addAttribute("message", "File missing! Please upload an excel file.");
@@ -82,24 +60,4 @@ public class ExcelController {
return "excel";
}
- @RequestMapping(method = RequestMethod.POST, value = "/writeJExcel")
- public String writeJExcel(Model model) throws IOException, BiffException, WriteException {
-
- jExcelHelper.writeJExcel();
-
- model.addAttribute("message", "Write successful!");
-
- return "excel";
- }
-
- @RequestMapping(method = RequestMethod.POST, value = "/writePOI")
- public String writePOI(Model model) throws IOException {
-
- excelPOIHelper.writeExcel();
-
- model.addAttribute("message", "Write successful!");
-
- return "excel";
- }
-
}
\ No newline at end of file
diff --git a/spring-mvc-java/src/main/webapp/WEB-INF/view/excel.jsp b/spring-mvc-java/src/main/webapp/WEB-INF/view/excel.jsp
index b50687df15..bcb5a31371 100644
--- a/spring-mvc-java/src/main/webapp/WEB-INF/view/excel.jsp
+++ b/spring-mvc-java/src/main/webapp/WEB-INF/view/excel.jsp
@@ -1,6 +1,6 @@
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
- pageEncoding="ISO-8859-1"%>
-<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
+ pageEncoding="ISO-8859-1"%>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
@@ -8,49 +8,43 @@
Excel Processing
-
-
-
-
-
-
+
+
+
-
-
-${message }
-
-
-
-Read file using JExcel
-Read file using Apache POI
-
+
+
+
+
${message }
+
+
-File content:
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+ ${cell.content}
+ |
+
+
+
+
+
-
\ No newline at end of file
diff --git a/spring-mvc-simple/README.md b/spring-mvc-simple/README.md
new file mode 100644
index 0000000000..ffb02c846a
--- /dev/null
+++ b/spring-mvc-simple/README.md
@@ -0,0 +1,3 @@
+## Relevant articles:
+
+- [HandlerAdapters in Spring MVC](http://www.baeldung.com/spring-mvc-handler-adapters)
diff --git a/spring-mvc-xml/pom.xml b/spring-mvc-xml/pom.xml
index f0e4bbff55..86eb17da64 100644
--- a/spring-mvc-xml/pom.xml
+++ b/spring-mvc-xml/pom.xml
@@ -116,7 +116,13 @@
com.maxmind.geoip2
geoip2
${geoip2.version}
-
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+
+
+
diff --git a/spring-reactor/README.md b/spring-reactor/README.md
new file mode 100644
index 0000000000..0da2d6be51
--- /dev/null
+++ b/spring-reactor/README.md
@@ -0,0 +1,3 @@
+## Relevant articles:
+
+- [Introduction to Spring Reactor](http://www.baeldung.com/spring-reactor)
diff --git a/spring-remoting/README.md b/spring-remoting/README.md
index 1aafdaf6f5..41bbd59f01 100644
--- a/spring-remoting/README.md
+++ b/spring-remoting/README.md
@@ -1,7 +1,8 @@
-## Spring Remoting Tutorials Project
+## Spring Remoting Tutorials
### Relevant Articles
- [Intro to Spring Remoting with HTTP Invokers](http://www.baeldung.com/spring-remoting-http-invoker)
+- [Spring Remoting with Hessian and Burlap](http://www.baeldung.com/spring-remoting-hessian-burlap)
### Overview
This Maven project contains the Java source code for various modules used in the Spring Remoting series of articles.
diff --git a/spring-remoting/pom.xml b/spring-remoting/pom.xml
index a43dd52a3e..52d670a726 100644
--- a/spring-remoting/pom.xml
+++ b/spring-remoting/pom.xml
@@ -3,16 +3,17 @@
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">
4.0.0
+ com.baeldung
+ spring-remoting
+ pom
+ 1.0-SNAPSHOT
+ spring-remoting
+ Parent for all projects related to Spring Remoting.
org.springframework.boot
spring-boot-starter-parent
1.4.3.RELEASE
- com.baeldung
- spring-remoting
- 1.0-SNAPSHOT
- Parent for all projects related to Spring Remoting.
- pom
1.8
@@ -34,6 +35,7 @@
remoting-http
+ remoting-hessian-burlap
\ No newline at end of file
diff --git a/spring-remoting/remoting-hessian-burlap/README.md b/spring-remoting/remoting-hessian-burlap/README.md
new file mode 100644
index 0000000000..bf90c9676f
--- /dev/null
+++ b/spring-remoting/remoting-hessian-burlap/README.md
@@ -0,0 +1,9 @@
+## Spring Remoting with Hessian and Burlap Tutorial
+
+### Relevant Articles
+- [Spring Remoting with Hessian and Burlap](http://www.baeldung.com/spring-remoting-hessian-burlap)
+
+### Overview
+This Maven project contains the Java source code for the Hessian and Burlap modules
+ used in the [Spring Remoting](https://github.com/eugenp/tutorials/tree/master/spring-remoting)
+ series of articles.
diff --git a/spring-remoting/remoting-hessian-burlap/client/pom.xml b/spring-remoting/remoting-hessian-burlap/client/pom.xml
new file mode 100644
index 0000000000..1ae9b10019
--- /dev/null
+++ b/spring-remoting/remoting-hessian-burlap/client/pom.xml
@@ -0,0 +1,59 @@
+
+
+
+ remoting-hessian-burlap
+ com.baeldung
+ 1.0-SNAPSHOT
+
+ 4.0.0
+
+ spring-remoting-hessian-burlap-client
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-tomcat
+
+
+
+
+ ${project.groupId}
+ api
+
+
+ com.caucho
+ hessian
+ 4.0.38
+
+
+
+
+ ${project.groupId}
+ remoting-hessian-burlap-server
+ ${project.version}
+ test
+
+
+ javax.servlet
+ javax.servlet-api
+ test
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.springframework.boot
+ spring-boot-starter-tomcat
+ test
+
+
+
+
\ No newline at end of file
diff --git a/spring-remoting/remoting-hessian-burlap/client/src/main/java/com/baeldung/client/BurlapClient.java b/spring-remoting/remoting-hessian-burlap/client/src/main/java/com/baeldung/client/BurlapClient.java
new file mode 100644
index 0000000000..477c29eb26
--- /dev/null
+++ b/spring-remoting/remoting-hessian-burlap/client/src/main/java/com/baeldung/client/BurlapClient.java
@@ -0,0 +1,28 @@
+package com.baeldung.client;
+
+import com.baeldung.api.BookingException;
+import com.baeldung.api.CabBookingService;
+import org.springframework.boot.SpringApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.remoting.caucho.BurlapProxyFactoryBean;
+
+import static java.lang.System.out;
+
+@Configuration
+public class BurlapClient {
+
+ @Bean
+ public BurlapProxyFactoryBean burlapInvoker() {
+ BurlapProxyFactoryBean invoker = new BurlapProxyFactoryBean();
+ invoker.setServiceUrl("http://localhost:8080/b_booking");
+ invoker.setServiceInterface(CabBookingService.class);
+ return invoker;
+ }
+
+ public static void main(String[] args) throws BookingException {
+ CabBookingService service = SpringApplication.run(BurlapClient.class, args).getBean(CabBookingService.class);
+ out.println(service.bookRide("13 Seagate Blvd, Key Largo, FL 33037"));
+ }
+
+}
diff --git a/spring-remoting/remoting-hessian-burlap/client/src/main/java/com/baeldung/client/HessianClient.java b/spring-remoting/remoting-hessian-burlap/client/src/main/java/com/baeldung/client/HessianClient.java
new file mode 100644
index 0000000000..b5f366094e
--- /dev/null
+++ b/spring-remoting/remoting-hessian-burlap/client/src/main/java/com/baeldung/client/HessianClient.java
@@ -0,0 +1,28 @@
+package com.baeldung.client;
+
+import com.baeldung.api.BookingException;
+import com.baeldung.api.CabBookingService;
+import org.springframework.boot.SpringApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.remoting.caucho.HessianProxyFactoryBean;
+
+import static java.lang.System.out;
+
+@Configuration
+public class HessianClient {
+
+ @Bean
+ public HessianProxyFactoryBean hessianInvoker() {
+ HessianProxyFactoryBean invoker = new HessianProxyFactoryBean();
+ invoker.setServiceUrl("http://localhost:8080/booking");
+ invoker.setServiceInterface(CabBookingService.class);
+ return invoker;
+ }
+
+ public static void main(String[] args) throws BookingException {
+ CabBookingService service = SpringApplication.run(HessianClient.class, args).getBean(CabBookingService.class);
+ out.println(service.bookRide("13 Seagate Blvd, Key Largo, FL 33037"));
+ }
+
+}
diff --git a/spring-remoting/remoting-hessian-burlap/client/src/test/java/com/baeldung/client/CabBookingServiceTest.java b/spring-remoting/remoting-hessian-burlap/client/src/test/java/com/baeldung/client/CabBookingServiceTest.java
new file mode 100644
index 0000000000..373701f714
--- /dev/null
+++ b/spring-remoting/remoting-hessian-burlap/client/src/test/java/com/baeldung/client/CabBookingServiceTest.java
@@ -0,0 +1,74 @@
+package com.baeldung.client;
+
+import com.baeldung.api.Booking;
+import com.baeldung.api.BookingException;
+import com.baeldung.api.CabBookingService;
+import com.baeldung.server.Server;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import static java.lang.Thread.sleep;
+
+@SpringBootTest(classes = {BurlapClient.class, HessianClient.class})
+@RunWith(SpringRunner.class)
+public class CabBookingServiceTest {
+
+ static Logger log = LoggerFactory.getLogger(CabBookingServiceTest.class);
+ @Autowired @Qualifier("burlapInvoker") CabBookingService burlapClient;
+ @Autowired @Qualifier("hessianInvoker") CabBookingService hessianClient;
+ static Thread serverThread;
+
+ @BeforeClass
+ public static void startServer() throws InterruptedException {
+ serverThread = serverThread();
+ log.info("Starting server.");
+ serverThread.start();
+ // increase this enough to let the server start
+ sleep(6000);
+ }
+
+ @org.junit.Test
+ public void bookACabWithBurlapClient() throws InterruptedException {
+ bookACab(this.burlapClient);
+ }
+
+ @org.junit.Test
+ public void bookACabWithHessianClient() throws InterruptedException {
+ bookACab(this.hessianClient);
+ }
+
+ private void bookACab(CabBookingService burlapClient) {
+ Booking booking;
+ try {
+ booking = burlapClient.bookRide("Duomo place");
+ log.info("Booking success: {}", booking);
+ } catch (BookingException e) {
+ log.info("Booking failed: {}", e.getMessage());
+ }
+ }
+
+ @AfterClass
+ public static void stopServer() throws InterruptedException {
+ serverThread.interrupt();
+ serverThread.join();
+ log.info("Server terminated.");
+ }
+
+ static Thread serverThread() {
+ Thread serverThread = new Thread(()-> {
+ log.info("Starting Burlap and Hessian server");
+ Server.main(new String[]{});
+ log.info("Burlap and Hessian server terminated");
+ });
+ serverThread.setDaemon(true);
+ return serverThread;
+ }
+
+}
diff --git a/spring-remoting/remoting-hessian-burlap/client/src/test/resources/application.properties b/spring-remoting/remoting-hessian-burlap/client/src/test/resources/application.properties
new file mode 100644
index 0000000000..13577dc391
--- /dev/null
+++ b/spring-remoting/remoting-hessian-burlap/client/src/test/resources/application.properties
@@ -0,0 +1 @@
+application.properties=9999
\ No newline at end of file
diff --git a/spring-remoting/remoting-hessian-burlap/pom.xml b/spring-remoting/remoting-hessian-burlap/pom.xml
new file mode 100644
index 0000000000..682e460880
--- /dev/null
+++ b/spring-remoting/remoting-hessian-burlap/pom.xml
@@ -0,0 +1,20 @@
+
+
+
+ spring-remoting
+ com.baeldung
+ 1.0-SNAPSHOT
+
+ pom
+
+ server
+ client
+
+ 4.0.0
+
+ remoting-hessian-burlap
+
+
+
\ No newline at end of file
diff --git a/spring-remoting/remoting-hessian-burlap/server/pom.xml b/spring-remoting/remoting-hessian-burlap/server/pom.xml
new file mode 100644
index 0000000000..f1fed73ed8
--- /dev/null
+++ b/spring-remoting/remoting-hessian-burlap/server/pom.xml
@@ -0,0 +1,30 @@
+
+
+
+ remoting-hessian-burlap
+ com.baeldung
+ 1.0-SNAPSHOT
+
+ 4.0.0
+
+ remoting-hessian-burlap-server
+
+
+
+ com.baeldung
+ spring-remoting-http-server
+ ${project.version}
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ com.caucho
+ hessian
+ 4.0.38
+
+
+
\ No newline at end of file
diff --git a/spring-remoting/remoting-hessian-burlap/server/src/main/java/com/baeldung/server/Server.java b/spring-remoting/remoting-hessian-burlap/server/src/main/java/com/baeldung/server/Server.java
new file mode 100644
index 0000000000..9b7e463871
--- /dev/null
+++ b/spring-remoting/remoting-hessian-burlap/server/src/main/java/com/baeldung/server/Server.java
@@ -0,0 +1,37 @@
+package com.baeldung.server;
+
+import com.baeldung.api.CabBookingService;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.remoting.caucho.BurlapServiceExporter;
+import org.springframework.remoting.caucho.HessianServiceExporter;
+import org.springframework.remoting.support.RemoteExporter;
+
+@Configuration @ComponentScan @EnableAutoConfiguration public class Server {
+
+ @Bean CabBookingService bookingService() {
+ return new CabBookingServiceImpl();
+ }
+
+ @Bean(name = "/booking") RemoteExporter hessianService(CabBookingService service) {
+ HessianServiceExporter exporter = new HessianServiceExporter();
+ exporter.setService(bookingService());
+ exporter.setServiceInterface(CabBookingService.class);
+ return exporter;
+ }
+
+ @Bean(name = "/b_booking") RemoteExporter burlapService(CabBookingService service) {
+ BurlapServiceExporter exporter = new BurlapServiceExporter();
+ exporter.setService(bookingService());
+ exporter.setServiceInterface(CabBookingService.class);
+ return exporter;
+ }
+
+ public static void main(String[] args) {
+ SpringApplication.run(Server.class, args);
+ }
+
+}
\ No newline at end of file
diff --git a/spring-rest-angular/pom.xml b/spring-rest-angular/pom.xml
index 099867d19b..62ab03522d 100644
--- a/spring-rest-angular/pom.xml
+++ b/spring-rest-angular/pom.xml
@@ -11,7 +11,7 @@
org.springframework.boot
spring-boot-starter-parent
- 1.4.4.RELEASE
+ 1.5.1.RELEASE
@@ -74,6 +74,15 @@
spring-boot-starter-test
test
+
+ org.springframework.boot
+ spring-boot-starter-data-rest
+
+
+ javax.servlet
+ jstl
+ 1.2
+
diff --git a/spring-rest-angular/src/main/java/org/baeldung/web/controller/EmployeeController.java b/spring-rest-angular/src/main/java/org/baeldung/web/controller/EmployeeController.java
new file mode 100644
index 0000000000..a8bfc254c3
--- /dev/null
+++ b/spring-rest-angular/src/main/java/org/baeldung/web/controller/EmployeeController.java
@@ -0,0 +1,14 @@
+package org.baeldung.web.controller;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+@Controller
+public class EmployeeController {
+
+ @RequestMapping(value = "/employeePage")
+ public String getEmployeePage() {
+ return "employee";
+ }
+
+}
diff --git a/spring-rest-angular/src/main/java/org/baeldung/web/dao/EmployeeCRUDRepository.java b/spring-rest-angular/src/main/java/org/baeldung/web/dao/EmployeeCRUDRepository.java
new file mode 100644
index 0000000000..1e5f81ed45
--- /dev/null
+++ b/spring-rest-angular/src/main/java/org/baeldung/web/dao/EmployeeCRUDRepository.java
@@ -0,0 +1,13 @@
+package org.baeldung.web.dao;
+
+import java.util.List;
+
+import org.baeldung.web.entity.Employee;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.data.repository.query.Param;
+import org.springframework.data.rest.core.annotation.RepositoryRestResource;
+
+@RepositoryRestResource(collectionResourceRel = "employee", path = "employees")
+public interface EmployeeCRUDRepository extends CrudRepository {
+ List findByName(@Param("name") String name);
+}
diff --git a/spring-rest-angular/src/main/java/org/baeldung/web/dao/StudentRepository.java b/spring-rest-angular/src/main/java/org/baeldung/web/dao/StudentRepository.java
index b1aafb583a..566d95da00 100644
--- a/spring-rest-angular/src/main/java/org/baeldung/web/dao/StudentRepository.java
+++ b/spring-rest-angular/src/main/java/org/baeldung/web/dao/StudentRepository.java
@@ -3,6 +3,7 @@ package org.baeldung.web.dao;
import org.baeldung.web.entity.Student;
import org.springframework.data.jpa.repository.JpaRepository;
-public interface StudentRepository extends JpaRepository {
+public interface StudentRepository extends JpaRepository
+{
}
diff --git a/spring-rest-angular/src/main/java/org/baeldung/web/entity/Employee.java b/spring-rest-angular/src/main/java/org/baeldung/web/entity/Employee.java
new file mode 100644
index 0000000000..8d6831726c
--- /dev/null
+++ b/spring-rest-angular/src/main/java/org/baeldung/web/entity/Employee.java
@@ -0,0 +1,57 @@
+package org.baeldung.web.entity;
+
+import java.io.Serializable;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+
+@Entity
+public class Employee implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @Id
+ private long id;
+
+ @Column(nullable = false)
+ private String name;
+
+ @Column(nullable = false)
+ private Integer age;
+
+ public Employee() {
+ }
+
+ public Employee(long id, String name, Integer age) {
+ super();
+ this.id = id;
+ this.name = name;
+ this.age = age;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Integer getAge() {
+ return age;
+ }
+
+ public void setAge(Integer age) {
+ this.age = age;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+}
diff --git a/spring-rest-angular/src/main/java/org/baeldung/web/main/MvcConfig.java b/spring-rest-angular/src/main/java/org/baeldung/web/main/MvcConfig.java
new file mode 100644
index 0000000000..b24aad1177
--- /dev/null
+++ b/spring-rest-angular/src/main/java/org/baeldung/web/main/MvcConfig.java
@@ -0,0 +1,36 @@
+package org.baeldung.web.main;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.ViewResolver;
+import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
+import org.springframework.web.servlet.config.annotation.EnableWebMvc;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
+import org.springframework.web.servlet.view.InternalResourceViewResolver;
+
+@Configuration
+@EnableWebMvc
+@ComponentScan("org.baeldung.web.controller")
+public class MvcConfig extends WebMvcConfigurerAdapter{
+
+ public MvcConfig(){
+ super();
+ }
+
+ @Override
+ public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
+ configurer.enable();
+ }
+
+ @Bean
+ public ViewResolver viewResolver() {
+ final InternalResourceViewResolver bean = new InternalResourceViewResolver();
+
+ bean.setPrefix("/WEB-INF/pages/");
+ bean.setSuffix(".html");
+
+ return bean;
+ }
+
+}
diff --git a/spring-rest-angular/src/main/java/org/baeldung/web/main/PersistenceConfig.java b/spring-rest-angular/src/main/java/org/baeldung/web/main/PersistenceConfig.java
index df1240f270..8454ce155a 100644
--- a/spring-rest-angular/src/main/java/org/baeldung/web/main/PersistenceConfig.java
+++ b/spring-rest-angular/src/main/java/org/baeldung/web/main/PersistenceConfig.java
@@ -2,7 +2,7 @@ package org.baeldung.web.main;
import javax.sql.DataSource;
-import org.springframework.boot.orm.jpa.EntityScan;
+import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@@ -26,7 +26,7 @@ public class PersistenceConfig {
@Bean
public DataSource dataSource() {
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
- EmbeddedDatabase db = builder.setType(EmbeddedDatabaseType.HSQL).addScript("db/sql/data.sql").build();
+ EmbeddedDatabase db = builder.setType(EmbeddedDatabaseType.HSQL).addScript("db/sql/data.sql").addScript("db/sql/employees.sql").build();
return db;
}
diff --git a/spring-rest-angular/src/main/resources/db/sql/employees.sql b/spring-rest-angular/src/main/resources/db/sql/employees.sql
new file mode 100644
index 0000000000..366c0c309a
--- /dev/null
+++ b/spring-rest-angular/src/main/resources/db/sql/employees.sql
@@ -0,0 +1,16 @@
+CREATE TABLE employee (
+ id INTEGER PRIMARY KEY,
+ name VARCHAR(30),
+ age INTEGER
+);
+
+INSERT INTO employee (id,name,age)
+VALUES (1,'Bryan',20);
+INSERT INTO employee (id,name,age)
+VALUES (2,'Lisa',30);
+INSERT INTO employee (id,name,age)
+VALUES (3,'Laura',40);
+INSERT INTO employee (id,name,age)
+VALUES (4,'Alex',35);
+INSERT INTO employee (id,name,age)
+VALUES (5,'John',47);
diff --git a/spring-rest-angular/src/main/webapp/WEB-INF/pages/employee.html b/spring-rest-angular/src/main/webapp/WEB-INF/pages/employee.html
new file mode 100644
index 0000000000..510e981f25
--- /dev/null
+++ b/spring-rest-angular/src/main/webapp/WEB-INF/pages/employee.html
@@ -0,0 +1,55 @@
+
+
+
+
+Employee CRUD
+
+
+
+
+
+
+