如何在JSON响应中仅获取实体ID而不是整个实体

时间:2017-09-07 17:03:03

标签: java json hibernate annotations

我看到了几个类似的问题,但没有答案对我有用。 我正在努力将现有项目转换为使用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();

2 个答案:

答案 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。只需确保使用groupIdupdatable=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....   
}