描述:我与用户和商店列表实体之间存在多对多关系。我正在制作一个REST API,当有人对/ users / {id}进行GET时,我只想查询User。如果我试图从数据库中获取用户,它说商店列表的集合没有被初始化,那正是我想要的,只有没有他的商店列表的用户。如果我得到用户的购物清单,则可以正常工作,但这不是我想要的。
我的实体:
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();
}
}
目标:正如我之前所说,我想返回有关用户的信息,而没有他的所有商店清单。
当您的实体序列化为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();
Baeldung's tutorial on this using ModelMapperA good alternative which is Mapstruct