[英]Convert native (join) queries in jpa (Hibernate) to json
I'm working on a spring boot project and am using jpa for data persistence. 我正在开发一个Spring Boot项目,并且正在使用jpa进行数据持久化。 Right now I have two tables that are related to each other, users and items. 现在,我有两个相互关联的表:用户和项目。 A user can own any number of items while an item can only owned by one user. 一个用户可以拥有任意数量的项目,而一个项目只能由一个用户拥有。
Here are my pojos: 这是我的pojos:
Users 用户
@Entity
@Table(name="users", uniqueConstraints = {
@UniqueConstraint(columnNames = {
"email"
})
})
@EntityListeners(AuditingEntityListener.class)
@JsonIgnoreProperties(value = {"createdAt", "updatedAt"}, allowGetters = true)
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotBlank
@NaturalId
@Column(unique = true)
private String email;
@NotBlank
@JsonIgnore
private String password;
@NotBlank
private String first_name;
@NotBlank
private String last_name;
@OneToMany(cascade = CascadeType.REMOVE, orphanRemoval = true)
@JsonIgnore
private Set<Item> items;
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "user_roles",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "role_id"))
private Set<Role> roles = new HashSet<>();
@Column(nullable = false, updatable = false)
@Temporal(TemporalType.TIMESTAMP)
@CreatedDate
private Date createdAt;
@Column(nullable = false)
@Temporal(TemporalType.TIMESTAMP)
@LastModifiedDate
private Date updatedAt;
Items 项目
@Entity
@Table(name="items")
@EntityListeners(AuditingEntityListener.class)
@JsonIgnoreProperties(value = {"createdAt", "updatedAt"}, allowGetters = true)
public class Item {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotBlank
@NotNull
private String name;
private String description;
@NotNull
private Date purchase_date;
private double price;
@ManyToOne(fetch = FetchType.LAZY, optional = true)
@JoinColumn(name = "owner", nullable = true)
private User owner;
@Column(nullable = false, updatable = false)
@Temporal(TemporalType.TIMESTAMP)
@CreatedDate
private Date createdAt;
@Column(nullable = false)
@Temporal(TemporalType.TIMESTAMP)
@LastModifiedDate
private Date updatedAt;
Now I want to get all items as RESTfull JSONs. 现在,我想将所有项目都获取为RESTfull JSON。 I need to join users with items so that I could get the following JSON: 我需要为用户添加项目,以便获得以下JSON:
{
"item_id":1,
"name":"item1",
"price":120.00,
etc .....
"owner_id":1,
"owner_name":"Jon"
etc ....
}
So I'm using a custom native query 所以我正在使用自定义的本机查询
SELECT i.id, i.name, i.description ...... u.id, u.name ..... from items i , users u where i.owner = u.id
And then I return query.getResultList()
however this returns and array of strings rather than a json like that 然后我返回query.getResultList()
但是这返回的是字符串数组,而不是像这样的json
[
[ 1 , "item1" , 120.00 , ..... , 1 , "Jon" , ....]
[ 2 , "item2" , 420.00 .... ]
etc...
]
How can I cast the returned object to either a JSON directly or to a list of maps that maps the column name to the value and then convert that to JSON? 如何将返回的对象直接转换为JSON或映射到将列名映射到值的映射列表,然后将其转换为JSON?
You could use the constructor expression to create a DTO (Data Transfer Object) that contains the data you need. 您可以使用构造函数表达式创建一个包含所需数据的DTO(数据传输对象)。
package dto;
public class ItemDTO {
private final Long item_id;
private final String name;
private final Long owner_id;
private final String owner_name;
public ItemDTO(Long item_id, String name, Long owner_id, String owner_name) {
// set the fields
}
// getters
}
And then use this DTO in a constructor expression query (important note: this only works with a JPQL query not a native query) 然后在构造函数表达式查询中使用此DTO(重要说明:这仅适用于JPQL查询而不适用于本机查询)
SELECT new dto.ItemDTO(i.id, i.name, i.owner.id, i.owner.name) from Item i where i.owner.id = u.id
This DTO can the be used to serialize to JSON. 此DTO可用于序列化为JSON。
Read more about the construtor expression here: https://vladmihalcea.com/the-best-way-to-map-a-projection-query-to-a-dto-with-jpa-and-hibernate/ 在此处阅读有关构造函数表达式的更多信息: https : //vladmihalcea.com/the-best-way-to-map-a-projection-query-to-a-dto-with-jpa-and-hibernate/
You can use this, there is no need for new DTO on every request. 您可以使用它,不需要在每个请求上都使用新的DTO。
@SuppressWarnings("unchecked")
public static List<ObjectNode> getQueryResult(EntityManager entityManager, String nativeQuery, Object... parameters) {
Query localQuery = entityManager.createNativeQuery(nativeQuery,Tuple.class);
for(int i = 0; i < parameters.length; i++)
localQuery.setParameter(i+1, parameters[i]);
return toJson(localQuery.getResultList());
}
private static List<ObjectNode> toJson(List<Tuple> results) {
List<ObjectNode> json = new ArrayList<>();
ObjectMapper mapper = new ObjectMapper();
for (Tuple tuple : results)
{
List<TupleElement<?>> cols = tuple.getElements();
ObjectNode node = mapper.createObjectNode();
for (TupleElement col : cols)
node.put(col.getAlias(), tuple.get(col.getAlias()).toString());
json.add(node);
}
return json;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.