Merge branch 'master' into BAEL-16646-2
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
package com.baeldung.algorithms.knapsack;
|
||||
|
||||
public class Knapsack {
|
||||
|
||||
public int knapsackRec(int[] w, int[] v, int n, int W) {
|
||||
if (n <= 0) {
|
||||
return 0;
|
||||
} else if (w[n - 1] > W) {
|
||||
return knapsackRec(w, v, n - 1, W);
|
||||
} else {
|
||||
return Math.max(knapsackRec(w, v, n - 1, W), v[n - 1] + knapsackRec(w, v, n - 1, W - w[n - 1]));
|
||||
}
|
||||
}
|
||||
|
||||
public int knapsackDP(int[] w, int[] v, int n, int W) {
|
||||
if (n <= 0 || W <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int[][] m = new int[n + 1][W + 1];
|
||||
for (int j = 0; j <= W; j++) {
|
||||
m[0][j] = 0;
|
||||
}
|
||||
|
||||
for (int i = 1; i <= n; i++) {
|
||||
for (int j = 1; j <= W; j++) {
|
||||
if (w[i - 1] > j) {
|
||||
m[i][j] = m[i - 1][j];
|
||||
} else {
|
||||
m[i][j] = Math.max(m[i - 1][j], m[i - 1][j - w[i - 1]] + v[i - 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return m[n][W];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.baeldung.algorithms.knapsack;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class KnapsackUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenWeightsandValues_whenCalculateMax_thenOutputCorrectResult() {
|
||||
final int[] w = new int[] { 23, 26, 20, 18, 32, 27, 29, 26, 30, 27 };
|
||||
final int[] v = new int[] { 505, 352, 458, 220, 354, 414, 498, 545, 473, 543 };
|
||||
final int n = 10;
|
||||
final int W = 67;
|
||||
final Knapsack knapsack = new Knapsack();
|
||||
|
||||
assertEquals(1270, knapsack.knapsackRec(w, v, n, W));
|
||||
assertEquals(1270, knapsack.knapsackDP(w, v, n, W));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenZeroItems_whenCalculateMax_thenOutputZero() {
|
||||
final int[] w = new int[] {};
|
||||
final int[] v = new int[] {};
|
||||
final int n = 0;
|
||||
final int W = 67;
|
||||
final Knapsack knapsack = new Knapsack();
|
||||
|
||||
assertEquals(0, knapsack.knapsackRec(w, v, n, W));
|
||||
assertEquals(0, knapsack.knapsackDP(w, v, n, W));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenZeroWeightLimit_whenCalculateMax_thenOutputZero() {
|
||||
final int[] w = new int[] { 23, 26, 20, 18, 32, 27, 29, 26, 30, 27 };
|
||||
final int[] v = new int[] { 505, 352, 458, 220, 354, 414, 498, 545, 473, 543 };
|
||||
final int n = 10;
|
||||
final int W = 0;
|
||||
final Knapsack knapsack = new Knapsack();
|
||||
|
||||
assertEquals(0, knapsack.knapsackRec(w, v, n, W));
|
||||
assertEquals(0, knapsack.knapsackDP(w, v, n, W));
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
package com.baeldung.java_8_features.groupingby;
|
||||
|
||||
public class Tuple {
|
||||
import java.util.Objects;
|
||||
|
||||
public class Tuple {
|
||||
private final BlogPostType type;
|
||||
private final String author;
|
||||
|
||||
private BlogPostType type;
|
||||
private String author;
|
||||
|
||||
public Tuple(BlogPostType type, String author) {
|
||||
super();
|
||||
this.type = type;
|
||||
this.author = author;
|
||||
}
|
||||
@@ -15,20 +15,27 @@ public class Tuple {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(BlogPostType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
public void setAuthor(String author) {
|
||||
this.author = author;
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o)
|
||||
return true;
|
||||
if (o == null || getClass() != o.getClass())
|
||||
return false;
|
||||
Tuple tuple = (Tuple) o;
|
||||
return type == tuple.type && author.equals(tuple.author);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(type, author);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Tuple [type=" + type + ", author=" + author + ", getType()=" + getType() + ", getAuthor()=" + getAuthor() + ", getClass()=" + getClass() + ", hashCode()=" + hashCode() + ", toString()=" + super.toString() + "]";
|
||||
return "Tuple{" + "type=" + type + ", author='" + author + '\'' + '}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,32 @@
|
||||
package com.baeldung.java_8_features.groupingby;
|
||||
|
||||
import com.baeldung.java_8_features.groupingby.BlogPost;
|
||||
import com.baeldung.java_8_features.groupingby.BlogPostType;
|
||||
import org.junit.Test;
|
||||
import static java.util.Comparator.comparingInt;
|
||||
import static java.util.stream.Collectors.averagingInt;
|
||||
import static java.util.stream.Collectors.counting;
|
||||
import static java.util.stream.Collectors.groupingBy;
|
||||
import static java.util.stream.Collectors.groupingByConcurrent;
|
||||
import static java.util.stream.Collectors.joining;
|
||||
import static java.util.stream.Collectors.mapping;
|
||||
import static java.util.stream.Collectors.maxBy;
|
||||
import static java.util.stream.Collectors.summarizingInt;
|
||||
import static java.util.stream.Collectors.summingInt;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
import static java.util.stream.Collectors.toSet;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumMap;
|
||||
import java.util.IntSummaryStatistics;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import static java.util.Comparator.comparingInt;
|
||||
import static java.util.stream.Collectors.*;
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Test;
|
||||
|
||||
public class Java8GroupingByCollectorUnitTest {
|
||||
|
||||
@@ -180,4 +197,19 @@ public class Java8GroupingByCollectorUnitTest {
|
||||
assertEquals(15, newsLikeStatistics.getMin());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenAListOfPosts_whenGroupedByComplexMapKeyType_thenGetAMapBetweenTupleAndList() {
|
||||
Map<Tuple, List<BlogPost>> postsPerTypeAndAuthor = posts.stream()
|
||||
.collect(groupingBy(post -> new Tuple(post.getType(), post.getAuthor())));
|
||||
|
||||
List<BlogPost> result = postsPerTypeAndAuthor.get(new Tuple(BlogPostType.GUIDE, "Author 1"));
|
||||
|
||||
assertThat(result.size()).isEqualTo(1);
|
||||
|
||||
BlogPost blogPost = result.get(0);
|
||||
|
||||
assertThat(blogPost.getTitle()).isEqualTo("Programming guide");
|
||||
assertThat(blogPost.getType()).isEqualTo(BlogPostType.GUIDE);
|
||||
assertThat(blogPost.getAuthor()).isEqualTo("Author 1");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,15 +192,48 @@ public class ArrayOperations {
|
||||
return array[new Random().nextInt(array.length)];
|
||||
}
|
||||
|
||||
public static Integer[] intersectionSimple(final Integer[] a, final Integer[] b){
|
||||
return Stream.of(a).filter(Arrays.asList(b)::contains).toArray(Integer[]::new);
|
||||
public static Integer[] intersectionSimple(final Integer[] a, final Integer[] b) {
|
||||
return Stream.of(a)
|
||||
.filter(Arrays.asList(b)::contains)
|
||||
.toArray(Integer[]::new);
|
||||
}
|
||||
|
||||
public static Integer[] intersectionSet(final Integer[] a, final Integer[] b){
|
||||
return Stream.of(a).filter(Arrays.asList(b)::contains).distinct().toArray(Integer[]::new);
|
||||
public static Integer[] intersectionSet(final Integer[] a, final Integer[] b) {
|
||||
return Stream.of(a)
|
||||
.filter(Arrays.asList(b)::contains)
|
||||
.distinct()
|
||||
.toArray(Integer[]::new);
|
||||
}
|
||||
|
||||
public static Integer[] intersectionMultiSet(final Integer[] a, final Integer[] b){
|
||||
return Stream.of(a).filter(new LinkedList<>(Arrays.asList(b))::remove).toArray(Integer[]::new);
|
||||
public static Integer[] intersectionMultiSet(final Integer[] a, final Integer[] b) {
|
||||
return Stream.of(a)
|
||||
.filter(new LinkedList<>(Arrays.asList(b))::remove)
|
||||
.toArray(Integer[]::new);
|
||||
}
|
||||
|
||||
public static Integer[] addElementUsingPureJava(Integer[] srcArray, int elementToAdd) {
|
||||
Integer[] destArray = new Integer[srcArray.length + 1];
|
||||
|
||||
for (int i = 0; i < srcArray.length; i++) {
|
||||
destArray[i] = srcArray[i];
|
||||
}
|
||||
|
||||
destArray[destArray.length - 1] = elementToAdd;
|
||||
return destArray;
|
||||
}
|
||||
|
||||
public static int[] insertAnElementAtAGivenIndex(final int[] srcArray, int index, int newElement) {
|
||||
int[] destArray = new int[srcArray.length + 1];
|
||||
int j = 0;
|
||||
for (int i = 0; i < destArray.length - 1; i++) {
|
||||
|
||||
if (i == index) {
|
||||
destArray[i] = newElement;
|
||||
} else {
|
||||
destArray[i] = srcArray[j];
|
||||
j++;
|
||||
}
|
||||
}
|
||||
return destArray;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.baeldung.arraylist.operations;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class ArrayListOperations {
|
||||
|
||||
public static Integer getAnIntegerElement(ArrayList<Integer> anArrayList, int index) {
|
||||
return anArrayList.get(index);
|
||||
}
|
||||
|
||||
public static void modifyAnIntegerElement(ArrayList<Integer> anArrayList, int index, Integer newElement) {
|
||||
anArrayList.set(index, newElement);
|
||||
}
|
||||
|
||||
public static void appendAnIntegerElement(ArrayList<Integer> anArrayList, Integer newElement) {
|
||||
anArrayList.add(newElement);
|
||||
}
|
||||
|
||||
public static void insertAnIntegerElementAtIndex(ArrayList<Integer> anArrayList, int index, Integer newElement) {
|
||||
anArrayList.add(index, newElement);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,12 +1,11 @@
|
||||
package com.baeldung.array.operations;
|
||||
|
||||
import java.util.Arrays;
|
||||
import org.assertj.core.api.Condition;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
|
||||
public class ArrayOperationsUnitTest {
|
||||
|
||||
@@ -262,8 +261,7 @@ public class ArrayOperationsUnitTest {
|
||||
|
||||
@Test
|
||||
public void whenMapIntArrayToString_thenReturnArray() {
|
||||
String[] expectedArray = new String[] { "Value: 3", "Value: 5", "Value: 2", "Value: 5", "Value: 14",
|
||||
"Value: 4" };
|
||||
String[] expectedArray = new String[] { "Value: 3", "Value: 5", "Value: 2", "Value: 5", "Value: 14", "Value: 4" };
|
||||
String[] output = ArrayOperations.mapIntArrayToString(defaultIntArray);
|
||||
|
||||
assertThat(output).containsExactly(expectedArray);
|
||||
@@ -313,13 +311,10 @@ public class ArrayOperationsUnitTest {
|
||||
int[] output5 = ArrayOperations.shuffleIntArray(defaultIntArray);
|
||||
int[] output6 = ArrayOperations.shuffleIntArray(defaultIntArray);
|
||||
|
||||
Condition<int[]> atLeastOneArraysIsNotEqual = new Condition<int[]>(
|
||||
"at least one output should be different (order-wise)") {
|
||||
Condition<int[]> atLeastOneArraysIsNotEqual = new Condition<int[]>("at least one output should be different (order-wise)") {
|
||||
@Override
|
||||
public boolean matches(int[] value) {
|
||||
return !Arrays.equals(value, output) || !Arrays.equals(value, output2) || !Arrays.equals(value, output3)
|
||||
|| !Arrays.equals(value, output4) || !Arrays.equals(value, output5)
|
||||
|| !Arrays.equals(value, output6);
|
||||
return !Arrays.equals(value, output) || !Arrays.equals(value, output2) || !Arrays.equals(value, output3) || !Arrays.equals(value, output4) || !Arrays.equals(value, output5) || !Arrays.equals(value, output6);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -335,13 +330,10 @@ public class ArrayOperationsUnitTest {
|
||||
Integer[] output5 = ArrayOperations.shuffleObjectArray(defaultObjectArray);
|
||||
Integer[] output6 = ArrayOperations.shuffleObjectArray(defaultObjectArray);
|
||||
|
||||
Condition<Integer[]> atLeastOneArraysIsNotEqual = new Condition<Integer[]>(
|
||||
"at least one output should be different (order-wise)") {
|
||||
Condition<Integer[]> atLeastOneArraysIsNotEqual = new Condition<Integer[]>("at least one output should be different (order-wise)") {
|
||||
@Override
|
||||
public boolean matches(Integer[] value) {
|
||||
return !Arrays.equals(value, output) || !Arrays.equals(value, output2) || !Arrays.equals(value, output3)
|
||||
|| !Arrays.equals(value, output4) || !Arrays.equals(value, output5)
|
||||
|| !Arrays.equals(value, output6);
|
||||
return !Arrays.equals(value, output) || !Arrays.equals(value, output2) || !Arrays.equals(value, output3) || !Arrays.equals(value, output4) || !Arrays.equals(value, output5) || !Arrays.equals(value, output6);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -362,4 +354,27 @@ public class ArrayOperationsUnitTest {
|
||||
|
||||
assertThat(defaultObjectArray).contains(output);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenSourceArrayAndElement_whenAddElementUsingPureJavaIsInvoked_thenNewElementMustBeAdded() {
|
||||
Integer[] sourceArray = { 1, 2, 3, 4 };
|
||||
int elementToAdd = 5;
|
||||
|
||||
Integer[] destArray = ArrayOperations.addElementUsingPureJava(sourceArray, elementToAdd);
|
||||
|
||||
Integer[] expectedArray = { 1, 2, 3, 4, 5 };
|
||||
assertArrayEquals(expectedArray, destArray);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenInsertAnElementAtAGivenIndexCalled_thenShiftTheFollowingElementsAndInsertTheElementInArray() {
|
||||
int[] expectedArray = { 1, 4, 2, 3, 0 };
|
||||
int[] anArray = new int[4];
|
||||
anArray[0] = 1;
|
||||
anArray[1] = 2;
|
||||
anArray[2] = 3;
|
||||
int[] outputArray = ArrayOperations.insertAnElementAtAGivenIndex(anArray, 1, 4);
|
||||
|
||||
assertThat(outputArray).containsExactly(expectedArray);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.baeldung.arraylist.operations;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class ArrayListOperationsUnitTest {
|
||||
|
||||
private ArrayList<Integer> anArrayList;
|
||||
|
||||
@BeforeEach
|
||||
public void setupDefaults() {
|
||||
anArrayList = new ArrayList<>();
|
||||
anArrayList.add(2);
|
||||
anArrayList.add(3);
|
||||
anArrayList.add(4);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenGetAnIntegerElementCalled_thenReturnTheIntegerElement() {
|
||||
Integer output = ArrayListOperations.getAnIntegerElement(anArrayList, 1);
|
||||
|
||||
assertThat(output).isEqualTo(3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenModifyAnIntegerElementCalled_thenModifyTheIntegerElement() {
|
||||
ArrayListOperations.modifyAnIntegerElement(anArrayList, 2, 5);
|
||||
Integer output = ArrayListOperations.getAnIntegerElement(anArrayList, 2);
|
||||
|
||||
assertThat(output).isEqualTo(5);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenAppendAnIntegerElementCalled_thenTheIntegerElementIsAppendedToArrayList() {
|
||||
ArrayListOperations.appendAnIntegerElement(anArrayList, 6);
|
||||
Integer output = ArrayListOperations.getAnIntegerElement(anArrayList, anArrayList.size() - 1);
|
||||
|
||||
assertThat(output).isEqualTo(6);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenInsertAnIntegerAtIndexCalled_thenTheIntegerElementIsInseredToArrayList() {
|
||||
ArrayListOperations.insertAnIntegerElementAtIndex(anArrayList, 1, 10);
|
||||
Integer output = ArrayListOperations.getAnIntegerElement(anArrayList, 1);
|
||||
|
||||
assertThat(output).isEqualTo(10);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.baeldung.list;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Demo different approaches to get count of duplicated elements in an
|
||||
* arrayList
|
||||
*/
|
||||
public class DuplicatesCounter {
|
||||
|
||||
public static <T> Map<T, Long> countByClassicalLoop(List<T> inputList) {
|
||||
Map<T, Long> resultMap = new HashMap<>();
|
||||
for (T element : inputList) {
|
||||
if (resultMap.containsKey(element)) {
|
||||
resultMap.put(element, resultMap.get(element) + 1L);
|
||||
} else {
|
||||
resultMap.put(element, 1L);
|
||||
}
|
||||
}
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
public static <T> Map<T, Long> countByClassicalLoopWithMapCompute(List<T> inputList) {
|
||||
Map<T, Long> resultMap = new HashMap<>();
|
||||
for (T element : inputList) {
|
||||
resultMap.compute(element, (k, v) -> v == null ? 1 : v + 1);
|
||||
}
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
public static <T> Map<T, Long> countByStreamToMap(List<T> inputList) {
|
||||
return inputList.stream().collect(Collectors.toMap(Function.identity(), v -> 1L, Long::sum));
|
||||
}
|
||||
|
||||
public static <T> Map<T, Long> countByStreamGroupBy(List<T> inputList) {
|
||||
return inputList.stream().collect(Collectors.groupingBy(k -> k, Collectors.counting()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.baeldung.list;
|
||||
|
||||
import org.assertj.core.util.Lists;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.data.MapEntry.entry;
|
||||
|
||||
class DuplicatesCounterUnitTest {
|
||||
|
||||
|
||||
private static List<String> INPUT_LIST = Lists.list(
|
||||
"expect1",
|
||||
"expect2", "expect2",
|
||||
"expect3", "expect3", "expect3",
|
||||
"expect4", "expect4", "expect4", "expect4");
|
||||
|
||||
@Test
|
||||
void givenInput_whenCountByClassicalLoop_thenGetResultMap() {
|
||||
Map<String, Long> result = DuplicatesCounter.countByClassicalLoop(INPUT_LIST);
|
||||
verifyResult(result);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void givenInput_whenCountByClassicalLoopWithMapCompute_thenGetResultMap() {
|
||||
Map<String, Long> result = DuplicatesCounter.countByClassicalLoopWithMapCompute(INPUT_LIST);
|
||||
verifyResult(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenInput_whenCountByStreamToMap_thenGetResultMap() {
|
||||
Map<String, Long> result = DuplicatesCounter.countByStreamToMap(INPUT_LIST);
|
||||
verifyResult(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenInput_whenCountByStreamGroupBy_thenGetResultMap() {
|
||||
Map<String, Long> result = DuplicatesCounter.countByStreamGroupBy(INPUT_LIST);
|
||||
verifyResult(result);
|
||||
}
|
||||
|
||||
private void verifyResult(Map<String, Long> resultMap) {
|
||||
assertThat(resultMap)
|
||||
.isNotEmpty().hasSize(4)
|
||||
.containsExactly(
|
||||
entry("expect1", 1L),
|
||||
entry("expect2", 2L),
|
||||
entry("expect3", 3L),
|
||||
entry("expect4", 4L));
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.baeldung.date;
|
||||
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
@@ -16,7 +16,7 @@ import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import org.junit.Test;
|
||||
|
||||
public class DateDiffUnitTest {
|
||||
|
||||
@@ -31,14 +31,14 @@ public class DateDiffUnitTest {
|
||||
|
||||
assertEquals(diff, 6);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void givenTwoDatesInJava8_whenDifferentiating_thenWeGetSix() {
|
||||
LocalDate now = LocalDate.now();
|
||||
LocalDate sixDaysBehind = now.minusDays(6);
|
||||
|
||||
Period period = Period.between(now, sixDaysBehind);
|
||||
int diff = period.getDays();
|
||||
int diff = Math.abs(period.getDays());
|
||||
|
||||
assertEquals(diff, 6);
|
||||
}
|
||||
@@ -68,7 +68,8 @@ public class DateDiffUnitTest {
|
||||
public void givenTwoZonedDateTimesInJava8_whenDifferentiating_thenWeGetSix() {
|
||||
LocalDateTime ldt = LocalDateTime.now();
|
||||
ZonedDateTime now = ldt.atZone(ZoneId.of("America/Montreal"));
|
||||
ZonedDateTime sixDaysBehind = now.withZoneSameInstant(ZoneId.of("Asia/Singapore")).minusDays(6);
|
||||
ZonedDateTime sixDaysBehind = now.withZoneSameInstant(ZoneId.of("Asia/Singapore"))
|
||||
.minusDays(6);
|
||||
long diff = ChronoUnit.DAYS.between(sixDaysBehind, now);
|
||||
assertEquals(diff, 6);
|
||||
}
|
||||
|
||||
@@ -36,10 +36,15 @@ class UseLocalDate {
|
||||
}
|
||||
|
||||
LocalDate getFirstDayOfMonth() {
|
||||
LocalDate firstDayOfMonth = LocalDate.now().with(TemporalAdjusters.firstDayOfMonth());
|
||||
LocalDate firstDayOfMonth = LocalDate.now()
|
||||
.with(TemporalAdjusters.firstDayOfMonth());
|
||||
return firstDayOfMonth;
|
||||
}
|
||||
|
||||
boolean isLeapYear(LocalDate localDate) {
|
||||
return localDate.isLeapYear();
|
||||
}
|
||||
|
||||
LocalDateTime getStartOfDay(LocalDate localDate) {
|
||||
LocalDateTime startofDay = localDate.atStartOfDay();
|
||||
return startofDay;
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.baeldung.datetime;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.temporal.ChronoField;
|
||||
|
||||
public class UseLocalDateTime {
|
||||
@@ -21,4 +22,7 @@ public class UseLocalDateTime {
|
||||
return endOfDate;
|
||||
}
|
||||
|
||||
LocalDateTime ofEpochSecond(int epochSecond, ZoneOffset zoneOffset) {
|
||||
return LocalDateTime.ofEpochSecond(epochSecond, 0, zoneOffset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,10 @@ public class UseLocalTime {
|
||||
return LocalTime.of(hour, min, seconds);
|
||||
}
|
||||
|
||||
LocalTime getLocalTimeUsingFactoryOfMethod(int hour, int min) {
|
||||
return LocalTime.of(hour, min);
|
||||
}
|
||||
|
||||
LocalTime getLocalTimeUsingParseMethod(String timeRepresentation) {
|
||||
return LocalTime.parse(timeRepresentation);
|
||||
}
|
||||
|
||||
@@ -12,31 +12,35 @@ class UseZonedDateTime {
|
||||
return ZonedDateTime.of(localDateTime, zoneId);
|
||||
}
|
||||
|
||||
ZonedDateTime getZonedDateTimeUsingParseMethod(String parsableString) {
|
||||
return ZonedDateTime.parse(parsableString);
|
||||
}
|
||||
|
||||
ZonedDateTime getStartOfDay(LocalDate localDate, ZoneId zone) {
|
||||
ZonedDateTime startofDay = localDate.atStartOfDay()
|
||||
ZonedDateTime startOfDay = localDate.atStartOfDay()
|
||||
.atZone(zone);
|
||||
return startofDay;
|
||||
return startOfDay;
|
||||
}
|
||||
|
||||
ZonedDateTime getStartOfDayShorthand(LocalDate localDate, ZoneId zone) {
|
||||
ZonedDateTime startofDay = localDate.atStartOfDay(zone);
|
||||
return startofDay;
|
||||
ZonedDateTime startOfDay = localDate.atStartOfDay(zone);
|
||||
return startOfDay;
|
||||
}
|
||||
|
||||
ZonedDateTime getStartOfDayFromZonedDateTime(ZonedDateTime zonedDateTime) {
|
||||
ZonedDateTime startofDay = zonedDateTime.toLocalDateTime()
|
||||
ZonedDateTime startOfDay = zonedDateTime.toLocalDateTime()
|
||||
.toLocalDate()
|
||||
.atStartOfDay(zonedDateTime.getZone());
|
||||
return startofDay;
|
||||
return startOfDay;
|
||||
}
|
||||
|
||||
ZonedDateTime getStartOfDayAtMinTime(ZonedDateTime zonedDateTime) {
|
||||
ZonedDateTime startofDay = zonedDateTime.with(ChronoField.HOUR_OF_DAY, 0);
|
||||
return startofDay;
|
||||
ZonedDateTime startOfDay = zonedDateTime.with(ChronoField.HOUR_OF_DAY, 0);
|
||||
return startOfDay;
|
||||
}
|
||||
|
||||
ZonedDateTime getStartOfDayAtMidnightTime(ZonedDateTime zonedDateTime) {
|
||||
ZonedDateTime startofDay = zonedDateTime.with(ChronoField.NANO_OF_DAY, 0);
|
||||
return startofDay;
|
||||
ZonedDateTime startOfDay = zonedDateTime.with(ChronoField.NANO_OF_DAY, 0);
|
||||
return startOfDay;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
package com.baeldung.date.comparison;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.time.*;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class Java8DateTimeApiGeneralComparisonsUnitTest {
|
||||
|
||||
@Test
|
||||
@@ -54,10 +58,8 @@ public class Java8DateTimeApiGeneralComparisonsUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenZonedDateTimes_whenComparing_thenAssertsPass() {
|
||||
ZonedDateTime timeInNewYork = ZonedDateTime.of(2019, 8, 10, 8, 0, 0, 0,
|
||||
ZoneId.of("America/New_York"));
|
||||
ZonedDateTime timeInBerlin = ZonedDateTime.of(2019, 8, 10, 14, 0, 0, 0,
|
||||
ZoneId.of("Europe/Berlin"));
|
||||
ZonedDateTime timeInNewYork = ZonedDateTime.of(2019, 8, 10, 8, 0, 0, 0, ZoneId.of("America/New_York"));
|
||||
ZonedDateTime timeInBerlin = ZonedDateTime.of(2019, 8, 10, 14, 0, 0, 0, ZoneId.of("Europe/Berlin"));
|
||||
|
||||
assertThat(timeInNewYork.isAfter(timeInBerlin), is(false));
|
||||
assertThat(timeInNewYork.isBefore(timeInBerlin), is(false));
|
||||
@@ -80,4 +82,14 @@ public class Java8DateTimeApiGeneralComparisonsUnitTest {
|
||||
|
||||
assertThat(firstTime.compareTo(secondTime), is(-1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenMinMaxLocalTimes_whenComparing_thenAssertsPass() {
|
||||
LocalTime minTime = LocalTime.MIN;
|
||||
LocalTime time = LocalTime.of(8, 30);
|
||||
LocalTime maxTime = LocalTime.MAX;
|
||||
|
||||
assertThat(minTime.isBefore(time), is(true));
|
||||
assertThat(time.isBefore(maxTime), is(true));
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,39 @@
|
||||
package com.baeldung.dateapi;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalTime;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class JavaDurationUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenATimePlus30Seconds_whenRequestingDuration_thenExpect30() {
|
||||
LocalTime initialTime = LocalTime.of(6, 30, 0);
|
||||
LocalTime finalTime = initialTime.plus(Duration.ofSeconds(30));
|
||||
|
||||
long seconds = Duration.between(initialTime, finalTime)
|
||||
.getSeconds();
|
||||
|
||||
assertThat(seconds).isEqualTo(30);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenATimePlus30Seconds_whenRequestingSecondsBetween_thenExpect30() {
|
||||
LocalTime initialTime = LocalTime.of(6, 30, 0);
|
||||
LocalTime finalTime = initialTime.plus(Duration.ofSeconds(30));
|
||||
|
||||
long seconds = ChronoUnit.SECONDS.between(initialTime, finalTime);
|
||||
|
||||
assertThat(seconds).isEqualTo(30);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test2() {
|
||||
Instant start = Instant.parse("2017-10-03T10:15:30.00Z");
|
||||
@@ -29,11 +52,15 @@ public class JavaDurationUnitTest {
|
||||
Duration fromMinutes = Duration.ofMinutes(60);
|
||||
assertEquals(1, fromMinutes.toHours());
|
||||
|
||||
assertEquals(120, duration.plusSeconds(60).getSeconds());
|
||||
assertEquals(30, duration.minusSeconds(30).getSeconds());
|
||||
assertEquals(120, duration.plusSeconds(60)
|
||||
.getSeconds());
|
||||
assertEquals(30, duration.minusSeconds(30)
|
||||
.getSeconds());
|
||||
|
||||
assertEquals(120, duration.plus(60, ChronoUnit.SECONDS).getSeconds());
|
||||
assertEquals(30, duration.minus(30, ChronoUnit.SECONDS).getSeconds());
|
||||
assertEquals(120, duration.plus(60, ChronoUnit.SECONDS)
|
||||
.getSeconds());
|
||||
assertEquals(30, duration.minus(30, ChronoUnit.SECONDS)
|
||||
.getSeconds());
|
||||
|
||||
Duration fromChar1 = Duration.parse("P1DT1H10M10.5S");
|
||||
Duration fromChar2 = Duration.parse("PT10M");
|
||||
|
||||
@@ -1,18 +1,41 @@
|
||||
package com.baeldung.dateapi;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.Period;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.Period;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
||||
public class JavaPeriodUnitTest {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(JavaPeriodUnitTest.class);
|
||||
|
||||
@Test
|
||||
public void givenADatePlus5Days_whenRequestingPeriod_thenExpectFive() {
|
||||
LocalDate initialDate = LocalDate.parse("2007-05-10");
|
||||
LocalDate finalDate = initialDate.plus(Period.ofDays(5));
|
||||
|
||||
int days = Period.between(initialDate, finalDate)
|
||||
.getDays();
|
||||
|
||||
assertThat(days).isEqualTo(5);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenADatePlus5Days_whenRequestingDaysBetween_thenExpectFive() {
|
||||
LocalDate initialDate = LocalDate.parse("2007-05-10");
|
||||
LocalDate finalDate = initialDate.plus(Period.ofDays(5));
|
||||
|
||||
long days = ChronoUnit.DAYS.between(initialDate, finalDate);
|
||||
|
||||
assertThat(days).isEqualTo(5);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenTestPeriod_thenOk() {
|
||||
|
||||
@@ -24,8 +47,10 @@ public class JavaPeriodUnitTest {
|
||||
LOG.info(String.format("Years:%d months:%d days:%d", period.getYears(), period.getMonths(), period.getDays()));
|
||||
|
||||
assertFalse(period.isNegative());
|
||||
assertEquals(56, period.plusDays(50).getDays());
|
||||
assertEquals(9, period.minusMonths(2).getMonths());
|
||||
assertEquals(56, period.plusDays(50)
|
||||
.getDays());
|
||||
assertEquals(9, period.minusMonths(2)
|
||||
.getMonths());
|
||||
|
||||
Period fromUnits = Period.of(3, 10, 10);
|
||||
Period fromDays = Period.ofDays(50);
|
||||
|
||||
@@ -7,12 +7,13 @@ import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.Month;
|
||||
import java.time.ZoneOffset;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class UseLocalDateTimeUnitTest {
|
||||
|
||||
UseLocalDateTime useLocalDateTime = new UseLocalDateTime();
|
||||
private UseLocalDateTime useLocalDateTime = new UseLocalDateTime();
|
||||
|
||||
@Test
|
||||
public void givenString_whenUsingParse_thenLocalDateTime() {
|
||||
@@ -33,4 +34,28 @@ public class UseLocalDateTimeUnitTest {
|
||||
assertThat(endOfDayFromGivenDirectly.toLocalTime()).isEqualTo(LocalTime.MAX);
|
||||
assertThat(endOfDayFromGivenDirectly.toString()).isEqualTo("2018-06-23T23:59:59.999999999");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenLocalDateTimeInFebruary_whenRequestingMonth_thenMonthIsFebruary() {
|
||||
LocalDateTime givenLocalDateTime = LocalDateTime.of(2015, Month.FEBRUARY, 20, 6, 30);
|
||||
|
||||
assertThat(givenLocalDateTime.getMonth()).isEqualTo(Month.FEBRUARY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenLocalDateTime_whenManipulating_thenResultIsAsExpected() {
|
||||
LocalDateTime givenLocalDateTime = LocalDateTime.parse("2015-02-20T06:30:00");
|
||||
|
||||
LocalDateTime manipulatedLocalDateTime = givenLocalDateTime.plusDays(1);
|
||||
manipulatedLocalDateTime = manipulatedLocalDateTime.minusHours(2);
|
||||
|
||||
assertThat(manipulatedLocalDateTime).isEqualTo(LocalDateTime.of(2015, Month.FEBRUARY, 21, 4, 30));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenRequestTimeFromEpoch_thenResultIsAsExpected() {
|
||||
LocalDateTime result = useLocalDateTime.ofEpochSecond(1465817690, ZoneOffset.UTC);
|
||||
|
||||
assertThat(result.toString()).isEqualTo("2016-06-13T11:34:50");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import org.junit.Test;
|
||||
|
||||
public class UseLocalDateUnitTest {
|
||||
|
||||
UseLocalDate useLocalDate = new UseLocalDate();
|
||||
private UseLocalDate useLocalDate = new UseLocalDate();
|
||||
|
||||
@Test
|
||||
public void givenValues_whenUsingFactoryOf_thenLocalDate() {
|
||||
@@ -88,4 +88,31 @@ public class UseLocalDateUnitTest {
|
||||
assertThat(endOfDayWithMax.toString()).isEqualTo("2018-06-23T23:59:59.999999999");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenTheYear2000_whenCheckingForLeapYear_thenReturnTrue() {
|
||||
LocalDate given = LocalDate.parse("2000-06-23");
|
||||
|
||||
boolean leapYear = useLocalDate.isLeapYear(given);
|
||||
|
||||
assertThat(leapYear).isEqualTo(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenTheYear2004_whenCheckingForLeapYear_thenReturnTrue() {
|
||||
LocalDate given = LocalDate.parse("2004-06-23");
|
||||
|
||||
boolean leapYear = useLocalDate.isLeapYear(given);
|
||||
|
||||
assertThat(leapYear).isEqualTo(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenTheYear2019_whenCheckingForLeapYear_thenReturnFalse() {
|
||||
LocalDate given = LocalDate.parse("2019-06-23");
|
||||
|
||||
boolean leapYear = useLocalDate.isLeapYear(given);
|
||||
|
||||
assertThat(leapYear).isEqualTo(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -7,21 +7,30 @@ import org.junit.Test;
|
||||
|
||||
public class UseLocalTimeUnitTest {
|
||||
|
||||
UseLocalTime useLocalTime = new UseLocalTime();
|
||||
private UseLocalTime useLocalTime = new UseLocalTime();
|
||||
|
||||
@Test
|
||||
public void givenValues_whenUsingFactoryOf_thenLocalTime() {
|
||||
Assert.assertEquals("07:07:07", useLocalTime.getLocalTimeUsingFactoryOfMethod(7, 7, 7).toString());
|
||||
Assert.assertEquals("07:07:07", useLocalTime.getLocalTimeUsingFactoryOfMethod(7, 7, 7)
|
||||
.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenValues_whenUsingFactoryOfWithoutSeconds_thenLocalTime() {
|
||||
Assert.assertEquals("07:07", useLocalTime.getLocalTimeUsingFactoryOfMethod(7, 7)
|
||||
.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenString_whenUsingParse_thenLocalTime() {
|
||||
Assert.assertEquals("06:30", useLocalTime.getLocalTimeUsingParseMethod("06:30").toString());
|
||||
Assert.assertEquals("06:30", useLocalTime.getLocalTimeUsingParseMethod("06:30")
|
||||
.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenTime_whenAddHour_thenLocalTime() {
|
||||
Assert.assertEquals("07:30", useLocalTime.addAnHour(LocalTime.of(6, 30)).toString());
|
||||
Assert.assertEquals("07:30", useLocalTime.addAnHour(LocalTime.of(6, 30))
|
||||
.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -7,13 +7,14 @@ import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class UseZonedDateTimeUnitTest {
|
||||
|
||||
UseZonedDateTime zonedDateTime = new UseZonedDateTime();
|
||||
private UseZonedDateTime zonedDateTime = new UseZonedDateTime();
|
||||
|
||||
@Test
|
||||
public void givenZoneId_thenZonedDateTime() {
|
||||
@@ -22,6 +23,13 @@ public class UseZonedDateTimeUnitTest {
|
||||
Assert.assertEquals(zoneId, ZoneId.from(zonedDatetime));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenRequestingZones_thenAtLeastOneIsReturned() {
|
||||
Set<String> allZoneIds = ZoneId.getAvailableZoneIds();
|
||||
|
||||
assertThat(allZoneIds.size()).isGreaterThan(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenLocalDateOrZoned_whenSettingStartOfDay_thenReturnMidnightInAllCases() {
|
||||
LocalDate given = LocalDate.parse("2018-06-23");
|
||||
@@ -42,4 +50,15 @@ public class UseZonedDateTimeUnitTest {
|
||||
assertThat(startOfOfDayWithMethod.toLocalTime()
|
||||
.toString()).isEqualTo("00:00");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenAStringWithTimeZone_whenParsing_thenEqualsExpected() {
|
||||
ZonedDateTime resultFromString = zonedDateTime.getZonedDateTimeUsingParseMethod("2015-05-03T10:15:30+01:00[Europe/Paris]");
|
||||
ZonedDateTime resultFromLocalDateTime = ZonedDateTime.of(2015, 5, 3, 11, 15, 30, 0, ZoneId.of("Europe/Paris"));
|
||||
|
||||
assertThat(resultFromString.getZone()).isEqualTo(ZoneId.of("Europe/Paris"));
|
||||
assertThat(resultFromLocalDateTime.getZone()).isEqualTo(ZoneId.of("Europe/Paris"));
|
||||
|
||||
assertThat(resultFromString).isEqualTo(resultFromLocalDateTime);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.baeldung.core.modifiers;
|
||||
|
||||
public class FirstClass {
|
||||
|
||||
protected String name;
|
||||
|
||||
protected FirstClass(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
protected String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
protected static class InnerClass {
|
||||
public InnerClass() {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.baeldung.core.modifiers;
|
||||
|
||||
public class GenericClass {
|
||||
|
||||
public static void main(String[] args) {
|
||||
// accessing protected constructor
|
||||
FirstClass first = new FirstClass("random name");
|
||||
// using protected method
|
||||
System.out.println("FirstClass name is " + first.getName());
|
||||
// accessing a protected field
|
||||
first.name = "new name";
|
||||
// instantiating protected inner class
|
||||
FirstClass.InnerClass innerClass = new FirstClass.InnerClass();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.baeldung.core.modifiers.otherpackage;
|
||||
|
||||
import com.baeldung.core.modifiers.FirstClass;
|
||||
|
||||
public class SecondClass extends FirstClass {
|
||||
|
||||
public SecondClass(String name) {
|
||||
// accessing protected constructor
|
||||
super(name);
|
||||
// using protected method
|
||||
System.out.println("SecondClass name is " + this.getName());
|
||||
// accessing a protected field
|
||||
this.name = "new name";
|
||||
// instantiating protected inner class -> add public constructor to InnerClass
|
||||
FirstClass.InnerClass innerClass = new FirstClass.InnerClass();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.baeldung.core.modifiers.otherpackage;
|
||||
|
||||
import com.baeldung.core.modifiers.FirstClass;
|
||||
//import com.baeldung.core.modifiers.FirstClass.InnerClass;
|
||||
|
||||
public class SecondGenericClass {
|
||||
|
||||
// uncomment the following lines to see the errors
|
||||
public static void main(String[] args) {
|
||||
// accessing protected constructor
|
||||
// FirstClass first = new FirstClass("random name");
|
||||
// using protected method
|
||||
// System.out.println("FirstClass name is " + first.getName());
|
||||
// accessing a protected field
|
||||
// first.name = "new name";
|
||||
// instantiating protected inner class
|
||||
// FirstClass.InnerClass innerClass = new FirstClass.InnerClass();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,7 +3,6 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung.ddd</groupId>
|
||||
<artifactId>ddd</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>ddd</name>
|
||||
<packaging>jar</packaging>
|
||||
<description>DDD series examples</description>
|
||||
@@ -35,7 +34,6 @@
|
||||
<dependency>
|
||||
<groupId>org.junit.platform</groupId>
|
||||
<artifactId>junit-platform-launcher</artifactId>
|
||||
<version>${junit-platform.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -85,8 +83,6 @@
|
||||
|
||||
<properties>
|
||||
<joda-money.version>1.0.1</joda-money.version>
|
||||
<maven-surefire-plugin.version>2.22.0</maven-surefire-plugin.version>
|
||||
<spring-boot.version>2.0.6.RELEASE</spring-boot.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -1,7 +1,6 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>disruptor</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<name>disruptor</name>
|
||||
@@ -116,10 +115,7 @@
|
||||
<properties>
|
||||
<!-- util -->
|
||||
<disruptor.version>3.3.6</disruptor.version>
|
||||
<!-- testing -->
|
||||
<testng.version>6.10</testng.version>
|
||||
<assertj.version>3.6.1</assertj.version>
|
||||
|
||||
<!-- testing -->
|
||||
<maven-shade-plugin.version>2.4.3</maven-shade-plugin.version>
|
||||
<maven-jar-plugin.version>3.0.2</maven-jar-plugin.version>
|
||||
<onejar-maven-plugin.version>1.4.4</onejar-maven-plugin.version>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>dozer</artifactId>
|
||||
<version>1.0</version>
|
||||
<name>dozer</name>
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
<dubbo.version>2.5.7</dubbo.version>
|
||||
<zookeeper.version>3.4.11</zookeeper.version>
|
||||
<zkclient.version>0.10</zkclient.version>
|
||||
<surefire.version>2.19.1</surefire.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung.ethereum</groupId>
|
||||
<artifactId>ethereum</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>ethereum</name>
|
||||
|
||||
<parent>
|
||||
@@ -207,8 +206,6 @@
|
||||
</repositories>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<tomcat.version>8.5.4</tomcat.version>
|
||||
<ethereumj-core.version>1.5.0-RELEASE</ethereumj-core.version>
|
||||
<web3j.core.version>3.3.1</web3j.core.version>
|
||||
<spring.boot.version>1.5.6.RELEASE</spring.boot.version>
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>flyway-cdi-extension</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<name>flyway-cdi-extension</name>
|
||||
@@ -51,8 +50,6 @@
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<cdi-api.version>2.0.SP1</cdi-api.version>
|
||||
<weld-se-core.version>3.0.5.Final</weld-se-core.version>
|
||||
<flyway-core.version>5.1.4</flyway-core.version>
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
<!-- POM file generated with GWT webAppCreator -->
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>google-web-toolkit</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<name>google-web-toolkit</name>
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>0.1-SNAPSHOT</version>
|
||||
<name>gson</name>
|
||||
|
||||
@@ -13,9 +13,6 @@
|
||||
<relativePath>../parent-java</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>guava-collections-map</finalName>
|
||||
<resources>
|
||||
@@ -26,7 +23,4 @@
|
||||
</resources>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -1,7 +1,6 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>guava-collections-set</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<name>guava-collections-set</name>
|
||||
@@ -28,8 +27,6 @@
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<!-- util -->
|
||||
<guava.version>27.1-jre</guava.version>
|
||||
<!-- testing -->
|
||||
<assertj.version>3.6.1</assertj.version>
|
||||
</properties>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>guava-collections</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<name>guava-collections</name>
|
||||
@@ -54,7 +53,6 @@
|
||||
|
||||
<properties>
|
||||
<!-- util -->
|
||||
<guava.version>24.0-jre</guava.version>
|
||||
<commons-collections4.version>4.1</commons-collections4.version>
|
||||
|
||||
<!-- testing -->
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>guava-io</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<name>guava-io</name>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<name>guava</name>
|
||||
@@ -39,9 +38,6 @@
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<!-- util -->
|
||||
<guava.version>24.0-jre</guava.version>
|
||||
|
||||
<!-- testing -->
|
||||
<assertj.version>3.6.1</assertj.version>
|
||||
</properties>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>hazelcast</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>hazelcast</name>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>httpclient-simple</artifactId>
|
||||
<version>0.1-SNAPSHOT</version>
|
||||
<name>httpclient-simple</name>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
<version>0.1-SNAPSHOT</version>
|
||||
<name>httpclient</name>
|
||||
@@ -48,11 +47,6 @@
|
||||
<artifactId>httpmime</artifactId>
|
||||
<version>${httpclient.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
<version>${commons-codec.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpasyncclient</artifactId>
|
||||
@@ -82,51 +76,12 @@
|
||||
</resources>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>live</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>integration-test</phase>
|
||||
<goals>
|
||||
<goal>test</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>**/*ManualTest.java</exclude>
|
||||
</excludes>
|
||||
<includes>
|
||||
<include>**/*LiveTest.java</include>
|
||||
</includes>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<systemPropertyVariables>
|
||||
<test.mime>json</test.mime>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
<properties>
|
||||
<!-- util -->
|
||||
<guava.version>19.0</guava.version>
|
||||
<commons-codec.version>1.10</commons-codec.version>
|
||||
<httpasyncclient.version>4.1.4</httpasyncclient.version>
|
||||
<!-- testing -->
|
||||
<wiremock.version>2.5.1</wiremock.version>
|
||||
<httpclient.version>4.5.8</httpclient.version> <!-- 4.3.6 --> <!-- 4.4-beta1 -->
|
||||
<!-- maven plugins -->
|
||||
<cargo-maven2-plugin.version>1.6.1</cargo-maven2-plugin.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -41,23 +41,11 @@
|
||||
<artifactId>hystrix-metrics-event-stream</artifactId>
|
||||
<version>${hystrix-metrics-event-stream.version}</version>
|
||||
</dependency>
|
||||
<!--<dependency> <groupId>com.netflix.hystrix</groupId> <artifactId>hystrix-dashboard</artifactId> <version>${hystrix-dashboard.version}</version> </dependency> -->
|
||||
<dependency>
|
||||
<groupId>com.netflix.rxjava</groupId>
|
||||
<artifactId>rxjava-core</artifactId>
|
||||
<version>${rxjava-core.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
<artifactId>hamcrest-all</artifactId>
|
||||
<version>${hamcrest-all.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
@@ -65,9 +53,7 @@
|
||||
<hystrix-core.version>1.5.8</hystrix-core.version>
|
||||
<rxjava-core.version>0.20.7</rxjava-core.version>
|
||||
<!-- maven plugins -->
|
||||
<maven-resources-plugin.version>2.7</maven-resources-plugin.version>
|
||||
<hystrix-metrics-event-stream.version>1.5.8</hystrix-metrics-event-stream.version>
|
||||
<hystrix-dashboard.version>1.5.8</hystrix-dashboard.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
This module contains articles about Jackson that are also part of the Jackson Ebook.
|
||||
|
||||
###The Course
|
||||
### The Course
|
||||
|
||||
The "REST With Spring" Classes: http://bit.ly/restwithspring
|
||||
|
||||
### Relevant Articles:
|
||||
|
||||
@@ -1,20 +1,29 @@
|
||||
package com.baeldung.jackson.objectmapper;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
|
||||
import com.baeldung.jackson.objectmapper.dto.Car;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
public class JavaReadWriteJsonExampleUnitTest {
|
||||
@Rule
|
||||
public TemporaryFolder folder = new TemporaryFolder();
|
||||
|
||||
final String EXAMPLE_JSON = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }";
|
||||
final String LOCAL_JSON = "[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : \"Red\", \"type\" : \"BMW\" }]";
|
||||
|
||||
@@ -27,6 +36,19 @@ public class JavaReadWriteJsonExampleUnitTest {
|
||||
assertThat(carAsString, containsString("renault"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenWriteToFile_thanCorrect() throws Exception {
|
||||
File resultFile = folder.newFile("car.json");
|
||||
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
Car car = new Car("yellow", "renault");
|
||||
objectMapper.writeValue(resultFile, car);
|
||||
|
||||
Car fromFile = objectMapper.readValue(resultFile, Car.class);
|
||||
assertEquals(car.getType(), fromFile.getType());
|
||||
assertEquals(car.getColor(), fromFile.getColor());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenReadJsonToJava_thanCorrect() throws Exception {
|
||||
final ObjectMapper objectMapper = new ObjectMapper();
|
||||
@@ -66,4 +88,26 @@ public class JavaReadWriteJsonExampleUnitTest {
|
||||
assertNotNull(key);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void wheReadFromFile_thanCorrect() throws Exception {
|
||||
File resource = new File("src/test/resources/json_car.json");
|
||||
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
Car fromFile = objectMapper.readValue(resource, Car.class);
|
||||
|
||||
assertEquals("BMW", fromFile.getType());
|
||||
assertEquals("Black", fromFile.getColor());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void wheReadFromUrl_thanCorrect() throws Exception {
|
||||
URL resource = new URL("file:src/test/resources/json_car.json");
|
||||
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
Car fromFile = objectMapper.readValue(resource, Car.class);
|
||||
|
||||
assertEquals("BMW", fromFile.getType());
|
||||
assertEquals("Black", fromFile.getColor());
|
||||
}
|
||||
}
|
||||
|
||||
13
jackson-simple/src/test/resources/.gitignore
vendored
13
jackson-simple/src/test/resources/.gitignore
vendored
@@ -1,13 +0,0 @@
|
||||
*.class
|
||||
|
||||
#folders#
|
||||
/target
|
||||
/neoDb*
|
||||
/data
|
||||
/src/main/webapp/WEB-INF/classes
|
||||
*/META-INF/*
|
||||
|
||||
# Packaged files #
|
||||
*.jar
|
||||
*.war
|
||||
*.ear
|
||||
4
jackson-simple/src/test/resources/json_car.json
Normal file
4
jackson-simple/src/test/resources/json_car.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"color": "Black",
|
||||
"type": "BMW"
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.baeldung.jackson.deserialization.enums;
|
||||
|
||||
public class City {
|
||||
|
||||
private Distance distance;
|
||||
|
||||
public Distance getDistance() {
|
||||
return distance;
|
||||
}
|
||||
|
||||
public void setDistance(Distance distance) {
|
||||
this.distance = distance;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.baeldung.jackson.deserialization.enums;
|
||||
|
||||
public enum Distance {
|
||||
|
||||
KILOMETER("km", 1000), MILE("miles", 1609.34), METER("meters", 1), INCH("inches", 0.0254), CENTIMETER("cm", 0.01), MILLIMETER("mm", 0.001);
|
||||
|
||||
private String unit;
|
||||
private double meters;
|
||||
|
||||
private Distance(String unit, double meters) {
|
||||
this.unit = unit;
|
||||
this.meters = meters;
|
||||
}
|
||||
|
||||
public void setMeters(double meters) {
|
||||
this.meters = meters;
|
||||
}
|
||||
|
||||
public double getMeters() {
|
||||
return meters;
|
||||
}
|
||||
|
||||
public String getUnit() {
|
||||
return unit;
|
||||
}
|
||||
|
||||
public void setUnit(String unit) {
|
||||
this.unit = unit;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.baeldung.jackson.deserialization.enums.customdeserializer;
|
||||
|
||||
public class City {
|
||||
|
||||
private Distance distance;
|
||||
|
||||
public Distance getDistance() {
|
||||
return distance;
|
||||
}
|
||||
|
||||
public void setDistance(Distance distance) {
|
||||
this.distance = distance;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.baeldung.jackson.deserialization.enums.customdeserializer;
|
||||
|
||||
import java.io.IOException;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
|
||||
|
||||
public class CustomEnumDeserializer extends StdDeserializer<Distance> {
|
||||
|
||||
private static final long serialVersionUID = -1166032307856492833L;
|
||||
|
||||
public CustomEnumDeserializer() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public CustomEnumDeserializer(Class<?> c) {
|
||||
super(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Distance deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException, JsonProcessingException {
|
||||
|
||||
JsonNode node = jsonParser.getCodec().readTree(jsonParser);
|
||||
|
||||
String unit = node.get("unit").asText();
|
||||
double meters = node.get("meters").asDouble();
|
||||
|
||||
for (Distance distance : Distance.values()) {
|
||||
|
||||
if (distance.getUnit().equals(unit) &&
|
||||
Double.compare(distance.getMeters(), meters) == 0) {
|
||||
|
||||
return distance;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.baeldung.jackson.deserialization.enums.customdeserializer;
|
||||
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
|
||||
@JsonDeserialize(using = CustomEnumDeserializer.class)
|
||||
public enum Distance {
|
||||
|
||||
KILOMETER("km", 1000), MILE("miles", 1609.34), METER("meters", 1), INCH("inches", 0.0254), CENTIMETER("cm", 0.01), MILLIMETER("mm", 0.001);
|
||||
|
||||
private String unit;
|
||||
private double meters;
|
||||
|
||||
private Distance(String unit, double meters) {
|
||||
this.unit = unit;
|
||||
this.meters = meters;
|
||||
}
|
||||
|
||||
public double getMeters() {
|
||||
return meters;
|
||||
}
|
||||
|
||||
public void setMeters(double meters) {
|
||||
this.meters = meters;
|
||||
}
|
||||
|
||||
public String getUnit() {
|
||||
return unit;
|
||||
}
|
||||
|
||||
public void setUnit(String unit) {
|
||||
this.unit = unit;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.baeldung.jackson.deserialization.enums.jsoncreator;
|
||||
|
||||
public class City {
|
||||
|
||||
private Distance distance;
|
||||
|
||||
public Distance getDistance() {
|
||||
return distance;
|
||||
}
|
||||
|
||||
public void setDistance(Distance distance) {
|
||||
this.distance = distance;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.baeldung.jackson.deserialization.enums.jsoncreator;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
public enum Distance {
|
||||
|
||||
KILOMETER("km", 1000), MILE("miles", 1609.34), METER("meters", 1), INCH("inches", 0.0254), CENTIMETER("cm", 0.01), MILLIMETER("mm", 0.001);
|
||||
|
||||
private String unit;
|
||||
private double meters;
|
||||
|
||||
private Distance(String unit, double meters) {
|
||||
this.unit = unit;
|
||||
this.meters = meters;
|
||||
}
|
||||
|
||||
public void setMeters(double meters) {
|
||||
this.meters = meters;
|
||||
}
|
||||
|
||||
public double getMeters() {
|
||||
return meters;
|
||||
}
|
||||
|
||||
public String getUnit() {
|
||||
return unit;
|
||||
}
|
||||
|
||||
public void setUnit(String unit) {
|
||||
this.unit = unit;
|
||||
}
|
||||
|
||||
@JsonCreator
|
||||
public static Distance forValues(@JsonProperty("unit") String unit, @JsonProperty("meters") double meters) {
|
||||
|
||||
for (Distance distance : Distance.values()) {
|
||||
if (distance.unit.equals(unit) && Double.compare(distance.meters, meters) == 0) {
|
||||
|
||||
return distance;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.baeldung.jackson.deserialization.enums.jsonproperty;
|
||||
|
||||
public class City {
|
||||
|
||||
private Distance distance;
|
||||
|
||||
public Distance getDistance() {
|
||||
return distance;
|
||||
}
|
||||
|
||||
public void setDistance(Distance distance) {
|
||||
this.distance = distance;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.baeldung.jackson.deserialization.enums.jsonproperty;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
public enum Distance {
|
||||
|
||||
@JsonProperty("distance-in-km")
|
||||
KILOMETER("km", 1000),
|
||||
|
||||
@JsonProperty("distance-in-miles")
|
||||
MILE("miles", 1609.34),
|
||||
|
||||
@JsonProperty("distance-in-meters")
|
||||
METER("meters", 1),
|
||||
|
||||
@JsonProperty("distance-in-inches")
|
||||
INCH("inches", 0.0254),
|
||||
|
||||
@JsonProperty("distance-in-cm")
|
||||
CENTIMETER("cm", 0.01),
|
||||
|
||||
@JsonProperty("distance-in-mm")
|
||||
MILLIMETER("mm", 0.001);
|
||||
|
||||
private String unit;
|
||||
private double meters;
|
||||
|
||||
private Distance(String unit, double meters) {
|
||||
this.unit = unit;
|
||||
this.meters = meters;
|
||||
}
|
||||
|
||||
public void setMeters(double meters) {
|
||||
this.meters = meters;
|
||||
}
|
||||
|
||||
public double getMeters() {
|
||||
return meters;
|
||||
}
|
||||
|
||||
public String getUnit() {
|
||||
return unit;
|
||||
}
|
||||
|
||||
public void setUnit(String unit) {
|
||||
this.unit = unit;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.baeldung.jackson.deserialization.enums.jsonvalue;
|
||||
|
||||
public class City {
|
||||
|
||||
private Distance distance;
|
||||
|
||||
public Distance getDistance() {
|
||||
return distance;
|
||||
}
|
||||
|
||||
public void setDistance(Distance distance) {
|
||||
this.distance = distance;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.baeldung.jackson.deserialization.enums.jsonvalue;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonValue;
|
||||
|
||||
public enum Distance {
|
||||
|
||||
KILOMETER("km", 1000), MILE("miles", 1609.34), METER("meters", 1), INCH("inches", 0.0254), CENTIMETER("cm", 0.01), MILLIMETER("mm", 0.001);
|
||||
|
||||
private String unit;
|
||||
private double meters;
|
||||
|
||||
private Distance(String unit, double meters) {
|
||||
this.unit = unit;
|
||||
this.meters = meters;
|
||||
}
|
||||
|
||||
public void setMeters(double meters) {
|
||||
this.meters = meters;
|
||||
}
|
||||
|
||||
@JsonValue
|
||||
public double getMeters() {
|
||||
return meters;
|
||||
}
|
||||
|
||||
public String getUnit() {
|
||||
return unit;
|
||||
}
|
||||
|
||||
public void setUnit(String unit) {
|
||||
this.unit = unit;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.baeldung.jackson.deserialization.enums;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import java.io.IOException;
|
||||
import org.junit.Test;
|
||||
import com.fasterxml.jackson.core.JsonParseException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
public class DefaultEnumDeserializationUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenEnum_whenDeserializingJson_thenCorrectRepresentation() throws JsonParseException, IOException {
|
||||
String json = "{\"distance\":\"KILOMETER\"}";
|
||||
City city = new ObjectMapper().readValue(json, City.class);
|
||||
|
||||
assertEquals(Distance.KILOMETER, city.getDistance());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.baeldung.jackson.deserialization.enums.customdeserializer;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import java.io.IOException;
|
||||
import org.junit.Test;
|
||||
import com.fasterxml.jackson.core.JsonParseException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
public class EnumCustomDeserializationUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenEnumWithCustomDeserializer_whenDeserializingJson_thenCorrectRepresentation() throws JsonParseException, IOException {
|
||||
String json = "{\"distance\": {\"unit\":\"miles\",\"meters\":1609.34}}";
|
||||
|
||||
City city = new ObjectMapper().readValue(json, City.class);
|
||||
assertEquals(Distance.MILE, city.getDistance());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.baeldung.jackson.deserialization.enums.jsoncreator;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import java.io.IOException;
|
||||
import org.junit.Test;
|
||||
import com.fasterxml.jackson.core.JsonParseException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
public class EnumDeserializationUsingJsonCreatorUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenEnumWithJsonCreator_whenDeserializingJson_thenCorrectRepresentation() throws JsonParseException, IOException {
|
||||
String json = "{\"distance\": {\"unit\":\"miles\",\"meters\":1609.34}}";
|
||||
|
||||
City city = new ObjectMapper().readValue(json, City.class);
|
||||
assertEquals(Distance.MILE, city.getDistance());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.baeldung.jackson.deserialization.enums.jsonproperty;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import java.io.IOException;
|
||||
import org.junit.Test;
|
||||
import com.fasterxml.jackson.core.JsonParseException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
public class EnumDeserializationUsingJsonPropertyUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenEnumWithJsonProperty_whenDeserializingJson_thenCorrectRepresentation() throws JsonParseException, IOException {
|
||||
String json = "{\"distance\": \"distance-in-km\"}";
|
||||
|
||||
City city = new ObjectMapper().readValue(json, City.class);
|
||||
assertEquals(Distance.KILOMETER, city.getDistance());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.baeldung.jackson.deserialization.enums.jsonvalue;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import java.io.IOException;
|
||||
import org.junit.Test;
|
||||
import com.fasterxml.jackson.core.JsonParseException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
public class EnumDeserializationUsingJsonValueUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenEnumWithJsonValue_whenDeserializingJson_thenCorrectRepresentation() throws JsonParseException, IOException {
|
||||
String json = "{\"distance\": \"0.0254\"}";
|
||||
|
||||
City city = new ObjectMapper().readValue(json, City.class);
|
||||
assertEquals(Distance.INCH, city.getDistance());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,11 +2,8 @@ package com.baeldung.jackson.enums;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParseException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
@@ -18,5 +15,5 @@ public class JacksonEnumSerializationUnitTest {
|
||||
|
||||
assertThat(dtoAsString, containsString("1609.34"));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.baeldung.datetime;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.FormatStyle;
|
||||
import java.util.Locale;
|
||||
|
||||
public class UseDateTimeFormatter {
|
||||
public String formatAsIsoDate(LocalDateTime localDateTime) {
|
||||
return localDateTime.format(DateTimeFormatter.ISO_DATE);
|
||||
}
|
||||
|
||||
public String formatCustom(LocalDateTime localDateTime, String pattern) {
|
||||
return localDateTime.format(DateTimeFormatter.ofPattern(pattern));
|
||||
}
|
||||
|
||||
public String formatWithStyleAndLocale(LocalDateTime localDateTime, FormatStyle formatStyle, Locale locale) {
|
||||
return localDateTime.format(DateTimeFormatter.ofLocalizedDateTime(formatStyle)
|
||||
.withLocale(locale));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.baeldung.datetime;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
|
||||
public class UseOffsetDateTime {
|
||||
public OffsetDateTime offsetOfLocalDateTimeAndOffset(LocalDateTime localDateTime, ZoneOffset offset) {
|
||||
return OffsetDateTime.of(localDateTime, offset);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.baeldung.datetime;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.Month;
|
||||
import java.time.format.FormatStyle;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class UseDateTimeFormatterUnitTest {
|
||||
private final UseDateTimeFormatter subject = new UseDateTimeFormatter();
|
||||
private final LocalDateTime localDateTime = LocalDateTime.of(2015, Month.JANUARY, 25, 6, 30);
|
||||
|
||||
@Test
|
||||
public void givenALocalDate_whenFormattingAsIso_thenPass() {
|
||||
String result = subject.formatAsIsoDate(localDateTime);
|
||||
|
||||
assertThat(result).isEqualTo("2015-01-25");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenALocalDate_whenFormattingWithPattern_thenPass() {
|
||||
String result = subject.formatCustom(localDateTime, "yyyy/MM/dd");
|
||||
|
||||
assertThat(result).isEqualTo("2015/01/25");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenALocalDate_whenFormattingWithStyleAndLocale_thenPass() {
|
||||
String result = subject.formatWithStyleAndLocale(localDateTime, FormatStyle.MEDIUM, Locale.UK);
|
||||
|
||||
assertThat(result).isEqualTo("25 Jan 2015, 06:30:00");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.baeldung.datetime;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.Month;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class UseOffsetDateTimeUnitTest {
|
||||
private final UseOffsetDateTime subject = new UseOffsetDateTime();
|
||||
|
||||
@Test
|
||||
public void givenAZoneOffSetAndLocalDateTime_whenCombing_thenValidResult() {
|
||||
ZoneOffset offset = ZoneOffset.of("+02:00");
|
||||
LocalDateTime localDateTime = LocalDateTime.of(2015, Month.FEBRUARY, 20, 6, 30);
|
||||
|
||||
OffsetDateTime result = subject.offsetOfLocalDateTimeAndOffset(localDateTime, offset);
|
||||
|
||||
assertThat(result.toString()).isEqualTo("2015-02-20T06:30+02:00");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.baeldung.datetime;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class UseToInstantUnitTest {
|
||||
|
||||
private UseToInstant subject = new UseToInstant();
|
||||
|
||||
@Test
|
||||
public void givenAGregorianCalenderDate_whenConvertingToLocalDate_thenAsExpected() {
|
||||
GregorianCalendar givenCalender = new GregorianCalendar(2018, Calendar.JULY, 28);
|
||||
|
||||
LocalDateTime localDateTime = subject.convertDateToLocalDate(givenCalender);
|
||||
|
||||
assertThat(localDateTime).isEqualTo("2018-07-28T00:00:00");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenADate_whenConvertingToLocalDate_thenAsExpected() {
|
||||
Date givenDate = new Date(1465817690000L);
|
||||
|
||||
LocalDateTime localDateTime = subject.convertDateToLocalDate(givenDate);
|
||||
|
||||
assertThat(localDateTime).isEqualTo("2016-06-13T13:34:50");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.baeldung.prototype;
|
||||
|
||||
public final class Position {
|
||||
|
||||
private final int x;
|
||||
private final int y;
|
||||
|
||||
public Position(int x, int y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public int getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + x;
|
||||
result = prime * result + y;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
Position other = (Position) obj;
|
||||
if (x != other.x)
|
||||
return false;
|
||||
if (y != other.y)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Position [x=" + x + ", y=" + y + "]";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.baeldung.prototype;
|
||||
|
||||
public class Tree implements Cloneable {
|
||||
|
||||
private double mass;
|
||||
private double height;
|
||||
private Position position;
|
||||
|
||||
public Tree(double mass, double height) {
|
||||
this.mass = mass;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
public void setMass(double mass) {
|
||||
this.mass = mass;
|
||||
}
|
||||
|
||||
public void setHeight(double height) {
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
public void setPosition(Position position) {
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
public double getMass() {
|
||||
return mass;
|
||||
}
|
||||
|
||||
public double getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tree clone() {
|
||||
Tree tree = null;
|
||||
try {
|
||||
tree = (Tree) super.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return tree;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Tree [mass=" + mass + ", height=" + height + ", position=" + position + "]";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.baeldung.prototype;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class TreePrototypeUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenATreePrototypeWhenClonedThenCreateA_Clone() {
|
||||
double mass = 10.0;
|
||||
double height = 3.7;
|
||||
Position position = new Position(3, 7);
|
||||
Position otherPosition = new Position(4, 8);
|
||||
|
||||
Tree tree = new Tree(mass, height);
|
||||
tree.setPosition(position);
|
||||
Tree anotherTree = tree.clone();
|
||||
anotherTree.setPosition(otherPosition);
|
||||
|
||||
assertEquals(position, tree.getPosition());
|
||||
assertEquals(otherPosition, anotherTree.getPosition());
|
||||
}
|
||||
}
|
||||
37
persistence-modules/hibernate5-2/pom.xml
Normal file
37
persistence-modules/hibernate5-2/pom.xml
Normal file
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.0"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>hibernate5-2</artifactId>
|
||||
<version>0.1-SNAPSHOT</version>
|
||||
<name>hibernate5-2</name>
|
||||
<packaging>jar</packaging>
|
||||
<description>Hibernate tutorial illustrating the use of named parameters</description>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-modules</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<relativePath>../../</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-core</artifactId>
|
||||
<version>5.4.7.Final</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<version>1.4.200</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<maven.deploy.skip>true</maven.deploy.skip>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.baeldung.hibernateparameters;
|
||||
|
||||
public class Event {
|
||||
private Long id;
|
||||
|
||||
private String title;
|
||||
|
||||
public Event() {
|
||||
}
|
||||
|
||||
public Event(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
private void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE hibernate-mapping PUBLIC
|
||||
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
||||
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
||||
|
||||
<hibernate-mapping package="com.baeldung.hibernateparameters">
|
||||
|
||||
<class name="Event" table="EVENTS">
|
||||
<id name="id" column="EVENT_ID">
|
||||
<generator class="increment"/>
|
||||
</id>
|
||||
<property name="title"/>
|
||||
</class>
|
||||
|
||||
</hibernate-mapping>
|
||||
@@ -0,0 +1,28 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<!DOCTYPE hibernate-configuration PUBLIC
|
||||
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
|
||||
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
|
||||
|
||||
<hibernate-configuration>
|
||||
|
||||
<session-factory>
|
||||
<property name="connection.driver_class">org.h2.Driver</property>
|
||||
<property name="connection.url">jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1</property>
|
||||
<property name="connection.username">sa</property>
|
||||
<property name="connection.password"/>
|
||||
|
||||
<property name="connection.pool_size">1</property>
|
||||
|
||||
<property name="dialect">org.hibernate.dialect.H2Dialect</property>
|
||||
|
||||
<property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>
|
||||
|
||||
<property name="show_sql">true</property>
|
||||
|
||||
<property name="hbm2ddl.auto">create</property>
|
||||
|
||||
<mapping resource="com/baeldung/hibernateparameters/Event.hbm.xml"/>
|
||||
|
||||
</session-factory>
|
||||
|
||||
</hibernate-configuration>
|
||||
@@ -0,0 +1,73 @@
|
||||
package com.baeldung.hibernateparameters;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.boot.MetadataSources;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.query.Query;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
public class NamedParameterUnitTest {
|
||||
private SessionFactory sessionFactory;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
final StandardServiceRegistry registry = new StandardServiceRegistryBuilder()
|
||||
.configure()
|
||||
.build();
|
||||
try {
|
||||
sessionFactory = new MetadataSources(registry).buildMetadata().buildSessionFactory();
|
||||
Session session = sessionFactory.openSession();
|
||||
session.beginTransaction();
|
||||
session.save(new Event("Event 1"));
|
||||
session.save(new Event("Event 2"));
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
} catch (Exception e) {
|
||||
fail(e);
|
||||
StandardServiceRegistryBuilder.destroy(registry);
|
||||
}
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
if (sessionFactory != null) {
|
||||
sessionFactory.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenNamedParameterProvided_thenCorrect() {
|
||||
Session session = sessionFactory.openSession();
|
||||
session.beginTransaction();
|
||||
Query<Event> query = session.createQuery("from Event E WHERE E.title = :eventTitle", Event.class);
|
||||
|
||||
// This binds the value "Event1" to the parameter :eventTitle
|
||||
query.setParameter("eventTitle", "Event 1");
|
||||
|
||||
assertEquals(1, query.list().size());
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
}
|
||||
|
||||
@Test(expected = org.hibernate.QueryException.class)
|
||||
public void whenNamedParameterMissing_thenThrowsQueryException() {
|
||||
Session session = sessionFactory.openSession();
|
||||
session.beginTransaction();
|
||||
Query<Event> query = session.createQuery("from Event E WHERE E.title = :eventTitle", Event.class);
|
||||
|
||||
try {
|
||||
query.list();
|
||||
fail("We are expecting an exception!");
|
||||
} finally {
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>java-jpa-2</artifactId>
|
||||
@@ -49,6 +48,13 @@
|
||||
<version>${postgres.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<version>${assertj.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
@@ -108,6 +114,7 @@
|
||||
<eclipselink.version>2.7.4-RC1</eclipselink.version>
|
||||
<postgres.version>42.2.5</postgres.version>
|
||||
<javax.persistence-api.version>2.2</javax.persistence-api.version>
|
||||
<assertj.version>3.11.1</assertj.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,73 @@
|
||||
package com.baeldung.jpa.multipletables.multipleentities;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.OneToOne;
|
||||
import javax.persistence.PrimaryKeyJoinColumn;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import com.baeldung.jpa.multipletables.secondarytable.MealAsSingleEntity;
|
||||
|
||||
@Entity
|
||||
@Table(name = "allergens")
|
||||
public class AllergensAsEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "meal_id")
|
||||
private Long mealId;
|
||||
|
||||
@OneToOne
|
||||
@PrimaryKeyJoinColumn(name = "meal_id")
|
||||
private MealAsSingleEntity meal;
|
||||
|
||||
@Column(name = "peanuts")
|
||||
private boolean peanuts;
|
||||
|
||||
@Column(name = "celery")
|
||||
private boolean celery;
|
||||
|
||||
@Column(name = "sesame_seeds")
|
||||
private boolean sesameSeeds;
|
||||
|
||||
public MealAsSingleEntity getMeal() {
|
||||
return meal;
|
||||
}
|
||||
|
||||
public void setMeal(MealAsSingleEntity meal) {
|
||||
this.meal = meal;
|
||||
}
|
||||
|
||||
public boolean isPeanuts() {
|
||||
return peanuts;
|
||||
}
|
||||
|
||||
public void setPeanuts(boolean peanuts) {
|
||||
this.peanuts = peanuts;
|
||||
}
|
||||
|
||||
public boolean isCelery() {
|
||||
return celery;
|
||||
}
|
||||
|
||||
public void setCelery(boolean celery) {
|
||||
this.celery = celery;
|
||||
}
|
||||
|
||||
public boolean isSesameSeeds() {
|
||||
return sesameSeeds;
|
||||
}
|
||||
|
||||
public void setSesameSeeds(boolean sesameSeeds) {
|
||||
this.sesameSeeds = sesameSeeds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AllergensAsEntity [peanuts=" + peanuts + ", celery=" + celery + ", sesameSeeds=" + sesameSeeds + "]";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package com.baeldung.jpa.multipletables.multipleentities;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.OneToOne;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name = "meal")
|
||||
public class MealWithMultipleEntities {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id")
|
||||
private Long id;
|
||||
|
||||
@Column(name = "name")
|
||||
private String name;
|
||||
|
||||
@Column(name = "description")
|
||||
private String description;
|
||||
|
||||
@Column(name = "price")
|
||||
private BigDecimal price;
|
||||
|
||||
@OneToOne(mappedBy = "meal")
|
||||
private AllergensAsEntity allergens;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public BigDecimal getPrice() {
|
||||
return price;
|
||||
}
|
||||
|
||||
public void setPrice(BigDecimal price) {
|
||||
this.price = price;
|
||||
}
|
||||
|
||||
public AllergensAsEntity getAllergens() {
|
||||
return allergens;
|
||||
}
|
||||
|
||||
public void setAllergens(AllergensAsEntity allergens) {
|
||||
this.allergens = allergens;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MealWithMultipleEntities [id=" + id + ", name=" + name + ", description=" + description + ", price=" + price + ", allergens=" + allergens + "]";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package com.baeldung.jpa.multipletables.secondarytable;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.PrimaryKeyJoinColumn;
|
||||
import javax.persistence.SecondaryTable;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name = "meal")
|
||||
@SecondaryTable(name = "allergens", pkJoinColumns = @PrimaryKeyJoinColumn(name = "meal_id"))
|
||||
public class MealAsSingleEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id")
|
||||
private Long id;
|
||||
|
||||
@Column(name = "name")
|
||||
private String name;
|
||||
|
||||
@Column(name = "description")
|
||||
private String description;
|
||||
|
||||
@Column(name = "price")
|
||||
private BigDecimal price;
|
||||
|
||||
@Column(name = "peanuts", table = "allergens")
|
||||
private boolean peanuts;
|
||||
|
||||
@Column(name = "celery", table = "allergens")
|
||||
private boolean celery;
|
||||
|
||||
@Column(name = "sesame_seeds", table = "allergens")
|
||||
private boolean sesameSeeds;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public BigDecimal getPrice() {
|
||||
return price;
|
||||
}
|
||||
|
||||
public void setPrice(BigDecimal price) {
|
||||
this.price = price;
|
||||
}
|
||||
|
||||
public boolean isPeanuts() {
|
||||
return peanuts;
|
||||
}
|
||||
|
||||
public void setPeanuts(boolean peanuts) {
|
||||
this.peanuts = peanuts;
|
||||
}
|
||||
|
||||
public boolean isCelery() {
|
||||
return celery;
|
||||
}
|
||||
|
||||
public void setCelery(boolean celery) {
|
||||
this.celery = celery;
|
||||
}
|
||||
|
||||
public boolean isSesameSeeds() {
|
||||
return sesameSeeds;
|
||||
}
|
||||
|
||||
public void setSesameSeeds(boolean sesameSeeds) {
|
||||
this.sesameSeeds = sesameSeeds;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MealAsSingleEntity [id=" + id + ", name=" + name + ", description=" + description + ", price=" + price + ", peanuts=" + peanuts + ", celery=" + celery + ", sesameSeeds=" + sesameSeeds + "]";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.baeldung.jpa.multipletables.secondarytable.embeddable;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Embeddable;
|
||||
|
||||
@Embeddable
|
||||
public class AllergensAsEmbeddable {
|
||||
|
||||
@Column(name = "peanuts", table = "allergens")
|
||||
private boolean peanuts;
|
||||
|
||||
@Column(name = "celery", table = "allergens")
|
||||
private boolean celery;
|
||||
|
||||
@Column(name = "sesame_seeds", table = "allergens")
|
||||
private boolean sesameSeeds;
|
||||
|
||||
public boolean isPeanuts() {
|
||||
return peanuts;
|
||||
}
|
||||
|
||||
public void setPeanuts(boolean peanuts) {
|
||||
this.peanuts = peanuts;
|
||||
}
|
||||
|
||||
public boolean isCelery() {
|
||||
return celery;
|
||||
}
|
||||
|
||||
public void setCelery(boolean celery) {
|
||||
this.celery = celery;
|
||||
}
|
||||
|
||||
public boolean isSesameSeeds() {
|
||||
return sesameSeeds;
|
||||
}
|
||||
|
||||
public void setSesameSeeds(boolean sesameSeeds) {
|
||||
this.sesameSeeds = sesameSeeds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AllergensAsEmbeddable [peanuts=" + peanuts + ", celery=" + celery + ", sesameSeeds=" + sesameSeeds + "]";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package com.baeldung.jpa.multipletables.secondarytable.embeddable;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Embedded;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.PrimaryKeyJoinColumn;
|
||||
import javax.persistence.SecondaryTable;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name = "meal")
|
||||
@SecondaryTable(name = "allergens", pkJoinColumns = @PrimaryKeyJoinColumn(name = "meal_id"))
|
||||
public class MealWithEmbeddedAllergens {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id")
|
||||
private Long id;
|
||||
|
||||
@Column(name = "name")
|
||||
private String name;
|
||||
|
||||
@Column(name = "description")
|
||||
private String description;
|
||||
|
||||
@Column(name = "price")
|
||||
private BigDecimal price;
|
||||
|
||||
@Embedded
|
||||
private AllergensAsEmbeddable allergens;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public BigDecimal getPrice() {
|
||||
return price;
|
||||
}
|
||||
|
||||
public void setPrice(BigDecimal price) {
|
||||
this.price = price;
|
||||
}
|
||||
|
||||
public AllergensAsEmbeddable getAllergens() {
|
||||
return allergens;
|
||||
}
|
||||
|
||||
public void setAllergens(AllergensAsEmbeddable allergens) {
|
||||
this.allergens = allergens;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MealWithEmbeddedAllergens [id=" + id + ", name=" + name + ", description=" + description + ", price=" + price + ", allergens=" + allergens + "]";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -135,4 +135,32 @@
|
||||
</properties>
|
||||
</persistence-unit>
|
||||
|
||||
<persistence-unit name="jpa-h2-multipltables">
|
||||
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
|
||||
<class>com.baeldung.jpa.multipletables.multipleentities.MealWithMultipleEntities</class>
|
||||
<class>com.baeldung.jpa.multipletables.multipleentities.AllergensAsEntity</class>
|
||||
|
||||
<class>com.baeldung.jpa.multipletables.secondarytable.MealAsSingleEntity</class>
|
||||
|
||||
<class>com.baeldung.jpa.multipletables.secondarytable.embeddable.MealWithEmbeddedAllergens</class>
|
||||
<class>com.baeldung.jpa.multipletables.secondarytable.embeddable.AllergensAsEmbeddable</class>
|
||||
|
||||
<exclude-unlisted-classes>true</exclude-unlisted-classes>
|
||||
<properties>
|
||||
<property name="javax.persistence.jdbc.driver"
|
||||
value="org.h2.Driver" />
|
||||
<property name="javax.persistence.jdbc.url"
|
||||
value="jdbc:h2:mem:test" />
|
||||
<property name="javax.persistence.jdbc.user" value="sa" />
|
||||
<property name="javax.persistence.jdbc.password" value="" />
|
||||
<property name="hibernate.dialect"
|
||||
value="org.hibernate.dialect.H2Dialect" />
|
||||
<property name="hibernate.hbm2ddl.auto" value="create" />
|
||||
<property name="hibernate.hbm2ddl.import_files" value="multipletables.sql" />
|
||||
<property name="show_sql" value="true" />
|
||||
<property name="hibernate.temp.use_jdbc_metadata_defaults"
|
||||
value="false" />
|
||||
</properties>
|
||||
</persistence-unit>
|
||||
|
||||
</persistence>
|
||||
@@ -0,0 +1,79 @@
|
||||
package com.baeldung.jpa.multipletables;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.persistence.Persistence;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.baeldung.jpa.multipletables.multipleentities.MealWithMultipleEntities;
|
||||
import com.baeldung.jpa.multipletables.secondarytable.MealAsSingleEntity;
|
||||
import com.baeldung.jpa.multipletables.secondarytable.embeddable.MealWithEmbeddedAllergens;
|
||||
|
||||
public class MultipleTablesIntegrationTest {
|
||||
|
||||
private static EntityManagerFactory emf;
|
||||
private static EntityManager em;
|
||||
|
||||
@BeforeClass
|
||||
public static void setup() {
|
||||
emf = Persistence.createEntityManagerFactory("jpa-h2-multipltables");
|
||||
em = emf.createEntityManager();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void entityManager_shouldLoadMealAsSingleEntity() {
|
||||
// given
|
||||
|
||||
// when
|
||||
MealAsSingleEntity meal = em.find(MealAsSingleEntity.class, 1L);
|
||||
|
||||
// then
|
||||
assertThat(meal).isNotNull();
|
||||
assertThat(meal.getId()).isEqualTo(1L);
|
||||
assertThat(meal.isPeanuts()).isFalse();
|
||||
assertThat(meal.isCelery()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void entityManager_shouldLoadMealWithEmbeddedAllergens() {
|
||||
// given
|
||||
|
||||
// when
|
||||
MealWithEmbeddedAllergens meal = em.find(MealWithEmbeddedAllergens.class, 1L);
|
||||
|
||||
// then
|
||||
assertThat(meal).isNotNull();
|
||||
assertThat(meal.getId()).isEqualTo(1L);
|
||||
assertThat(meal.getAllergens()).isNotNull();
|
||||
assertThat(meal.getAllergens().isPeanuts()).isFalse();
|
||||
assertThat(meal.getAllergens().isCelery()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void entityManager_shouldLoadMealWithAllergensEntity() {
|
||||
// given
|
||||
|
||||
// when
|
||||
MealWithMultipleEntities meal = em.find(MealWithMultipleEntities.class, 1L);
|
||||
|
||||
// then
|
||||
assertThat(meal).isNotNull();
|
||||
assertThat(meal.getId()).isEqualTo(1L);
|
||||
assertThat(meal.getAllergens()).isNotNull();
|
||||
assertThat(meal.getAllergens().isPeanuts()).isFalse();
|
||||
assertThat(meal.getAllergens().isCelery()).isTrue();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void teardown() {
|
||||
if (emf != null) {
|
||||
emf.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
drop table if exists allergens;
|
||||
drop table if exists meal;
|
||||
|
||||
create table meal (id bigint auto_increment, name varchar(255) not null, description varchar(255) not null, price decimal(19, 2) not null, primary key (id));
|
||||
create table allergens (meal_id bigint auto_increment, peanuts number(1) not null, celery number(1) not null, sesame_seeds number(1) not null, primary key (meal_id));
|
||||
|
||||
insert into meal (id, name, description, price) values (1, 'Pizza', 'Delicious', 5);
|
||||
insert into allergens (meal_id, peanuts, celery, sesame_seeds) values (1, 0, 1, 0);
|
||||
@@ -23,7 +23,7 @@
|
||||
<module>hibernate5</module>
|
||||
<module>hibernate-ogm</module>
|
||||
<module>hibernate-mapping</module>
|
||||
<module>hibernate-parameters</module>
|
||||
<module>hibernate5-2</module>
|
||||
<module>influxdb</module>
|
||||
<module>java-cassandra</module>
|
||||
<module>java-cockroachdb</module>
|
||||
@@ -49,6 +49,7 @@
|
||||
<module>spring-data-elasticsearch</module>
|
||||
<module>spring-data-gemfire</module>
|
||||
<module>spring-data-jpa</module>
|
||||
<module>spring-data-jpa-3</module>
|
||||
<module>spring-data-keyvalue</module>
|
||||
<module>spring-data-mongodb</module> <!-- long -->
|
||||
<module>spring-data-neo4j</module>
|
||||
@@ -60,7 +61,7 @@
|
||||
<module>spring-jpa</module>
|
||||
<module>spring-persistence-simple</module>
|
||||
<module>jpa-hibernate-cascade-type</module>
|
||||
<module>r2dbc</module>
|
||||
<module>r2dbc</module>
|
||||
<module>spring-boot-jdbi</module>
|
||||
</modules>
|
||||
</project>
|
||||
|
||||
78
persistence-modules/spring-data-jpa-3/pom.xml
Normal file
78
persistence-modules/spring-data-jpa-3/pom.xml
Normal file
@@ -0,0 +1,78 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
|
||||
http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>spring-data-jpa-3</artifactId>
|
||||
<name>spring-data-jpa-3</name>
|
||||
|
||||
<parent>
|
||||
<artifactId>parent-boot-2</artifactId>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../../parent-boot-2</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- Prod Dependencies -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>${postgresql.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Test Dependencies -->
|
||||
<dependency>
|
||||
<groupId>org.testcontainers</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<version>${testcontainers.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.testcontainers</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>${testcontainers.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.platform</groupId>
|
||||
<artifactId>junit-platform-launcher</artifactId>
|
||||
<version>${junit-platform.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<testcontainers.version>1.12.2</testcontainers.version>
|
||||
<postgresql.version>42.2.8</postgresql.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.baeldung;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class Application {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.baeldung.tx;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
||||
@Entity
|
||||
public class Payment {
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
|
||||
private Long amount;
|
||||
|
||||
@Column(unique = true)
|
||||
private String referenceNumber;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
private State state;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Long getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
public void setAmount(Long amount) {
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
public String getReferenceNumber() {
|
||||
return referenceNumber;
|
||||
}
|
||||
|
||||
public void setReferenceNumber(String referenceNumber) {
|
||||
this.referenceNumber = referenceNumber;
|
||||
}
|
||||
|
||||
public State getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
public void setState(State state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public enum State {
|
||||
STARTED, FAILED, SUCCESSFUL
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
package com.baeldung.tx;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
|
||||
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.transaction.support.DefaultTransactionDefinition;
|
||||
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
import org.testcontainers.containers.PostgreSQLContainer;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
import static java.util.Collections.singletonList;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase.Replace.NONE;
|
||||
import static org.springframework.transaction.annotation.Propagation.NOT_SUPPORTED;
|
||||
|
||||
@DataJpaTest
|
||||
@Testcontainers
|
||||
@ActiveProfiles("test")
|
||||
@AutoConfigureTestDatabase(replace = NONE)
|
||||
@Transactional(propagation = NOT_SUPPORTED)
|
||||
class ManualTransactionIntegrationTest {
|
||||
|
||||
@Container
|
||||
private static PostgreSQLContainer<?> pg = initPostgres();
|
||||
|
||||
@Autowired
|
||||
private PlatformTransactionManager transactionManager;
|
||||
|
||||
@Autowired
|
||||
private EntityManager entityManager;
|
||||
|
||||
private TransactionTemplate transactionTemplate;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
transactionTemplate = new TransactionTemplate(transactionManager);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void flushDb() {
|
||||
transactionTemplate.execute(status -> entityManager
|
||||
.createQuery("delete from Payment")
|
||||
.executeUpdate());
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenAPayment_WhenNotDuplicate_ThenShouldCommit() {
|
||||
Long id = transactionTemplate.execute(status -> {
|
||||
Payment payment = new Payment();
|
||||
payment.setAmount(1000L);
|
||||
payment.setReferenceNumber("Ref-1");
|
||||
payment.setState(Payment.State.SUCCESSFUL);
|
||||
|
||||
entityManager.persist(payment);
|
||||
|
||||
return payment.getId();
|
||||
});
|
||||
|
||||
Payment payment = entityManager.find(Payment.class, id);
|
||||
assertThat(payment).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenAPayment_WhenMarkAsRollback_ThenShouldRollback() {
|
||||
transactionTemplate.execute(status -> {
|
||||
Payment payment = new Payment();
|
||||
payment.setAmount(1000L);
|
||||
payment.setReferenceNumber("Ref-1");
|
||||
payment.setState(Payment.State.SUCCESSFUL);
|
||||
|
||||
entityManager.persist(payment);
|
||||
status.setRollbackOnly();
|
||||
|
||||
return payment.getId();
|
||||
});
|
||||
|
||||
assertThat(entityManager
|
||||
.createQuery("select p from Payment p")
|
||||
.getResultList()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenTwoPayments_WhenRefIsDuplicate_ThenShouldRollback() {
|
||||
try {
|
||||
transactionTemplate.execute(s -> {
|
||||
Payment first = new Payment();
|
||||
first.setAmount(1000L);
|
||||
first.setReferenceNumber("Ref-1");
|
||||
first.setState(Payment.State.SUCCESSFUL);
|
||||
|
||||
Payment second = new Payment();
|
||||
second.setAmount(2000L);
|
||||
second.setReferenceNumber("Ref-1");
|
||||
second.setState(Payment.State.SUCCESSFUL);
|
||||
|
||||
entityManager.persist(first);
|
||||
entityManager.persist(second);
|
||||
|
||||
return "Ref-1";
|
||||
});
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
|
||||
assertThat(entityManager
|
||||
.createQuery("select p from Payment p")
|
||||
.getResultList()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenAPayment_WhenNotExpectingAnyResult_ThenShouldCommit() {
|
||||
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
|
||||
@Override
|
||||
protected void doInTransactionWithoutResult(TransactionStatus status) {
|
||||
Payment payment = new Payment();
|
||||
payment.setReferenceNumber("Ref-1");
|
||||
payment.setState(Payment.State.SUCCESSFUL);
|
||||
|
||||
entityManager.persist(payment);
|
||||
}
|
||||
});
|
||||
|
||||
assertThat(entityManager
|
||||
.createQuery("select p from Payment p")
|
||||
.getResultList()).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenAPayment_WhenUsingTxManager_ThenShouldCommit() {
|
||||
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
|
||||
definition.setIsolationLevel(TransactionDefinition.ISOLATION_REPEATABLE_READ);
|
||||
definition.setTimeout(3);
|
||||
|
||||
TransactionStatus status = transactionManager.getTransaction(definition);
|
||||
try {
|
||||
Payment payment = new Payment();
|
||||
payment.setReferenceNumber("Ref-1");
|
||||
payment.setState(Payment.State.SUCCESSFUL);
|
||||
|
||||
entityManager.persist(payment);
|
||||
transactionManager.commit(status);
|
||||
} catch (Exception ex) {
|
||||
transactionManager.rollback(status);
|
||||
}
|
||||
|
||||
assertThat(entityManager
|
||||
.createQuery("select p from Payment p")
|
||||
.getResultList()).hasSize(1);
|
||||
}
|
||||
|
||||
private static PostgreSQLContainer<?> initPostgres() {
|
||||
PostgreSQLContainer<?> pg = new PostgreSQLContainer<>("postgres:11.1")
|
||||
.withDatabaseName("baeldung")
|
||||
.withUsername("test")
|
||||
.withPassword("test");
|
||||
pg.setPortBindings(singletonList("54320:5432"));
|
||||
|
||||
return pg;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
spring.jpa.hibernate.ddl-auto=update
|
||||
spring.datasource.url=jdbc:postgresql://localhost:54320/baeldung
|
||||
spring.datasource.username=test
|
||||
spring.datasource.password=test
|
||||
@@ -0,0 +1,250 @@
|
||||
package com.baeldung.persistence.service.transactional;
|
||||
|
||||
import com.baeldung.persistence.model.Foo;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.PersistenceContext;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.support.AnnotationConfigContextLoader;
|
||||
import org.springframework.transaction.IllegalTransactionStateException;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(classes = { PersistenceTransactionalTestConfig.class }, loader = AnnotationConfigContextLoader.class)
|
||||
@DirtiesContext
|
||||
public class FooTransactionalUnitTest {
|
||||
|
||||
static abstract class BasicFooDao {
|
||||
@PersistenceContext private EntityManager entityManager;
|
||||
|
||||
public Foo findOne(final long id) {
|
||||
return entityManager.find(Foo.class, id);
|
||||
}
|
||||
|
||||
public Foo create(final Foo entity) {
|
||||
entityManager.persist(entity);
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
|
||||
@Repository
|
||||
static class RequiredTransactionalFooDao extends BasicFooDao {
|
||||
@Override
|
||||
@Transactional(propagation = Propagation.REQUIRED)
|
||||
public Foo create(Foo entity) {
|
||||
return super.create(entity);
|
||||
}
|
||||
}
|
||||
|
||||
@Repository
|
||||
static class RequiresNewTransactionalFooDao extends BasicFooDao {
|
||||
@Override
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
public Foo create(Foo entity) {
|
||||
return super.create(entity);
|
||||
}
|
||||
}
|
||||
|
||||
@Repository
|
||||
static class SupportTransactionalFooDao extends BasicFooDao {
|
||||
@Override
|
||||
@Transactional(propagation = Propagation.SUPPORTS)
|
||||
public Foo create(Foo entity) {
|
||||
return super.create(entity);
|
||||
}
|
||||
}
|
||||
|
||||
@Repository
|
||||
static class MandatoryTransactionalFooDao extends BasicFooDao {
|
||||
@Override
|
||||
@Transactional(propagation = Propagation.MANDATORY)
|
||||
public Foo create(Foo entity) {
|
||||
return super.create(entity);
|
||||
}
|
||||
}
|
||||
|
||||
@Repository
|
||||
static class SupportTransactionalFooService {
|
||||
@Transactional(propagation = Propagation.SUPPORTS)
|
||||
public Foo identity(Foo entity) {
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
|
||||
@Service
|
||||
static class MandatoryTransactionalFooService {
|
||||
@Transactional(propagation = Propagation.MANDATORY)
|
||||
public Foo identity(Foo entity) {
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
|
||||
@Service
|
||||
static class NotSupportedTransactionalFooService {
|
||||
@Transactional(propagation = Propagation.NOT_SUPPORTED)
|
||||
public Foo identity(Foo entity) {
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
|
||||
@Service
|
||||
static class NeverTransactionalFooService {
|
||||
@Transactional(propagation = Propagation.NEVER)
|
||||
public Foo identity(Foo entity) {
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
|
||||
@Autowired private TransactionTemplate transactionTemplate;
|
||||
|
||||
@Autowired private RequiredTransactionalFooDao requiredTransactionalFooDao;
|
||||
|
||||
@Autowired private RequiresNewTransactionalFooDao requiresNewTransactionalFooDao;
|
||||
|
||||
@Autowired private SupportTransactionalFooDao supportTransactionalFooDao;
|
||||
|
||||
@Autowired private MandatoryTransactionalFooDao mandatoryTransactionalFooDao;
|
||||
|
||||
@Autowired private MandatoryTransactionalFooService mandatoryTransactionalFooService;
|
||||
|
||||
@Autowired private NeverTransactionalFooService neverTransactionalFooService;
|
||||
|
||||
@Autowired private NotSupportedTransactionalFooService notSupportedTransactionalFooService;
|
||||
|
||||
@Autowired private SupportTransactionalFooService supportTransactionalFooService;
|
||||
|
||||
@After
|
||||
public void tearDown(){
|
||||
PersistenceTransactionalTestConfig.clearSpy();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenRequiredWithNoActiveTransaction_whenCallCreate_thenExpect1NewAnd0Suspend() {
|
||||
requiredTransactionalFooDao.create(new Foo("baeldung"));
|
||||
PersistenceTransactionalTestConfig.TransactionSynchronizationAdapterSpy transactionSpy = PersistenceTransactionalTestConfig.getSpy();
|
||||
Assert.assertEquals(0, transactionSpy.getSuspend());
|
||||
Assert.assertEquals(1, transactionSpy.getCreate());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void givenRequiresNewWithNoActiveTransaction_whenCallCreate_thenExpect1NewAnd0Suspend() {
|
||||
requiresNewTransactionalFooDao.create(new Foo("baeldung"));
|
||||
PersistenceTransactionalTestConfig.TransactionSynchronizationAdapterSpy transactionSpy = PersistenceTransactionalTestConfig.getSpy();
|
||||
Assert.assertEquals(0, transactionSpy.getSuspend());
|
||||
Assert.assertEquals(1, transactionSpy.getCreate());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenSupportWithNoActiveTransaction_whenCallService_thenExpect0NewAnd0Suspend() {
|
||||
supportTransactionalFooService.identity(new Foo("baeldung"));
|
||||
PersistenceTransactionalTestConfig.TransactionSynchronizationAdapterSpy transactionSpy = PersistenceTransactionalTestConfig.getSpy();
|
||||
Assert.assertEquals(0, transactionSpy.getSuspend());
|
||||
Assert.assertEquals(0, transactionSpy.getCreate());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalTransactionStateException.class)
|
||||
public void givenMandatoryWithNoActiveTransaction_whenCallService_thenExpectIllegalTransactionStateExceptionWith0NewAnd0Suspend() {
|
||||
mandatoryTransactionalFooService.identity(new Foo("baeldung"));
|
||||
PersistenceTransactionalTestConfig.TransactionSynchronizationAdapterSpy transactionSpy = PersistenceTransactionalTestConfig.getSpy();
|
||||
Assert.assertEquals(0, transactionSpy.getSuspend());
|
||||
Assert.assertEquals(0, transactionSpy.getCreate());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenNotSupportWithNoActiveTransaction_whenCallService_thenExpect0NewAnd0Suspend() {
|
||||
notSupportedTransactionalFooService.identity(new Foo("baeldung"));
|
||||
PersistenceTransactionalTestConfig.TransactionSynchronizationAdapterSpy transactionSpy = PersistenceTransactionalTestConfig.getSpy();
|
||||
Assert.assertEquals(0, transactionSpy.getSuspend());
|
||||
Assert.assertEquals(0, transactionSpy.getCreate());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenNeverWithNoActiveTransaction_whenCallService_thenExpect0NewAnd0Suspend() {
|
||||
neverTransactionalFooService.identity(new Foo("baeldung"));
|
||||
PersistenceTransactionalTestConfig.TransactionSynchronizationAdapterSpy transactionSpy = PersistenceTransactionalTestConfig.getSpy();
|
||||
Assert.assertEquals(0, transactionSpy.getSuspend());
|
||||
Assert.assertEquals(0, transactionSpy.getCreate());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenRequiredWithActiveTransaction_whenCallCreate_thenExpect0NewAnd0Suspend() {
|
||||
transactionTemplate.execute(status -> {
|
||||
Foo foo = new Foo("baeldung");
|
||||
return requiredTransactionalFooDao.create(foo);
|
||||
});
|
||||
PersistenceTransactionalTestConfig.TransactionSynchronizationAdapterSpy transactionSpy = PersistenceTransactionalTestConfig.getSpy();
|
||||
Assert.assertEquals(0, transactionSpy.getSuspend());
|
||||
Assert.assertEquals(1, transactionSpy.getCreate());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenRequiresNewWithActiveTransaction_whenCallCreate_thenExpect1NewAnd1Suspend() {
|
||||
transactionTemplate.execute(status -> {
|
||||
Foo foo = new Foo("baeldung");
|
||||
return requiresNewTransactionalFooDao.create(foo);
|
||||
});
|
||||
PersistenceTransactionalTestConfig.TransactionSynchronizationAdapterSpy transactionSpy = PersistenceTransactionalTestConfig.getSpy();
|
||||
Assert.assertEquals(1, transactionSpy.getSuspend());
|
||||
Assert.assertEquals(2, transactionSpy.getCreate());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenSupportWithActiveTransaction_whenCallCreate_thenExpect0NewAnd0Suspend() {
|
||||
transactionTemplate.execute(status -> {
|
||||
Foo foo = new Foo("baeldung");
|
||||
return supportTransactionalFooDao.create(foo);
|
||||
});
|
||||
PersistenceTransactionalTestConfig.TransactionSynchronizationAdapterSpy transactionSpy = PersistenceTransactionalTestConfig.getSpy();
|
||||
Assert.assertEquals(0, transactionSpy.getSuspend());
|
||||
Assert.assertEquals(1, transactionSpy.getCreate());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenMandatoryWithActiveTransaction_whenCallCreate_thenExpect0NewAnd0Suspend() {
|
||||
|
||||
transactionTemplate.execute(status -> {
|
||||
Foo foo = new Foo("baeldung");
|
||||
return mandatoryTransactionalFooDao.create(foo);
|
||||
});
|
||||
|
||||
PersistenceTransactionalTestConfig.TransactionSynchronizationAdapterSpy transactionSpy = PersistenceTransactionalTestConfig.getSpy();
|
||||
Assert.assertEquals(0, transactionSpy.getSuspend());
|
||||
Assert.assertEquals(1, transactionSpy.getCreate());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenNotSupportWithActiveTransaction_whenCallCreate_thenExpect0NewAnd1Suspend() {
|
||||
transactionTemplate.execute(status -> {
|
||||
Foo foo = new Foo("baeldung");
|
||||
return notSupportedTransactionalFooService.identity(foo);
|
||||
});
|
||||
|
||||
PersistenceTransactionalTestConfig.TransactionSynchronizationAdapterSpy transactionSpy = PersistenceTransactionalTestConfig.getSpy();
|
||||
Assert.assertEquals(1, transactionSpy.getSuspend());
|
||||
Assert.assertEquals(1, transactionSpy.getCreate());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalTransactionStateException.class)
|
||||
public void givenNeverWithActiveTransaction_whenCallCreate_thenExpectIllegalTransactionStateExceptionWith0NewAnd0Suspend() {
|
||||
transactionTemplate.execute(status -> {
|
||||
Foo foo = new Foo("baeldung");
|
||||
return neverTransactionalFooService.identity(foo);
|
||||
});
|
||||
PersistenceTransactionalTestConfig.TransactionSynchronizationAdapterSpy transactionSpy = PersistenceTransactionalTestConfig.getSpy();
|
||||
Assert.assertEquals(0, transactionSpy.getSuspend());
|
||||
Assert.assertEquals(1, transactionSpy.getCreate());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
package com.baeldung.persistence.service.transactional;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import java.util.Properties;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.sql.DataSource;
|
||||
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.EnableJpaRepositories;
|
||||
import org.springframework.jdbc.datasource.DriverManagerDataSource;
|
||||
import org.springframework.orm.jpa.JpaTransactionManager;
|
||||
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
import org.springframework.transaction.support.DefaultTransactionStatus;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
@Configuration
|
||||
@EnableTransactionManagement
|
||||
@PropertySource({ "classpath:persistence-h2.properties" })
|
||||
@ComponentScan({ "com.baeldung.persistence","com.baeldung.jpa.dao" })
|
||||
@EnableJpaRepositories(basePackages = "com.baeldung.jpa.dao")
|
||||
public class PersistenceTransactionalTestConfig {
|
||||
|
||||
public static class TransactionSynchronizationAdapterSpy extends TransactionSynchronizationAdapter {
|
||||
private int create, suspend;
|
||||
|
||||
public int getSuspend() {
|
||||
return suspend;
|
||||
}
|
||||
|
||||
public int getCreate() {
|
||||
return create;
|
||||
}
|
||||
|
||||
public void create() {
|
||||
create++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suspend() {
|
||||
suspend++;
|
||||
super.suspend();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class JpaTransactionManagerSpy extends JpaTransactionManager {
|
||||
@Override
|
||||
protected void prepareSynchronization(DefaultTransactionStatus status, TransactionDefinition definition) {
|
||||
super.prepareSynchronization(status, definition);
|
||||
if (status.isNewTransaction()) {
|
||||
if ( adapterSpyThreadLocal.get() == null ){
|
||||
TransactionSynchronizationAdapterSpy spy = new TransactionSynchronizationAdapterSpy();
|
||||
TransactionSynchronizationManager.registerSynchronization(spy);
|
||||
adapterSpyThreadLocal.set(spy);
|
||||
}
|
||||
adapterSpyThreadLocal.get().create();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static ThreadLocal<TransactionSynchronizationAdapterSpy> adapterSpyThreadLocal = new ThreadLocal<>();
|
||||
|
||||
@Autowired
|
||||
private Environment env;
|
||||
|
||||
public PersistenceTransactionalTestConfig() {
|
||||
super();
|
||||
}
|
||||
|
||||
public static TransactionSynchronizationAdapterSpy getSpy(){
|
||||
if ( adapterSpyThreadLocal.get() == null )
|
||||
return new TransactionSynchronizationAdapterSpy();
|
||||
return adapterSpyThreadLocal.get();
|
||||
}
|
||||
|
||||
public static void clearSpy(){
|
||||
adapterSpyThreadLocal.set(null);
|
||||
}
|
||||
|
||||
// beans
|
||||
|
||||
@Bean
|
||||
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean() {
|
||||
final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
|
||||
em.setDataSource(dataSource());
|
||||
em.setPackagesToScan(new String[] { "com.baeldung.persistence.model" });
|
||||
|
||||
final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
|
||||
em.setJpaVendorAdapter(vendorAdapter);
|
||||
em.setJpaProperties(additionalProperties());
|
||||
|
||||
return em;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DataSource dataSource() {
|
||||
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
|
||||
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 transactionManager(final EntityManagerFactory emf) {
|
||||
final JpaTransactionManagerSpy transactionManager = new JpaTransactionManagerSpy();
|
||||
transactionManager.setEntityManagerFactory(emf);
|
||||
return transactionManager;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
|
||||
return new PersistenceExceptionTranslationPostProcessor();
|
||||
}
|
||||
|
||||
final Properties additionalProperties() {
|
||||
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.cache.use_second_level_cache", "false");
|
||||
return hibernateProperties;
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public TransactionTemplate transactionTemplate(PlatformTransactionManager transactionManager){
|
||||
TransactionTemplate template = new TransactionTemplate(transactionManager);
|
||||
template.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
return template;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -25,7 +25,7 @@
|
||||
<module>spring-cloud-zookeeper</module>
|
||||
<module>spring-cloud-gateway</module>
|
||||
<module>spring-cloud-stream</module>
|
||||
<module>spring-cloud-stream-starters/twitterhdfs</module>
|
||||
<module>spring-cloud-stream-starters/twitterhdfs</module>
|
||||
<module>spring-cloud-connectors-heroku</module>
|
||||
<module>spring-cloud-aws</module>
|
||||
<module>spring-cloud-consul</module>
|
||||
@@ -35,9 +35,10 @@
|
||||
<module>spring-cloud-archaius</module>
|
||||
<module>spring-cloud-functions</module>
|
||||
<module>spring-cloud-vault</module>
|
||||
<!-- <module>spring-cloud-security</module> --> <!-- Fixing in BAEL-10887 -->
|
||||
<module>spring-cloud-task</module>
|
||||
<!-- <module>spring-cloud-security</module> --> <!-- Fixing in BAEL-10887 -->
|
||||
<module>spring-cloud-task</module>
|
||||
<module>spring-cloud-zuul</module>
|
||||
<module>spring-cloud-zuul-fallback</module>
|
||||
</modules>
|
||||
|
||||
<build>
|
||||
|
||||
2
spring-cloud/spring-cloud-zuul-fallback/README.md
Normal file
2
spring-cloud/spring-cloud-zuul-fallback/README.md
Normal file
@@ -0,0 +1,2 @@
|
||||
### Relevant Articles:
|
||||
- [Fallback for Zuul Route](TODO)
|
||||
43
spring-cloud/spring-cloud-zuul-fallback/api-gateway/pom.xml
Normal file
43
spring-cloud/spring-cloud-zuul-fallback/api-gateway/pom.xml
Normal file
@@ -0,0 +1,43 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>api-gateway</artifactId>
|
||||
<name>api-gateway</name>
|
||||
<description>API Gateway using Zuul</description>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung.spring.cloud</groupId>
|
||||
<artifactId>spring-cloud-zuul-fallback</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-parent</artifactId>
|
||||
<version>${spring-cloud-dependencies.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
</project>
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.baeldung.spring.cloud.apigateway;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableZuulProxy
|
||||
public class ApiGatewayApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(ApiGatewayApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.baeldung.spring.cloud.apigateway.fallback;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
|
||||
public class GatewayClientResponse implements ClientHttpResponse {
|
||||
|
||||
private HttpStatus status;
|
||||
private String message;
|
||||
|
||||
public GatewayClientResponse(HttpStatus status, String message) {
|
||||
this.status = status;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpStatus getStatusCode() throws IOException {
|
||||
return status;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRawStatusCode() throws IOException {
|
||||
return status.value();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStatusText() throws IOException {
|
||||
return status.getReasonPhrase();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getBody() throws IOException {
|
||||
return new ByteArrayInputStream(message.getBytes());
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpHeaders getHeaders() {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
return headers;
|
||||
}
|
||||
|
||||
public HttpStatus getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(HttpStatus status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.baeldung.spring.cloud.apigateway.fallback;
|
||||
|
||||
import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.netflix.hystrix.exception.HystrixTimeoutException;
|
||||
|
||||
@Component
|
||||
class GatewayServiceFallback implements FallbackProvider {
|
||||
|
||||
private static final String DEFAULT_MESSAGE = "Service not available.";
|
||||
|
||||
@Override
|
||||
public String getRoute() {
|
||||
return "*"; // or return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
|
||||
if (cause instanceof HystrixTimeoutException) {
|
||||
return new GatewayClientResponse(HttpStatus.GATEWAY_TIMEOUT, DEFAULT_MESSAGE);
|
||||
} else {
|
||||
return new GatewayClientResponse(HttpStatus.INTERNAL_SERVER_ERROR, DEFAULT_MESSAGE);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user