在 Spring-Roo 2.0 中,我得到的 JSON 不显示对象之间的关系。
In Spring-Roo 2.0, the JSON I get does not show relationship between objects.
这是我在 Spring-Roo 2.0 从 RESTful 网络服务调用返回 JSON 时遇到的问题的简化示例。下面是 2 类(公司和用户)的 Roo 脚本,显示用户与 company_id=1 相关的数据库内容,以及我返回的 JSON GET在用户身上。请注意,company=null。那就是问题所在。我做错了什么吗?
Roo 脚本
jpa setup --provider HIBERNATE --database MYSQL
--userName pivot --password pivot --databaseName testdb
entity jpa --class ~.model.MyUser
field string --fieldName firstName --notNull
field string --fieldName lastName --notNull
entity jpa --class ~.model.Company
field string --fieldName name –notNull
field set --fieldName users --type ~.model.MyUser --cardinality ONE_TO_MANY
--mappedBy company --comment "Users" --notNull false
repository jpa --all --package ~.repository
service --all --apiPackage ~.service.api --implPackage ~.service.impl
web mvc setup
/* ThymeLeaf view layer */
web mvc view setup --type THYMELEAF
web mvc templates setup --type THYMELEAF
web mvc controller --all --package ~.web --responseType THYMELEAF
/* JSON Rest controllers */
web mvc controller --all --responseType JSON --pathPrefix /json
web mvc finder --all --responseType THYMELEAF
web mvc finder --all --responseType JSON
数据库
mysql> select * from my_user;
+----+------------+-----------+---------+------------+
| id | first_name | last_name | version | company_id |
+----+------------+-----------+---------+------------+
| 1 | First | Last | 0 | 1 |
+----+------------+-----------+---------+------------+
1 row in set (0.00 sec)
JSON
{
"content": [
{
"id": 1,
"version": 0,
"firstName": "First",
"lastName": "Last",
"company": null
}
],
"last": true,
"totalPages": 1,
"totalElements": 1,
"size": 20,
"number": 0,
"first": true,
"numberOfElements": 1,
"sort": null
}
由 Spring Roo 2.0 生成的关系默认设置为 Lazy 以防止数据过载。请记住,Spring Roo 尝试尽可能地应用最佳实践。您可以在 MyUser.java
实体中看到:
@ManyToOne(fetch = FetchType.LAZY)
@EntityFormat
private Company company;
因此,当您获取MyUser
实体的所有记录时,默认情况下不会加载与Compny的关系。
但是,如果您知道要获取此信息,则应通过 Spring Roo 自定义生成的代码。请按照以下步骤操作:
在 MyUserRepositoryImpl
class 中声明的方法 findAll
进行推送。为此,请执行以下命令:
push-in --class ~.repository.MyUserRepositoryImpl --method findAll(GlobalSearch,Pageable)
之后,打开 MyUserRepositoryImpl.java
class 并更改默认查询以使用 Company
执行左连接。为此,请更改生成的代码:
JPQLQuery<MyUser> query = from(myUser);
给这个:
JPQLQuery<MyUser> query = from(myUser).leftJoin(myUser.company).fetchJoin();
使用尝试获取单个项目而不是列表时使用的 findOne
方法重复该过程。在这种情况下,您应该在 MyUserRepositoryCustom
接口中定义 findOne
方法,然后在 MyUserRepositoryImpl
.
中使用 QueryDSL 实现它
通过上述修改,当您使用GET
操作访问urlhttp://localhost:8080/json/myusers/
时,您应该能够获得以下JSON:
{
"content": [
{
"id": 1,
"version": 0,
"firstName": "test",
"lastName": "test",
"company": {
"id": 1,
"version": 0,
"name": "aaa"
}
}
],
"last": true,
"totalPages": 1,
"totalElements": 1,
"sort": null,
"numberOfElements": 1,
"first": true,
"size": 20,
"number": 0
}
作为建议,我不得不说,在 JSON 响应中使用具有关系的实体时应该小心。如果某个实体与与第一个实体相关的另一个实体相关,也许您可以获得循环关系。您应该 return 一个 实体投影 而不是 return 您 JSON 响应中的完整实体,它只显示相关元素的标识符而不是整个相关实体。
希望对您有所帮助,
这是我在 Spring-Roo 2.0 从 RESTful 网络服务调用返回 JSON 时遇到的问题的简化示例。下面是 2 类(公司和用户)的 Roo 脚本,显示用户与 company_id=1 相关的数据库内容,以及我返回的 JSON GET在用户身上。请注意,company=null。那就是问题所在。我做错了什么吗?
Roo 脚本
jpa setup --provider HIBERNATE --database MYSQL
--userName pivot --password pivot --databaseName testdb
entity jpa --class ~.model.MyUser
field string --fieldName firstName --notNull
field string --fieldName lastName --notNull
entity jpa --class ~.model.Company
field string --fieldName name –notNull
field set --fieldName users --type ~.model.MyUser --cardinality ONE_TO_MANY
--mappedBy company --comment "Users" --notNull false
repository jpa --all --package ~.repository
service --all --apiPackage ~.service.api --implPackage ~.service.impl
web mvc setup
/* ThymeLeaf view layer */
web mvc view setup --type THYMELEAF
web mvc templates setup --type THYMELEAF
web mvc controller --all --package ~.web --responseType THYMELEAF
/* JSON Rest controllers */
web mvc controller --all --responseType JSON --pathPrefix /json
web mvc finder --all --responseType THYMELEAF
web mvc finder --all --responseType JSON
数据库
mysql> select * from my_user;
+----+------------+-----------+---------+------------+
| id | first_name | last_name | version | company_id |
+----+------------+-----------+---------+------------+
| 1 | First | Last | 0 | 1 |
+----+------------+-----------+---------+------------+
1 row in set (0.00 sec)
JSON
{
"content": [
{
"id": 1,
"version": 0,
"firstName": "First",
"lastName": "Last",
"company": null
}
],
"last": true,
"totalPages": 1,
"totalElements": 1,
"size": 20,
"number": 0,
"first": true,
"numberOfElements": 1,
"sort": null
}
由 Spring Roo 2.0 生成的关系默认设置为 Lazy 以防止数据过载。请记住,Spring Roo 尝试尽可能地应用最佳实践。您可以在 MyUser.java
实体中看到:
@ManyToOne(fetch = FetchType.LAZY)
@EntityFormat
private Company company;
因此,当您获取MyUser
实体的所有记录时,默认情况下不会加载与Compny的关系。
但是,如果您知道要获取此信息,则应通过 Spring Roo 自定义生成的代码。请按照以下步骤操作:
在 MyUserRepositoryImpl
class 中声明的方法 findAll
进行推送。为此,请执行以下命令:
push-in --class ~.repository.MyUserRepositoryImpl --method findAll(GlobalSearch,Pageable)
之后,打开 MyUserRepositoryImpl.java
class 并更改默认查询以使用 Company
执行左连接。为此,请更改生成的代码:
JPQLQuery<MyUser> query = from(myUser);
给这个:
JPQLQuery<MyUser> query = from(myUser).leftJoin(myUser.company).fetchJoin();
使用尝试获取单个项目而不是列表时使用的 findOne
方法重复该过程。在这种情况下,您应该在 MyUserRepositoryCustom
接口中定义 findOne
方法,然后在 MyUserRepositoryImpl
.
通过上述修改,当您使用GET
操作访问urlhttp://localhost:8080/json/myusers/
时,您应该能够获得以下JSON:
{
"content": [
{
"id": 1,
"version": 0,
"firstName": "test",
"lastName": "test",
"company": {
"id": 1,
"version": 0,
"name": "aaa"
}
}
],
"last": true,
"totalPages": 1,
"totalElements": 1,
"sort": null,
"numberOfElements": 1,
"first": true,
"size": 20,
"number": 0
}
作为建议,我不得不说,在 JSON 响应中使用具有关系的实体时应该小心。如果某个实体与与第一个实体相关的另一个实体相关,也许您可以获得循环关系。您应该 return 一个 实体投影 而不是 return 您 JSON 响应中的完整实体,它只显示相关元素的标识符而不是整个相关实体。
希望对您有所帮助,