Hibernate多对多关系查询没有其集合元素的实体
Hibernate many-to-many relationship query the Entity without its collection elements
描述:我在 User 和 Shoplist 实体之间建立了多对多关系。我正在休息 api,我只想在有人对 /users/{id} 进行 GET 时查询用户。如果我尝试从数据库中获取用户,它会说购物清单的集合没有初始化,但这正是我想要的,只有没有他的购物清单的用户。如果我得到用户的购物清单,它工作正常,但这不是我想要的。
我的实体:
User.java
@Entity
public class User implements Serializable {
@Id
@GeneratedValue
private int id;
private String name;
private String lastname;
@Column(nullable = false)
private String email;
private String password;
@Column(nullable = true) //maybe set @ColumnDefault()
private URL avatar;
@JsonIgnoreProperties("users")
@JoinTable(
name = "User_Shoplist",
joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "shoplist_id", referencedColumnName = "id")
)
@ManyToMany
private Set<Shoplist> shoplists = new HashSet<>();
// getters and setter
Shoplist.java
@Entity
public class Shoplist implements Serializable {
@Id
@GeneratedValue
private int id;
private String name;
@JsonIgnoreProperties("shoplists")
@ManyToMany(mappedBy = "shoplists")
private Set<User> users = new HashSet<>();
// getters and setter
Controller.java
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response index() {
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
try {
session.beginTransaction();
User u1 = session.get(User.class, 1);
session.getTransaction().commit();
session.close();
return Response.status(200).entity(u1).build();
} catch(Exception e) {
session.getTransaction().rollback();
return Response.status(Response.Status.BAD_REQUEST).build();
}
}
目标 :正如我之前所说,我想 return 关于用户的信息,但没有他的所有购物清单。
当您的实体序列化为 JSON 时,将调用所有 getter(包括 getShoplists
),并且因为这是在事务之外发生的,所以您会得到 LazyInitializationException。这是实体对象永远不应该离开服务的原因之一。
您需要创建 DTO(数据传输对象),仅分配您需要发送的那些值(所有仍在交易中的值),然后发送 dto 而不是实体。
例如
public class UserDto {
private int id;
private String name;
private String lastname;
private String email;
// btw, this is probably not a good idea to send user password to the client
// ...
// getters and setters
}
session.beginTransaction();
User u1 = session.get(User.class, 1);
UserDto dto = new UserDto();
dto.setName(u1.getName());
// map other values
session.getTransaction().commit();
session.close();
return Response.status(200).body(dto).build();
描述:我在 User 和 Shoplist 实体之间建立了多对多关系。我正在休息 api,我只想在有人对 /users/{id} 进行 GET 时查询用户。如果我尝试从数据库中获取用户,它会说购物清单的集合没有初始化,但这正是我想要的,只有没有他的购物清单的用户。如果我得到用户的购物清单,它工作正常,但这不是我想要的。
我的实体:
User.java
@Entity
public class User implements Serializable {
@Id
@GeneratedValue
private int id;
private String name;
private String lastname;
@Column(nullable = false)
private String email;
private String password;
@Column(nullable = true) //maybe set @ColumnDefault()
private URL avatar;
@JsonIgnoreProperties("users")
@JoinTable(
name = "User_Shoplist",
joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "shoplist_id", referencedColumnName = "id")
)
@ManyToMany
private Set<Shoplist> shoplists = new HashSet<>();
// getters and setter
Shoplist.java
@Entity
public class Shoplist implements Serializable {
@Id
@GeneratedValue
private int id;
private String name;
@JsonIgnoreProperties("shoplists")
@ManyToMany(mappedBy = "shoplists")
private Set<User> users = new HashSet<>();
// getters and setter
Controller.java
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response index() {
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
try {
session.beginTransaction();
User u1 = session.get(User.class, 1);
session.getTransaction().commit();
session.close();
return Response.status(200).entity(u1).build();
} catch(Exception e) {
session.getTransaction().rollback();
return Response.status(Response.Status.BAD_REQUEST).build();
}
}
目标 :正如我之前所说,我想 return 关于用户的信息,但没有他的所有购物清单。
当您的实体序列化为 JSON 时,将调用所有 getter(包括 getShoplists
),并且因为这是在事务之外发生的,所以您会得到 LazyInitializationException。这是实体对象永远不应该离开服务的原因之一。
您需要创建 DTO(数据传输对象),仅分配您需要发送的那些值(所有仍在交易中的值),然后发送 dto 而不是实体。
例如
public class UserDto {
private int id;
private String name;
private String lastname;
private String email;
// btw, this is probably not a good idea to send user password to the client
// ...
// getters and setters
}
session.beginTransaction();
User u1 = session.get(User.class, 1);
UserDto dto = new UserDto();
dto.setName(u1.getName());
// map other values
session.getTransaction().commit();
session.close();
return Response.status(200).body(dto).build();