diff --git a/persistence-modules/hibernate-types/.gitignore b/persistence-modules/hibernate-types/.gitignore
new file mode 100644
index 0000000000..94b9c48616
--- /dev/null
+++ b/persistence-modules/hibernate-types/.gitignore
@@ -0,0 +1,33 @@
+.classpath
+.project
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**
+!**/src/test/**
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+
+### VS Code ###
+.vscode/
diff --git a/persistence-modules/hibernate-types/README.md b/persistence-modules/hibernate-types/README.md
new file mode 100644
index 0000000000..9d02d8c8f2
--- /dev/null
+++ b/persistence-modules/hibernate-types/README.md
@@ -0,0 +1,7 @@
+## Hibernate Types
+
+This module contains articles specific to use of Hibernate Types.
+
+### Relevant articles:
+
+- [A Guide to Hibernate Types Project](https://www.baeldung.com/a-guide-to-hibernate-types-project/)
diff --git a/persistence-modules/hibernate-types/docker-compose.yml b/persistence-modules/hibernate-types/docker-compose.yml
new file mode 100644
index 0000000000..3ea9fef2e7
--- /dev/null
+++ b/persistence-modules/hibernate-types/docker-compose.yml
@@ -0,0 +1,19 @@
+version: '3.2'
+
+services:
+ mysql:
+ image: mysql:5.7
+ container_name: mysql57
+ restart: unless-stopped
+ ports:
+ - 53306:3306
+ environment:
+ - MYSQL_ALLOW_EMPTY_PASSWORD=true
+ volumes :
+ - ./docker/etc/mysql/conf.d:/etc/mysql/conf.d
+ - ./docker/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
+ logging:
+ driver: "json-file"
+ options:
+ max-size: "50m"
+ max-file: "1"
diff --git a/persistence-modules/hibernate-types/docker/docker-entrypoint-initdb.d/init-db.sql b/persistence-modules/hibernate-types/docker/docker-entrypoint-initdb.d/init-db.sql
new file mode 100644
index 0000000000..1df234f5a1
--- /dev/null
+++ b/persistence-modules/hibernate-types/docker/docker-entrypoint-initdb.d/init-db.sql
@@ -0,0 +1,3 @@
+CREATE DATABASE hibernate_types;
+use hibernate_types;
+GRANT ALL PRIVILEGES ON hibernate_types.* TO 'mysql'@'%' IDENTIFIED BY 'admin';
diff --git a/persistence-modules/hibernate-types/docker/etc/mysql/conf.d/utf8.cnf b/persistence-modules/hibernate-types/docker/etc/mysql/conf.d/utf8.cnf
new file mode 100644
index 0000000000..1885d83c8b
--- /dev/null
+++ b/persistence-modules/hibernate-types/docker/etc/mysql/conf.d/utf8.cnf
@@ -0,0 +1,7 @@
+[mysqld]
+init_connect='SET collation_connection = utf8_unicode_ci'
+character-set-server = utf8
+collation-server = utf8_unicode_ci
+
+[client]
+default-character-set = utf8
\ No newline at end of file
diff --git a/persistence-modules/hibernate-types/pom.xml b/persistence-modules/hibernate-types/pom.xml
new file mode 100644
index 0000000000..9fa5d66347
--- /dev/null
+++ b/persistence-modules/hibernate-types/pom.xml
@@ -0,0 +1,214 @@
+
+
+ 4.0.0
+ hibernate-types
+ 0.0.1-SNAPSHOT
+ hibernate-types
+ Introduction into hibernate types library
+
+
+ com.baeldung
+ persistence-modules
+ 1.0.0-SNAPSHOT
+
+
+
+
+ com.vladmihalcea
+ hibernate-types-52
+ ${hibernate-types.version}
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+ ${spring-boot.version}
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ ${spring-boot.version}
+ test
+
+
+ org.junit.vintage
+ junit-vintage-engine
+
+
+
+
+ org.springframework.boot
+ spring-boot-devtools
+ ${spring-boot.version}
+ runtime
+ true
+
+
+ org.hibernate
+ hibernate-core
+ ${hibernate.version}
+ provided
+
+
+ org.hibernate
+ hibernate-ehcache
+ ${hibernate.version}
+ test
+
+
+ org.hibernate
+ hibernate-testing
+ ${hibernate.version}
+ test
+
+
+ org.assertj
+ assertj-core
+ ${assertj-core.version}
+ test
+
+
+ mysql
+ mysql-connector-java
+ ${mysql.version}
+ runtime
+
+
+ org.slf4j
+ slf4j-api
+ ${slf4j.version}
+ provided
+ true
+
+
+ ch.qos.logback
+ logback-classic
+ ${logback.version}
+ provided
+ true
+
+
+ javax.xml.bind
+ jaxb-api
+ ${jaxb.version}
+
+
+ org.javassist
+ javassist
+ ${javassist.version}
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ ${jackson.version}
+ provided
+ true
+
+
+ com.google.guava
+ guava
+ ${guava.version}
+ provided
+ true
+
+
+ net.ttddyy
+ datasource-proxy
+ ${datasource-proxy.version}
+ test
+
+
+ com.integralblue
+ log4jdbc-spring-boot-starter
+ ${log4jdbc.version}
+
+
+
+
+ hibernate-types
+
+
+ src/main/resources
+ true
+
+
+
+
+ org.apache.maven.plugins
+ maven-war-plugin
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ ${maven.version}
+
+
+ ${target.version}
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+ 3
+ true
+
+ **/*IntegrationTest.java
+
+
+
+
+
+
+
+
+ integration
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+ integration-test
+
+ test
+
+
+
+ none
+
+
+ **/*IntegrationTest.java
+
+
+
+
+
+
+
+
+
+
+
+ 3.15.0
+ 1.6
+ 29.0-jre
+ 2.9.7
+ 5.4.14.Final
+ 2.10.3
+ 1.8
+ 3.27.0-GA
+ 2.3.1
+ 2.0.0
+ 1.2.3
+ 3.0.2
+ 2.22.2
+ 3.8.1
+ 3.7.0
+ 8.0.19
+ 1.7.30
+ 2.1.3.RELEASE
+
+
+
diff --git a/persistence-modules/hibernate-types/src/main/java/com/baeldung/hibernate/types/Album.java b/persistence-modules/hibernate-types/src/main/java/com/baeldung/hibernate/types/Album.java
new file mode 100644
index 0000000000..f18818c3a9
--- /dev/null
+++ b/persistence-modules/hibernate-types/src/main/java/com/baeldung/hibernate/types/Album.java
@@ -0,0 +1,34 @@
+package com.baeldung.hibernate.types;
+
+import org.hibernate.annotations.Type;
+
+import javax.persistence.*;
+import java.util.List;
+
+@Entity(name = "Album")
+@Table(name = "album")
+public class Album extends BaseEntity {
+ @Type(type = "json")
+ @Column(columnDefinition = "json")
+ private CoverArt coverArt;
+
+ @OneToMany(fetch = FetchType.EAGER)
+ private List songs;
+
+ public CoverArt getCoverArt() {
+ return coverArt;
+ }
+
+ public void setCoverArt(CoverArt coverArt) {
+ this.coverArt = coverArt;
+ }
+
+
+ public List getSongs() {
+ return songs;
+ }
+
+ public void setSong(List songs) {
+ this.songs = songs;
+ }
+}
diff --git a/persistence-modules/hibernate-types/src/main/java/com/baeldung/hibernate/types/AlbumRepository.java b/persistence-modules/hibernate-types/src/main/java/com/baeldung/hibernate/types/AlbumRepository.java
new file mode 100644
index 0000000000..d89542de46
--- /dev/null
+++ b/persistence-modules/hibernate-types/src/main/java/com/baeldung/hibernate/types/AlbumRepository.java
@@ -0,0 +1,8 @@
+package com.baeldung.hibernate.types;
+
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface AlbumRepository extends CrudRepository {
+}
diff --git a/persistence-modules/hibernate-types/src/main/java/com/baeldung/hibernate/types/Artist.java b/persistence-modules/hibernate-types/src/main/java/com/baeldung/hibernate/types/Artist.java
new file mode 100644
index 0000000000..8f3ccb44c5
--- /dev/null
+++ b/persistence-modules/hibernate-types/src/main/java/com/baeldung/hibernate/types/Artist.java
@@ -0,0 +1,72 @@
+package com.baeldung.hibernate.types;
+
+import java.io.Serializable;
+
+public class Artist implements Serializable {
+
+ private String name;
+ private String country;
+ private String genre;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getCountry() {
+ return country;
+ }
+
+ public void setCountry(String country) {
+ this.country = country;
+ }
+
+ public String getGenre() {
+ return genre;
+ }
+
+ public void setGenre(String genre) {
+ this.genre = genre;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((country == null) ? 0 : country.hashCode());
+ result = prime * result + ((genre == null) ? 0 : genre.hashCode());
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Artist other = (Artist) obj;
+ if (country == null) {
+ if (other.country != null)
+ return false;
+ } else if (!country.equals(other.country))
+ return false;
+ if (genre == null) {
+ if (other.genre != null)
+ return false;
+ } else if (!genre.equals(other.genre))
+ return false;
+ if (name == null) {
+ if (other.name != null)
+ return false;
+ } else if (!name.equals(other.name))
+ return false;
+ return true;
+ }
+
+ }
diff --git a/persistence-modules/hibernate-types/src/main/java/com/baeldung/hibernate/types/BaseEntity.java b/persistence-modules/hibernate-types/src/main/java/com/baeldung/hibernate/types/BaseEntity.java
new file mode 100644
index 0000000000..3e0fbc7595
--- /dev/null
+++ b/persistence-modules/hibernate-types/src/main/java/com/baeldung/hibernate/types/BaseEntity.java
@@ -0,0 +1,37 @@
+package com.baeldung.hibernate.types;
+
+import com.vladmihalcea.hibernate.type.json.JsonBinaryType;
+import com.vladmihalcea.hibernate.type.json.JsonStringType;
+import org.hibernate.annotations.TypeDef;
+import org.hibernate.annotations.TypeDefs;
+
+import javax.persistence.*;
+
+@TypeDefs({
+ @TypeDef(name = "json", typeClass = JsonStringType.class),
+ @TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
+})
+@MappedSuperclass
+public class BaseEntity {
+ @Id
+ @GeneratedValue(strategy=GenerationType.AUTO)
+ @Column(name = "id", unique = true, nullable = false)
+ long id;
+ String name;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
diff --git a/persistence-modules/hibernate-types/src/main/java/com/baeldung/hibernate/types/CoverArt.java b/persistence-modules/hibernate-types/src/main/java/com/baeldung/hibernate/types/CoverArt.java
new file mode 100644
index 0000000000..bd71edc53c
--- /dev/null
+++ b/persistence-modules/hibernate-types/src/main/java/com/baeldung/hibernate/types/CoverArt.java
@@ -0,0 +1,71 @@
+package com.baeldung.hibernate.types;
+
+import java.io.Serializable;
+
+public class CoverArt implements Serializable {
+
+ private String frontCoverArtUrl;
+ private String backCoverArtUrl;
+ private String upcCode;
+
+ public String getFrontCoverArtUrl() {
+ return frontCoverArtUrl;
+ }
+
+ public void setFrontCoverArtUrl(String frontCoverArtUrl) {
+ this.frontCoverArtUrl = frontCoverArtUrl;
+ }
+
+ public String getBackCoverArtUrl() {
+ return backCoverArtUrl;
+ }
+
+ public void setBackCoverArtUrl(String backCoverArtUrl) {
+ this.backCoverArtUrl = backCoverArtUrl;
+ }
+
+ public String getUpcCode() {
+ return upcCode;
+ }
+
+ public void setUpcCode(String upcCode) {
+ this.upcCode = upcCode;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((backCoverArtUrl == null) ? 0 : backCoverArtUrl.hashCode());
+ result = prime * result + ((frontCoverArtUrl == null) ? 0 : frontCoverArtUrl.hashCode());
+ result = prime * result + ((upcCode == null) ? 0 : upcCode.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ CoverArt other = (CoverArt) obj;
+ if (backCoverArtUrl == null) {
+ if (other.backCoverArtUrl != null)
+ return false;
+ } else if (!backCoverArtUrl.equals(other.backCoverArtUrl))
+ return false;
+ if (frontCoverArtUrl == null) {
+ if (other.frontCoverArtUrl != null)
+ return false;
+ } else if (!frontCoverArtUrl.equals(other.frontCoverArtUrl))
+ return false;
+ if (upcCode == null) {
+ if (other.upcCode != null)
+ return false;
+ } else if (!upcCode.equals(other.upcCode))
+ return false;
+ return true;
+ }
+}
diff --git a/persistence-modules/hibernate-types/src/main/java/com/baeldung/hibernate/types/HibernateTypesApplication.java b/persistence-modules/hibernate-types/src/main/java/com/baeldung/hibernate/types/HibernateTypesApplication.java
new file mode 100644
index 0000000000..ac379f9ee2
--- /dev/null
+++ b/persistence-modules/hibernate-types/src/main/java/com/baeldung/hibernate/types/HibernateTypesApplication.java
@@ -0,0 +1,13 @@
+package com.baeldung.hibernate.types;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class HibernateTypesApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(HibernateTypesApplication.class, args);
+ }
+
+}
diff --git a/persistence-modules/hibernate-types/src/main/java/com/baeldung/hibernate/types/Song.java b/persistence-modules/hibernate-types/src/main/java/com/baeldung/hibernate/types/Song.java
new file mode 100644
index 0000000000..2d22296024
--- /dev/null
+++ b/persistence-modules/hibernate-types/src/main/java/com/baeldung/hibernate/types/Song.java
@@ -0,0 +1,57 @@
+package com.baeldung.hibernate.types;
+
+import org.hibernate.annotations.Type;
+import org.hibernate.annotations.TypeDef;
+
+import java.time.YearMonth;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Table;
+
+import com.vladmihalcea.hibernate.type.basic.YearMonthIntegerType;
+
+@Entity(name = "Song")
+@Table(name = "song")
+@TypeDef(
+ typeClass = YearMonthIntegerType.class,
+ defaultForType = YearMonth.class
+)
+public class Song extends BaseEntity {
+
+ private Long length = 0L;
+
+ @Type(type = "json")
+ @Column(columnDefinition = "json")
+ private Artist artist;
+
+ @Column(
+ name = "recorded_on",
+ columnDefinition = "mediumint"
+ )
+ private YearMonth recordedOn = YearMonth.now();
+
+ public Long getLength() {
+ return length;
+ }
+
+ public void setLength(Long length) {
+ this.length = length;
+ }
+
+ public Artist getArtist() {
+ return artist;
+ }
+
+ public void setArtist(Artist artist) {
+ this.artist = artist;
+ }
+
+ public YearMonth getRecordedOn() {
+ return recordedOn;
+ }
+
+ public void setRecordedOn(YearMonth recordedOn) {
+ this.recordedOn = recordedOn;
+ }
+}
\ No newline at end of file
diff --git a/persistence-modules/hibernate-types/src/main/java/com/baeldung/hibernate/types/SongRepository.java b/persistence-modules/hibernate-types/src/main/java/com/baeldung/hibernate/types/SongRepository.java
new file mode 100644
index 0000000000..e79e88108b
--- /dev/null
+++ b/persistence-modules/hibernate-types/src/main/java/com/baeldung/hibernate/types/SongRepository.java
@@ -0,0 +1,8 @@
+package com.baeldung.hibernate.types;
+
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface SongRepository extends CrudRepository {
+}
diff --git a/persistence-modules/hibernate-types/src/main/resources/application.properties b/persistence-modules/hibernate-types/src/main/resources/application.properties
new file mode 100644
index 0000000000..bcd21578dd
--- /dev/null
+++ b/persistence-modules/hibernate-types/src/main/resources/application.properties
@@ -0,0 +1,21 @@
+log4jdbc.dump.sql.addsemicolon=true
+log4jdbc.dump.sql.maxlinelength=0
+log4jdbc.trim.sql.extrablanklines=false
+logging.level.jdbc.audit=fatal
+logging.level.jdbc.connection=fatal
+logging.level.jdbc.resultset=fatal
+logging.level.jdbc.resultsettable=info
+logging.level.jdbc.sqlonly=fatal
+logging.level.jdbc.sqltiming=info
+# logging.level.org.hibernate.SQL=DEBUG
+# logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
+# logging.level.org.hibernate.type.descriptor.sql=trace
+# logging.level.org.springframework.jdbc.core.JdbcTemplate=DEBUG
+# logging.level.org.springframework.jdbc.core.StatementCreatorUtils=TRACE
+spring.datasource.url=jdbc:mysql://localhost:53306/hibernate_types?serverTimezone=UTC&useSSL=false
+spring.datasource.username=root
+spring.jpa.database-platform=org.hibernate.dialect.MySQL5Dialect
+spring.jpa.hibernate.ddl-auto=create
+spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
+# spring.jpa.properties.hibernate.format_sql=false
+# spring.jpa.show-sql=false
\ No newline at end of file
diff --git a/persistence-modules/hibernate-types/src/main/resources/hibernate-types.properties b/persistence-modules/hibernate-types/src/main/resources/hibernate-types.properties
new file mode 100644
index 0000000000..226b50fafd
--- /dev/null
+++ b/persistence-modules/hibernate-types/src/main/resources/hibernate-types.properties
@@ -0,0 +1 @@
+hibernate.types.print.banner=false
diff --git a/persistence-modules/hibernate-types/src/test/java/com/baeldung/hibernate/types/HibernateTypesIntegrationTest.java b/persistence-modules/hibernate-types/src/test/java/com/baeldung/hibernate/types/HibernateTypesIntegrationTest.java
new file mode 100644
index 0000000000..cf3c34777e
--- /dev/null
+++ b/persistence-modules/hibernate-types/src/test/java/com/baeldung/hibernate/types/HibernateTypesIntegrationTest.java
@@ -0,0 +1,182 @@
+package com.baeldung.hibernate.types;
+
+import com.google.common.collect.Lists;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import java.time.Duration;
+import java.time.YearMonth;
+import java.util.UUID;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+@SpringBootTest
+public class HibernateTypesIntegrationTest {
+
+ @Autowired
+ AlbumRepository albumRepository;
+
+ @Autowired
+ SongRepository songRepository;
+
+ private void deleteAll() {
+ albumRepository.deleteAll();
+ songRepository.deleteAll();
+ }
+
+ @BeforeEach
+ public void setUp() {
+ deleteAll();
+ }
+
+ @BeforeEach
+ public void tearDown() {
+ setUp();
+ }
+
+
+ @Test
+ void hibernateTypeJsonTest() {
+ Album nullAlbum = new Album();
+ nullAlbum = albumRepository.save(nullAlbum);
+
+ Song nullSong = new Song();
+ nullSong = songRepository.save(nullSong);
+
+ Artist artist0 = new Artist();
+ artist0.setCountry("England");
+ artist0.setGenre("Pop");
+ artist0.setName("Superstar");
+
+ Song song0 = new Song();
+ song0.setArtist(artist0);
+ song0.setName("A Happy Song");
+ song0.setLength(Duration.ofMinutes(4).getSeconds());
+ song0 = songRepository.save(song0);
+
+ Song song1 = new Song();
+ song1.setArtist(artist0);
+ song1.setName("A Sad Song");
+ song1.setLength(Duration.ofMinutes(2).getSeconds());
+ song1 = songRepository.save(song1);
+
+ Song song2 = new Song();
+ song2.setArtist(artist0);
+ song2.setName("Another Happy Song");
+ song2.setLength(Duration.ofMinutes(3).getSeconds());
+ song2 = songRepository.save(song2);
+
+ Artist artist1 = new Artist();
+ artist1.setCountry("Jamaica");
+ artist1.setGenre("Reggae");
+ artist1.setName("Newcomer");
+
+ Song song3 = new Song();
+ song3.setArtist(artist1);
+ song3.setName("A New Song");
+ song3.setLength(Duration.ofMinutes(5).getSeconds());
+ song3 = songRepository.save(song3);
+
+ CoverArt album0CoverArt = new CoverArt();
+ album0CoverArt.setUpcCode(UUID.randomUUID().toString());
+ album0CoverArt.setFrontCoverArtUrl("http://fakeurl-0");
+ album0CoverArt.setBackCoverArtUrl("http://fakeurl-1");
+
+ Album album0 = new Album();
+ album0.setCoverArt(album0CoverArt);
+ album0.setName("Album 0");
+ album0.setSong(Lists.newArrayList(song0, song1, song2));
+ album0 = albumRepository.save(album0);
+
+ CoverArt album1CoverArt = new CoverArt();
+ album1CoverArt.setUpcCode(UUID.randomUUID().toString());
+ album1CoverArt.setFrontCoverArtUrl("http://fakeurl-2");
+ album1CoverArt.setBackCoverArtUrl("http://fakeurl-3");
+
+ Album album1 = new Album();
+ album1.setCoverArt(album1CoverArt);
+ album1.setName("Album 1");
+ album1.setSong(Lists.newArrayList(song3));
+ albumRepository.save(album1);
+
+ Iterable queryAlbumsResult = albumRepository.findAll();
+ assertThat(queryAlbumsResult).hasSize(3);
+
+ Iterable querySongsResult = songRepository.findAll();
+ assertThat(querySongsResult).hasSize(5);
+
+ Album queryAlbumResult;
+
+ queryAlbumResult = albumRepository.findById(nullAlbum.getId()).get();
+ assertThat(queryAlbumResult.getName()).isNull();
+ assertThat(queryAlbumResult.getCoverArt()).isNull();
+ assertThat(queryAlbumResult.getSongs()).isNullOrEmpty();
+
+ queryAlbumResult = albumRepository.findById(album0.getId()).get();
+ assertThat(queryAlbumResult.getName()).isEqualTo("Album 0");
+ assertThat(queryAlbumResult.getCoverArt().getFrontCoverArtUrl()).isEqualTo("http://fakeurl-0");
+ assertThat(queryAlbumResult.getCoverArt().getBackCoverArtUrl()).isEqualTo("http://fakeurl-1");
+ assertThat(queryAlbumResult.getSongs()).hasSize(3);
+ assertThat(queryAlbumResult.getSongs()).usingFieldByFieldElementComparator().containsExactlyInAnyOrder(song0, song1, song2);
+
+ queryAlbumResult = albumRepository.findById(album1.getId()).get();
+ assertThat(queryAlbumResult.getName()).isEqualTo("Album 1");
+ assertThat(queryAlbumResult.getCoverArt().getFrontCoverArtUrl()).isEqualTo("http://fakeurl-2");
+ assertThat(queryAlbumResult.getCoverArt().getBackCoverArtUrl()).isEqualTo("http://fakeurl-3");
+ assertThat(queryAlbumResult.getSongs()).hasSize(1);
+ assertThat(queryAlbumResult.getSongs()).usingFieldByFieldElementComparator().containsExactlyInAnyOrder(song3);
+
+ Song querySongResult;
+
+ querySongResult = songRepository.findById(nullSong.getId()).get();
+ assertThat(querySongResult.getName()).isNull();
+ assertThat(querySongResult.getLength()).isZero();
+ assertThat(querySongResult.getArtist()).isNull();
+
+ querySongResult = songRepository.findById(song0.getId()).get();
+ assertThat(querySongResult.getName()).isEqualTo("A Happy Song");
+ assertThat(querySongResult.getLength()).isEqualTo(Duration.ofMinutes(4).getSeconds());
+ assertThat(querySongResult.getArtist().getName()).isEqualTo("Superstar");
+ assertThat(querySongResult.getArtist().getGenre()).isEqualTo("Pop");
+ assertThat(querySongResult.getArtist().getCountry()).isEqualTo("England");
+
+ querySongResult = songRepository.findById(song1.getId()).get();
+ assertThat(querySongResult.getName()).isEqualTo("A Sad Song");
+ assertThat(querySongResult.getLength()).isEqualTo(Duration.ofMinutes(2).getSeconds());
+ assertThat(querySongResult.getArtist().getName()).isEqualTo("Superstar");
+ assertThat(querySongResult.getArtist().getGenre()).isEqualTo("Pop");
+ assertThat(querySongResult.getArtist().getCountry()).isEqualTo("England");
+
+ querySongResult = songRepository.findById(song2.getId()).get();
+ assertThat(querySongResult.getName()).isEqualTo("Another Happy Song");
+ assertThat(querySongResult.getLength()).isEqualTo(Duration.ofMinutes(3).getSeconds());
+ assertThat(querySongResult.getArtist().getName()).isEqualTo("Superstar");
+ assertThat(querySongResult.getArtist().getGenre()).isEqualTo("Pop");
+ assertThat(querySongResult.getArtist().getCountry()).isEqualTo("England");
+
+ querySongResult = songRepository.findById(song3.getId()).get();
+ assertThat(querySongResult.getName()).isEqualTo("A New Song");
+ assertThat(querySongResult.getLength()).isEqualTo(Duration.ofMinutes(5).getSeconds());
+ assertThat(querySongResult.getArtist().getName()).isEqualTo("Newcomer");
+ assertThat(querySongResult.getArtist().getGenre()).isEqualTo("Reggae");
+ assertThat(querySongResult.getArtist().getCountry()).isEqualTo("Jamaica");
+ }
+
+ @Test
+ void hibernateTypeYearMonthTest() {
+ Song mySong = new Song();
+ YearMonth now = YearMonth.of(2019, 12);
+ mySong.setArtist(new Artist());
+ mySong.setName("My Song");
+ mySong.setLength(Duration.ofMinutes(1).getSeconds());
+ mySong.setRecordedOn(now);
+ mySong = songRepository.save(mySong);
+
+ Song queryResult;
+ queryResult = songRepository.findById(mySong.getId()).get();
+ assertThat(queryResult.getRecordedOn().getYear()).isEqualTo(2019);
+ assertThat(queryResult.getRecordedOn().getMonthValue()).isEqualTo(12);
+ }
+}
diff --git a/persistence-modules/pom.xml b/persistence-modules/pom.xml
index ec7f0bcec2..4d39b2d98b 100644
--- a/persistence-modules/pom.xml
+++ b/persistence-modules/pom.xml
@@ -24,6 +24,7 @@
hibernate-mapping
hibernate-ogm
hibernate-annotations
+ hibernate-types
hibernate-jpa
hibernate-queries
hibernate-enterprise