如何对可以为空的列使用休眠延迟加载
How to use hibernate lazy loading with column that can be null
这是我的实体:
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "name")
private String name;
@Column(name = "surname")
private String surname;
@ManyToOne(fetch = FetchType.LAZY, cascade=CascadeType.MERGE)
@JoinColumn(name = "id_city")
private City city;
//...
}
在我的存储库中我有:
public interface UserRepository extends JpaRepository<User, Long>{
@Query("SELECT u FROM User u JOIN FETCH u.city")
public List<User> findAllUserForApi();
}
如果 table 中有任何城市,findAllUserForApi()
会显示有关用户的完整信息:
[{"id":1,"name":"John","surname":"Pillman","city":{"id":1,"name":"New York"}]
如果没有城市,我想至少得到[{"id":1,"name":"John","surname":"Pillman","city":null]
但是我什么都没有:[]
请帮帮我。
为什么要在这里写自定义查询。你不需要。
首先你必须遵循一般惯例:
@ManyToOne(fetch = FetchType.LAZY, cascade=CascadeType.MERGE)
@JoinColumn(name = "CITY_ID")
private City city;
...
这里JPA显示了与用户相关的所有信息。
public interface UserRepository extends JpaRepository<User, Long>{
public List<User> findAll();
}
您似乎在尝试对预定义查询使用延迟加载,我认为这不会奏效。
请看,您查询中的 JOIN FETCH
状态如下:
Get all the Users which has u.City
因此,如果您没有用户的 u.City
,return 将为空。
更多 info Join
和 Fetch
你真正想要的是:
public User findUserByID(Long userId)
{
Session session = sessionFactory.getCurrentSession();
User user = (Users) session.createCriteria(User.class).add(Restrictions.idEq(userId)).uniqueResult();
// this will force SQL to execute the query that will join with the user's city and populate
// the appropriate information into the user object.
Hibernate.initialize(user.geCity());
return user;
}
如果u.City
是NULL
,它将return一个NULL
。而 User
对象包含数据。
或者您的情况 查找所有用户 :
public List<User> findUserByID(Long userId)
{
Session session = sessionFactory.getCurrentSession();
List<User> users = (List<User>) session.createCriteria(User.class);
// this will force SQL to execute the query that will join with the user's city and populate
// the appropriate information into the user object.
for (User user : users)
Hibernate.initialize(user.geCity());
return user;
}
注意:
我没有测试代码,这是伪代码,因此您可能需要更改其中的一些内容。
鉴于您已经在使用自定义查询,最简单的解决方案是 LEFT JOIN FETCH:
@Query("SELECT u FROM User u LEFT JOIN FETCH u.city")
这样无论有没有城市,所有用户都会被加载;对于那些拥有城市的人,它将在 user.getCity()
.
之前提供
这是我的实体:
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "name")
private String name;
@Column(name = "surname")
private String surname;
@ManyToOne(fetch = FetchType.LAZY, cascade=CascadeType.MERGE)
@JoinColumn(name = "id_city")
private City city;
//...
}
在我的存储库中我有:
public interface UserRepository extends JpaRepository<User, Long>{
@Query("SELECT u FROM User u JOIN FETCH u.city")
public List<User> findAllUserForApi();
}
如果 table 中有任何城市,findAllUserForApi()
会显示有关用户的完整信息:
[{"id":1,"name":"John","surname":"Pillman","city":{"id":1,"name":"New York"}]
如果没有城市,我想至少得到[{"id":1,"name":"John","surname":"Pillman","city":null]
但是我什么都没有:[]
请帮帮我。
为什么要在这里写自定义查询。你不需要。
首先你必须遵循一般惯例:
@ManyToOne(fetch = FetchType.LAZY, cascade=CascadeType.MERGE)
@JoinColumn(name = "CITY_ID")
private City city;
...
这里JPA显示了与用户相关的所有信息。
public interface UserRepository extends JpaRepository<User, Long>{
public List<User> findAll();
}
您似乎在尝试对预定义查询使用延迟加载,我认为这不会奏效。
请看,您查询中的 JOIN FETCH
状态如下:
Get all the Users which has u.City
因此,如果您没有用户的 u.City
,return 将为空。
更多 info Join
和 Fetch
你真正想要的是:
public User findUserByID(Long userId)
{
Session session = sessionFactory.getCurrentSession();
User user = (Users) session.createCriteria(User.class).add(Restrictions.idEq(userId)).uniqueResult();
// this will force SQL to execute the query that will join with the user's city and populate
// the appropriate information into the user object.
Hibernate.initialize(user.geCity());
return user;
}
如果u.City
是NULL
,它将return一个NULL
。而 User
对象包含数据。
或者您的情况 查找所有用户 :
public List<User> findUserByID(Long userId)
{
Session session = sessionFactory.getCurrentSession();
List<User> users = (List<User>) session.createCriteria(User.class);
// this will force SQL to execute the query that will join with the user's city and populate
// the appropriate information into the user object.
for (User user : users)
Hibernate.initialize(user.geCity());
return user;
}
注意: 我没有测试代码,这是伪代码,因此您可能需要更改其中的一些内容。
鉴于您已经在使用自定义查询,最简单的解决方案是 LEFT JOIN FETCH:
@Query("SELECT u FROM User u LEFT JOIN FETCH u.city")
这样无论有没有城市,所有用户都会被加载;对于那些拥有城市的人,它将在 user.getCity()
.