【问题标题】:Spring Data JPA findOne returns nullSpring Data JPA findOne 返回 null
【发布时间】:2017-02-14 18:27:44
【问题描述】:

我正在使用 Spring Data JPA,我遇到了一个非常奇怪的问题,即 findOne 方法返回 null,即使该行存在于 DB 中。

我有一个消费者线程,它从队列中获取一个 id,并尝试从始终返回 null 的 DB 中获取实体,但是如果我暂停线程(通过在方法调用之前放置断点),那么它会从 DB 中获取实体,但是在程序的正常执行中返回 null,我知道断点的东西听起来很奇怪,但它就是这样,可能是我遗漏了一些东西。我的代码如下所示:-

     if (id > 0) {
      employee = employeeService.get(id);
      if (employee == null) {
            logger.error(String.format("No employee found for id : %d",
                        id));
            return;
     }

我没有在“employeeService”中使用任何事务,因为它不是必需的,因为它是读取操作。

我的服务看起来像

public Employee get(long id) {
    return employeeDao.findOne(id);
}

我的模型看起来像:-

   @Entity
   @Table(name = "employee")
   @JsonInclude(JsonInclude.Include.NON_NULL)
   public class Employee implements Serializable {

   private static final long serialVersionUID = 1681182382236322985L;

     @Id
     @GeneratedValue(strategy = GenerationType.AUTO)
     private long id;

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

    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JoinColumn(name = "emplopyee_id")
    @Fetch(FetchMode.SELECT)
    private List<Address> addresses;

  // getter/setter and few fields have been omitted

}

谁能指出我错在哪里。

【问题讨论】:

  • 读取操作不需要事务是一个神话。每次访问 Hibernate 都应该有一个事务。隔离(ACID 中的 I)也很重要,并且需要事务。
  • 我尝试使用事务并将其标记为只读,但我仍然得到空值。
  • 能否在employeeService.get中显示相关代码和实体映射?
  • @Naros,更新问题
  • 如前所述,仅在事务结束后将消息放入队列,而不是在事务内部。如果你这样做,你就会得到你现在的行为。

标签: spring hibernate spring-data spring-data-jpa


【解决方案1】:

Spring 4.2 的方法是在 spring 组件上引入 @TransactionEventListener 注释方法来处理回调。然后,您只需发布一个事件并让事件框架完成它的工作:

// Spring component that handles repository interactions
@Component
public class ProducerService implements ApplicationContextAware {
  private ApplicationContext applicationContext;

  @Transactional
  public void doSomeThingAwesome(String data) {
    MyAwesome awesome = new MyAwesome( data );
    myAwesomeRepository.save( awesome );
    applicationContext.publishEvent( new MyAwesomeSaved( awesome.getId() ) );
  }
}

// Spring component that handles the AFTER_COMMIT transaction callback
// This component only fires when a MyAwesomeSaved event is published and
// the associated transaction it is published in commits successfully.
@Component
public class QueueIdentifierHandler {
  @TransactionalEventListener
  public void onMyAwesomeSaved(MyAwesomeSaved event) {
    Long entityId = event.getId();
    // post the entityId to your queue now
  }
}

【讨论】:

  • 哇,太好了,非常感谢您提供如此出色的解决方案。
猜你喜欢
  • 2018-02-26
  • 2017-08-06
  • 2015-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-13
相关资源
最近更新 更多