Java 如何对可以为null的列使用hibernate延迟加载
这是我的实体:Java 如何对可以为null的列使用hibernate延迟加载,java,spring,hibernate,jpa,spring-data-jpa,Java,Spring,Hibernate,Jpa,Spring Data Jpa,这是我的实体: @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 =
@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();
}
如果没有城市,我想得到至少[{“id”:1,“name”:“John”,“姓氏”:“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();
}
public interface UserRepository扩展了JpaRepository{
公共列表findAll();
}
看起来您试图对预定义查询使用延迟加载,我认为这行不通
请参阅,查询中的连接获取
状态如下:
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的用户
因此,如果您没有用户的u.City
,则返回值将为空
有关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
,它将返回NULL
。而用户
对象包含数据
或者在您的情况下查找所有用户:
公共列表findUserByID(长用户ID)
{
Session Session=sessionFactory.getCurrentSession();
List users=(List)session.createCriteria(User.class);
//这将强制SQL执行查询,该查询将与用户的城市连接并填充
//将适当的信息导入用户对象。
for(用户:用户)
初始化(user.geCity());
返回用户;
}
注意:
我没有测试代码,这是伪代码,因此您可能需要对其进行一些更改
鉴于您已经在使用自定义查询,最简单的解决方案是左连接获取:
@查询(“从用户u中选择u左加入获取u.city”)
这样,所有用户都将被加载,无论他们是否拥有城市;对于那些拥有城市的用户,
user.getCity()
因为我不想从表中加载所有列。我有更多的列。我还有电话、地址……我不想在查询答案中看到它们。@TomWally如果你不想在json上看到,你可以使用Jsonignore注释。这样你可以显示特定的属性。是的,但Jsonignore没有选项。如果我想不想为具有优先级管理员的用户显示某些字段,如密码,但不想为具有优先级版主的用户显示。JsonIgnore没有给我机会向任何人显示这些字段。也许你可以尝试额外的DTO对象,并为每个用户标题分别显示属性。如果它看不到你的业务,当你返回类似密码的属性时,你可以n将它们设置为空。为什么不简单地使用左连接获取?太棒了!我会将其标记为答案。谢谢您,但左连接获取是正确的答案(@TomWally although'LEFT JOIN'将起作用。它不是延迟加载。它只是一个自定义查询。
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;
}