【问题标题】:Spring JPA repository method does'nt set values of entity after querySpring JPA 存储库方法在查询后不设置实体的值
【发布时间】:2015-02-13 14:56:17
【问题描述】:

页面实体。

@Entity
@Table(name = "pages", schema = "admin")
public class Page implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", unique = true)
    private Integer id;

    @Column(name = "name")
    private String name;


    @ManyToOne(targetEntity = Partition.class, fetch = FetchType.LAZY)
    private Partition partition;

    @Column(name = "is_startable")
    private Boolean isStartable;

    @Column(name = "priority")
    private Integer priority;

    @Column(name = "prefix_granted_authority")
    private String prefixGrantedAuthority;

    @OneToMany(mappedBy = "page", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
    private List<Permission> permissions;

    @Column(name = "link", unique = true)
    private String link;

页面存储库

    List<Page> findByPermissionsGroupsOrderByPartitionNameAscNameAsc(@Param(value = "group") Group group);

PageServiceImpl

    @Override
public Collection<Page> getAccessedPages(Group group) {
    try {
          List<Page> pages = pageRepository.findByPermissionsGroupsOrderByPartitionNameAscNameAsc(group);
        return pages;
    } catch (Exception ex) {
        logger.error("getPage error", ex);
        return null;
    }
}

getAccessedPages 返回页面实体的真实列表(非空),但实体中的所有字段均为空。

为什么?

【问题讨论】:

  • 您是在事务内部还是外部访问这些实体?
  • 如果没有找到结果,Repository 方法将返回一个空列表(不是 null,但没有实体)。你确定你得到的是真实的实体吗?结果列表大小是多少?
  • 未使用事务且列表大小不为0,它反映了真实的查询结果大小。
  • 如何检查字段是否为空?在调试器中?例如,如果您打印page.getId(),它仍然为空吗?调试器大多使用反射来显示字段值,有时只有在调用它们的 getter 方法后才会初始化。
  • 是的,Eclipse Luna 中的调试器。实际上在控制器中我有相同的结果。从服务返回的页面仍然由空值填充。毕竟,Jackson 将这个列表序列化为 [{},{},{},{}]。

标签: java spring jpa


【解决方案1】:

我前段时间也遇到过这个问题,好像spring data做了一些惰性实例化。
因此,如果您没有在交易中访问此字段,它们将保留null。在你调用这个请求的方法上添加注解@Transactional,问题就解决了。

【讨论】:

  • @wolandec 我找不到任何参考供您查看,但对我来说,当您获取数据时,spring 数据不会返回您的实体而是它的代理。在您实际向它们请求一些数据之前,不会填充代理。事务完成后,不再管理实体。
  • 好的,如果没有@Transactional 注释,该服务中的其他方法在相同条件下也能正常工作吗?
【解决方案2】:

我想扩展 @user902383 的答案,最终也解决了我的问题,但评论太长了。

在我的例子中,我有一个获取实体 Helper 的存储库方法,该方法在 @PostLoad 侦听器中调用,该侦听器使用 Helper 来计算填充另一个实体 Child 中的字段。监听器方法已经用org.springframework.transaction.annotation.Transactional注解了。

当被Child 的存储库调用时,它获取了一个所有字段都已填满的Helper 实体,但是当由具有子Child 的实体Parent 的存储库调用时,它获取了一个空的@987654331 @ 对象仅填充了 id,即使它已正确注释。

问题是我使用 this hack 访问 Spring @Component 之外的存储库(我无法将侦听器设为组件)。我怀疑当存储库不正确@Autowired 时,用于检测@Transactional 方法中何时取消引用字段的Spring 魔法不起作用。我仍然不知道为什么它在 Child 的存储库中有效,但在 Parent 中无效。

我对这个特定问题的解决方案是移动存储库调用并取消引用到@Service,它正确地@Autowires 存储库,并执行骇人听闻的静态调用来获取该服务,这无论如何都会产生更好的代码结构.

【讨论】:

    猜你喜欢
    • 2019-06-10
    • 2012-07-16
    • 2021-04-16
    • 2014-06-21
    • 1970-01-01
    • 2015-10-13
    • 1970-01-01
    • 2015-03-28
    • 2018-11-09
    相关资源
    最近更新 更多