Java 将 JSON 对象映射到 Hibernate 实体
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22729740/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Mapping JSON object to Hibernate entity
提问by Fractaliste
I'm going to start a project of a REST application managed with Spring and with Hibernate for my model.
我将为我的模型启动一个使用 Spring 和 Hibernate 管理的 REST 应用程序项目。
I know that Spring allows you to get Java object from the HTTP Request (with @Consumes(JSON)
annotation). Is there any conflict if this Java object is also a Hibernate entities? And is nested object working (like @ManyToOne
relation)?
我知道 Spring 允许您从 HTTP 请求(带@Consumes(JSON)
注释)中获取 Java 对象。如果这个 Java 对象也是一个 Hibernate 实体,是否有任何冲突?嵌套对象是否工作(如@ManyToOne
关系)?
采纳答案by oceansize
We were using such approach to simplify design and get rid of many dtos (we were abusing them too much). Basically, it worked for us.
我们正在使用这种方法来简化设计并摆脱许多 dtos(我们滥用它们太多了)。基本上,它对我们有用。
However, in our REST model we were trying to do not expose other relations for an object as you can always create another REST resources to access them.
但是,在我们的 REST 模型中,我们试图不公开对象的其他关系,因为您始终可以创建其他 REST 资源来访问它们。
So we just put @JsonIgnore
annotations to relations mappings like @OneToMany
or @ManyToOne
making them transient.
所以我们只是@JsonIgnore
在关系映射上添加注释,例如@OneToMany
或@ManyToOne
使它们成为瞬态。
Another problem I see that if you still like to return these relations you would have to use Join.FETCH
strategy for them or move transaction management higher so that transaction still exists when a response is serialized to JSON (Open Session In View Pattern).
On my opinion these two solutions are not so good.
我看到的另一个问题是,如果您仍然想返回这些关系,则必须Join.FETCH
对它们使用策略或将事务管理移到更高的位置,以便在将响应序列化为 JSON(打开会话视图模式)时事务仍然存在。在我看来,这两种解决方案都不是很好。
回答by Nikola Yovchev
Yes, this wouldn't be a problem and is actually a fairly common practice.
是的,这不会成为问题,实际上是一种相当普遍的做法。
In the recent years I have come to realize that sometimes, however, it is not a good idea to always build your views based on your domain directly. You can take a look at this post:
近年来,我逐渐意识到,有时,总是直接基于您的领域构建您的视图并不是一个好主意。你可以看看这个帖子:
http://codebetter.com/jpboodhoo/2007/09/27/screen-bound-dto-s/
http://codebetter.com/jpboodhoo/2007/09/27/screen-bound-dto-s/
It is also known as "Presentation Model":
它也被称为“演示模型”:
http://martinfowler.com/eaaDev/PresentationModel.html
http://martinfowler.com/eaaDev/PresentationModel.html
The idea behind that is basically the following:
其背后的想法基本上如下:
Imagine you have the domain entry User, who looks like that :
想象一下,您有域条目 User,它看起来像这样:
@Entity
@Data
public class User {
@Id private UUID userId;
private String username;
@OneToMany private List<Permission> permissions;
}
Let's now imagine you have a view where you wanna display that user's name, and you totally don't care about the permissions. If you use your approach of immediately returning the User to the view, Hibernate will make an additional join from the Permissions table because event though the permissions are lazily loaded by default, there is no easy way to signal to the Hymanson serializer or whatever you are using, that you don't care about them in this particular occasion, so Hymanson will try to unproxy them (if your transaction is still alive by the time your object is put for json serialization, otherwise you get a nasty exception). Yes, you can add a @JsonIgnore
annotation on the permissions field, but then if you need it in some other view, you are screwed.
现在让我们假设您有一个视图,您想在其中显示该用户的名称,而您完全不关心权限。如果您使用立即将 User 返回到视图的方法,Hibernate 将从 Permissions 表中进行额外的连接,因为尽管默认情况下权限是延迟加载的事件,但没有简单的方法可以向 Hymanson 序列化程序或任何您发送信号使用,在这种特殊情况下您不关心它们,因此 Hymanson 将尝试取消代理它们(如果在您的对象用于 json 序列化时您的事务仍然存在,否则您会得到一个令人讨厌的异常)。是的,您可以@JsonIgnore
在权限字段上添加注释,但是如果您在其他视图中需要它,您就搞砸了。
That a very basic example, but you should get the idea that sometimes your domain model can't be immediately used to be returned to the presentation layer, due to both code maintainability and performance issues.
这是一个非常基本的示例,但您应该明白,由于代码可维护性和性能问题,有时您的域模型不能立即用于返回到表示层。
回答by Rajit
Since you are just starting, perhaps you could use Spring Data REST?
既然您刚刚开始,也许您可以使用 Spring Data REST?
This is the project: http://projects.spring.io/spring-data-rest/
这是项目:http: //projects.spring.io/spring-data-rest/
And here are some simple examples:
这里有一些简单的例子:
- https://github.com/spring-projects/spring-data-book/tree/master/rest
- https://github.com/olivergierke/spring-restbucks
- https://github.com/spring-projects/spring-data-book/tree/master/rest
- https://github.com/olivergierke/spring-restbucks
As you can see in the examples, there are no extra DTOs beyond the @Entity annotated POJOs.
正如您在示例中看到的,除了@Entity 注释的 POJO 之外,没有额外的 DTO。
回答by Vlad Mihalcea
This is a very common question, so I decided to write a very detailed article, about the best way to map JSON column types when using JPA and Hibernate.
这是一个很常见的问题,所以我决定写一篇非常详细的文章,介绍使用 JPA 和 Hibernate 时映射 JSON 列类型的最佳方法。
Maven dependency
Maven 依赖
The first thing you need to do is to set up the following Hibernate TypesMaven dependency in your project pom.xml
configuration file:
您需要做的第一件事是在您的项目配置文件中设置以下Hibernate TypesMaven 依赖项pom.xml
:
<dependency>
<groupId>com.vladmihalcea</groupId>
<artifactId>hibernate-types-52</artifactId>
<version>${hibernate-types.version}</version>
</dependency>
Domain model
领域模型
Now, if you are using PostgreSQL, you need to use the JsonBinaryType
from Hibernate Types. In order to use it in your entities, you will have to declare it on either class level or in a package-info.javapackage-level descriptor, like this:
现在,如果您使用 PostgreSQL,则需要使用JsonBinaryType
from Hibernate Types。为了在您的实体中使用它,您必须在类级别或package-info.java包级别描述符中声明它,如下所示:
@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
And, the entity mapping will look like this:
而且,实体映射将如下所示:
@Type(type = "jsonb")
@Column(columnDefinition = "json")
private Location location;
If you're using Hibernate 5 or later, then the JSON
type is [registered automatically by the Postgre92Dialect
][4].
如果您使用的是 Hibernate 5 或更高版本,则JSON
类型为 [由Postgre92Dialect
][4]自动注册。
Otherwise, you need to register it yourself:
否则,您需要自己注册:
public class PostgreSQLDialect extends PostgreSQL91Dialect {
public PostgreSQL92Dialect() {
super();
this.registerColumnType( Types.JAVA_OBJECT, "json" );
}
}
Hibernate Types supports Oracle, SQL Server, PostgreSQL, and MySQL JSON column types. Check out the projectpage for more details about how you can map JSON column types on various relational database systems.
Hibernate Types 支持 Oracle、SQL Server、PostgreSQL 和 MySQL JSON 列类型。查看项目页面,了解有关如何在各种关系数据库系统上映射 JSON 列类型的更多详细信息。
回答by hager
You can map the json request without using any library at REST web-services (Jersy)
this sample of code:
您可以在不使用任何库的情况下映射 json 请求 REST web-services (Jersy)
此代码示例:
This hibernate entity called book:
这个休眠实体称为 book:
@Entity
@Table(name = "book", schema = "cashcall")
public class Book implements java.io.Serializable {
private int id;
private Author author; // another hibernate entity
private String bookName;
//setters and getters
}
This web-services function
这个网络服务功能
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public String addBook(Book book) {
String bookName=book.getName();
return bookName;
}
This is sample json request:
这是示例 json 请求:
{
"bookName" : "Head First Java",
"author" : {
"id" : 1
}
}