我看到了几个类似的问题,但没有答案对我有用。 我正在努力将现有项目转换为使用Hibernate。我正在使用Mysql作为数据库。我有一个这样的课:
@Entity
@Table(name = "user")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "user_id")
private Long userId;
@ManyToOne
@JoinColumn(name = "group_id_user")
private Group group;
@Column(name = "name")
private String name;
...
// getters and setters....
}
和这样的课程:
@Entity
@Table(name = "group")
public class Group {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "group_id")
private Long groupId;
@Column(name="group_name")
private String groupName;
...
// getters and setters....
}
当我从数据库中获取User
项时,我将其转换为JSON并以此格式得到结果:
{
"user": {
"userId": 1,
"group": {
"groupId": 3,
"groupName": "Group Three",
},
"name": "John Doe",
}
}
在我的例子中,Group
对象实际上比这个例子大得多,并且还包含对另一个表的引用(即Group
有一个SomeOtherClass
对象)。我希望最终得到如下内容:
{
"user": {
"userId": 1,
"groupId": 3,
"name": "John Doe",
}
}
有没有办法在我的JSON响应中获取groupId而不是整个Group
对象?
我尝试将FetchType.Lazy添加到我的用户类
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "group_id_user")
private Group group;
但是当我尝试将User
对象转换为Json时,我收到以下错误:
error: Errorjava.lang.UnsupportedOperationException: Attempted to serialize java.lang.Class: org.hibernate.proxy.HibernateProxy. Forgot to register a type adapter?
我发现this answer摆脱了错误,但是JSON对象与我添加FetchType.LAZY
之前完全相同。它似乎以某种方式转换为JSON添加了FetchType.LAZY
忽略的值。
我正在使用转换为JSON,如下所示:
GsonBuilder b = new GsonBuilder();
Gson gson = b.create();
//b.registerTypeAdapterFactory(HibernateProxyTypeAdapter.FACTORY);
com.google.gson.JsonArray jsonArray = gson.toJsonTree(out).getAsJsonArray();
答案 0 :(得分:1)
如果我错了,请纠正我,因为我不熟悉休眠。根据我迄今为止的经验,是的,可以只发送对象ID而不是发送整个对象详细信息作为响应。使用@JsonIdentityReference
和@JsonIdentityInfo
查找documentation here
以下是为我工作的示例代码:
小组课程
@Entity
@Table(name = "group")
public class Group {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "group_id")
private Long groupId;
@Column(name="group_name")
private String groupName;
...
// getters and setters....
}
用户类
@Entity
@Table(name = "user")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "user_id")
private Long userId;
@ManyToOne
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "group_id")
@JsonIdentityReference(alwaysAsId = true)
@JoinColumn(name = "group_id_user")
private Group group;
...
// getters and setters....
}
结果
{ " userId":1, " group":1, "名称":"样本用户" }
我使用以下代码转换JSON
ObjectMapper mapper = new ObjectMapper();
try {
json = mapper.writeValue(user);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
我找到了我的问题here
的解决方案答案 1 :(得分:0)
选项1:(来自@ JBNizet'评论)
创建表示API输出的类(DTO),将实体转换为这些DTO类的实例,并使用Gson将DTO序列化为JSON。好的REST框架会自动为您完成最后一部分。
对于此示例,您可以创建一个如下所示的UserItem类:
public class UserItem {
private Long userId;
private Long groupId;
private String name;
...
// getters and setters....
}
然后您需要一个将User实体转换为UserItem的方法:
public UserItem UserToUserItem(User user) {
UserItem userItem = new UserItem();
userItem.setUserId(user.getUserId());
userItem.setGroupId(user.getGroup().getGroupId());
userItem.setName(user.getName());
return userItem;
}
在您的回复中使用userItem。
选项2:
更新:将选项2更新为可行的内容
如果您不想为每个实体类编写DTO,因为(如本例所示)唯一需要更改的字段是groupId的Group对象,您可以创建ExclusionStrategy
并使用{ {1}}注释如下:
首先创建一个实现@Expose
ExclusionStrategy
然后将public class SerializeExclusionStrat implements ExclusionStrategy {
@Override
public boolean shouldSkipField(FieldAttributes fieldAttributes) {
final Expose expose = fieldAttributes.getAnnotation(Expose.class);
return expose != null && !expose.serialize();
}
@Override
public boolean shouldSkipClass(Class<?> aClass) {
return false;
}
}
@Entity
@Table(name = "user")
public class User {
注释添加到User类。添加附加字段@Expose
将允许在查询和json响应中返回groupId。只需确保使用groupId
和updatable=false
标记groupId。
insertable=false
然后在创建Gson时设置排除策略:
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "user_id")
private Long userId;
@ManyToOne
@JoinColumn(name = "group_id_user")
@Expose(serialize = false)
private Group group;
@Column(name = "group_id_user", updatable = false, insertable = false)
private Long groupId;
@Column(name = "name")
private String name;
...
// getters and setters....
}