1. Overview
1.概述
In this tutorial, we’ll take a look at Hibernate Types. This library provides us with a few types that are not native in the core Hibernate ORM.
在本教程中,我们将看一下Hibernate类型。该库为我们提供了一些在核心Hibernate ORM中不存在的类型。
2. Dependencies
2.依赖性
To enable Hibernate Types we’ll just add the appropriate hibernate-types dependency:
要启用Hibernate Types,我们只需添加相应的hibernate-types依赖关系。
<dependency>
<groupId>com.vladmihalcea</groupId>
<artifactId>hibernate-types-52</artifactId>
<version>2.9.7</version>
</dependency>
This will work with Hibernate versions 5.4, 5.3, and 5.2.
这将适用于Hibernate版本5.4,5.3,和5.2.。
In the event that the version of Hibernate is older, the artifactId value above will be different. For versions 5.1 and 5.0, we can use hibernate-types-51. Similarly, version 4.3 requires hibernate-types-43, and versions 4.2, and 4.1 require hibernate-types-4.
如果Hibernate的版本较老,上面的artifactId值将会不同。对于版本5.1和5.0,,我们可以使用hibernate-types-51. 类似地,版本4.3需要hibernate-types-43,,版本4.2和4.1需要hibernate-types-4.。
The examples in this tutorial require a database. Using Docker we’ve provided a database container. Therefore, we’ll need a working copy of Docker.
本教程中的例子需要一个数据库。使用Docker,我们已经提供了一个数据库容器。因此,我们需要一个Docker>的工作副本。
So, to run and create our database we only need to execute:
因此,为了运行和创建我们的数据库,我们只需要执行。
$ ./create-database.sh
3. Supported Databases
3.支持的数据库
We can use our types with Oracle, SQL Server, PostgreSQL, and MySQL databases. Therefore, the mapping of types in Java to database column types will vary depending on the database we use. In our case, we will use MySQL and map the JsonBinaryType to a JSON column type.
我们可以在Oracle、SQL Server、PostgreSQL和MySQL数据库中使用我们的类型。因此,Java中的类型与数据库列类型的映射将根据我们使用的数据库而有所不同。在我们的案例中,我们将使用MySQL并将JsonBinaryType映射到JSON列类型。
Documentation on the supported mappings can be found over on the Hibernate Types repository.
关于支持的映射的文档可以在Hibernate类型库上找到。
4. Data Model
4.数据模型
The data model for this tutorial will allow us to store information about albums and songs. An album has cover art and one or more songs. A song has an artist and length. The cover art has two image URLs and a UPC code. Finally, an artist has a name, a country, and a musical genre.
本教程的数据模型将允许我们存储有关专辑和歌曲的信息。一张专辑有封面设计和一首或多首歌曲。一首歌曲有一个艺术家和长度。封面图有两个图片URL和一个UPC代码。最后,一个艺术家有一个名字,一个国家,和一个音乐流派。
In the past, we’d have created tables to represent all the data in our model. But, now that we have types available to us we can very easily store some of the data as JSON instead.
在过去,我们会创建表格来表示我们模型中的所有数据。但是,现在我们有了可用的类型,我们可以非常容易地将一些数据存储为 JSON。
For this tutorial, we’ll only create tables for the albums and the songs:
在本教程中,我们将只为专辑和歌曲创建表格。
public class Album extends BaseEntity {
@Type(type = "json")
@Column(columnDefinition = "json")
private CoverArt coverArt;
@OneToMany(fetch = FetchType.EAGER)
private List<Song> songs;
// other class members
}
public class Song extends BaseEntity {
private Long length = 0L;
@Type(type = "json")
@Column(columnDefinition = "json")
private Artist artist;
// other class members
}
Using the JsonStringType we’ll represent the cover art and artists as JSON columns in those tables:
使用JsonStringType,我们将在这些表中把封面艺术和艺术家表示为JSON列:。
public class Artist implements Serializable {
private String name;
private String country;
private String genre;
// other class members
}
public class CoverArt implements Serializable {
private String frontCoverArtUrl;
private String backCoverArtUrl;
private String upcCode;
// other class members
}
It’s important to note that the Artist and CoverArt classes are POJOs and not entities. Furthermore, they are members of our database entity classes, defined with the @Type(type = “json”) annotation.
需要注意的是,Artist和CoverArt类是POJO,而不是实体。此外,它们是我们数据库实体类的成员,用@Type(type = “json”)注解定义。
4.1. Storing JSON Types
4.1. 存储JSON类型
We defined our album and songs models to contain members the database will store as JSON. This is due to using the provided json type. In order to have that type available for us to use we must define it using a type definition:
我们定义了我们的专辑和歌曲模型,包含数据库将存储为JSON的成员。这是由于使用了提供的json类型。为了使该类型可供我们使用,我们必须使用一个类型定义来定义它。
@TypeDefs({
@TypeDef(name = "json", typeClass = JsonStringType.class),
@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
})
public class BaseEntity {
// class members
}
The @Type for JsonStringType and JsonBinaryType makes the types json and jsonb available.
用于JsonStringType和JsonBinaryType的@Type使得json和jsonb类型可用。
The latest MySQL versions support JSON as a column type. Consequently, JDBC processes any JSON read from or any object saved to a column with either of these types as a String. This means that to map to the column correctly we must use JsonStringType in our type definition.
最新的MySQL版本支持JSON作为一种列类型。因此,JDBC将从这些类型的列中读取的任何JSON或保存到列中的任何对象都处理为String。这意味着为了正确地映射到列,我们必须在类型定义中使用JsonStringType。
4.2. Hibernate
4.2.休眠
Ultimately, our types will automatically translate to SQL using JDBC and Hibernate. So, now we can create a few song objects, an album object and persist them to the database. Subsequently, Hibernate generates the following SQL statements:
最终,我们的类型将使用JDBC和Hibernate自动转换为SQL。所以,现在我们可以创建一些歌曲对象,一个专辑对象,并将它们持久化到数据库中。 随后,Hibernate会生成以下SQL语句。
insert into song (name, artist, length, id) values ('A Happy Song', '{"name":"Superstar","country":"England","genre":"Pop"}', 240, 3);
insert into song (name, artist, length, id) values ('A Sad Song', '{"name":"Superstar","country":"England","genre":"Pop"}', 120, 4);
insert into song (name, artist, length, id) values ('A New Song', '{"name":"Newcomer","country":"Jamaica","genre":"Reggae"}', 300, 6)
insert into album (name, cover_art, id) values ('Album 0', '{"frontCoverArtUrl":"http://fakeurl-0","backCoverArtUrl":"http://fakeurl-1","upcCode":"b2b9b193-ee04-4cdc-be8f-3a276769ab5b"}', 7)
As expected, our json type Java objects are all translated by Hibernate and stored as well-formed JSON in our database.
正如预期的那样,我们的json类型的Java对象都被Hibernate翻译,并作为格式良好的JSON存储在我们的数据库中。
5. Storing Generic Types
5.存储通用类型
Besides supporting JSON based columns, the library also adds a few generics types: YearMonth, Year, and Month from the java.time package.
除了支持基于JSON的列,该库还增加了一些泛型类型。YearMonth, Year,和Month来自java.time包。
Now, we can map these types that are not natively supported by Hibernate or JPA. Also, we now have the ability to store them as an Integer, String, or Date column.
现在,我们可以映射Hibernate或JPA不支持的这些类型。此外,我们现在可以将它们存储为整数、字符串或日期列。
For example, let’s say we want to add the recorded date of a song to our song model and store it as an Integer in our database. We can use the YearMonthIntegerType in our Song entity class definition:
例如,假设我们想将一首歌曲的录制日期添加到我们的歌曲模型中,并将其作为Integer存储在数据库中。我们可以在我们的Song实体类定义中使用YearMonthIntegerType。
@TypeDef(
typeClass = YearMonthIntegerType.class,
defaultForType = YearMonth.class
)
public class Song extends BaseEntity {
@Column(
name = "recorded_on",
columnDefinition = "mediumint"
)
private YearMonth recordedOn = YearMonth.now();
// other class members
}
Our recordedOn property value is translated to the typeClass we provided. As a result, a pre-defined converter will persist the value in our database as an Integer.
我们的recordedOn属性值被翻译成我们提供的typeClass。因此,一个预定义的转换器将把这个值作为Integer持久化在我们的数据库中。
6. Other Utility Classes
6.其他公用事业类
Hibernate Types has a few helper classes that further improve the developer experience when using Hibernate.
Hibernate Types有一些辅助类,可以进一步改善开发者在使用Hibernate时的体验。
The CamelCaseToSnakeCaseNamingStrategy maps camel-cased properties in our Java classes to snake-cased columns in our database.
CamelCaseToSnakeCaseNamingStrategy将我们Java类中以骆驼命名的属性映射到我们数据库中以蛇命名的列。
The ClassImportIntegrator allows simple Java DTO class name values in JPA constructor parameters.
ClassImportIntegrator允许在JPA构造器参数中使用简单的Java DTO类名值。
There are also the ListResultTransformer and the MapResultTransformer classes providing cleaner implementations of the result objects used by JPA. In addition, they support the use of lambdas and provide backward compatibility with older JPA versions.
还有ListResultTransformer和MapResultTransformer类提供了JPA使用的结果对象的更清洁的实现。此外,它们还支持使用lambdas,并提供与旧版JPA的向后兼容性。
7. Conclusion
7.结语
In this tutorial, we introduced the Hibernate Types Java library and the new types it adds to Hibernate and JPA. We also looked at some of the utilities and generic types provided by the library.
在本教程中,我们介绍了Hibernate Types Java库以及它为Hibernate和JPA增加的新类型。我们还看了该库所提供的一些实用工具和通用类型。
The implementation of the examples and code snippets are available over on GitHub.
实例的实现和代码片段可在GitHub上获得over。