服务层在春季总是必须是事务性的吗?

时间:2019-05-09 13:09:58

标签: java spring spring-boot jpa transactional

我在春季有一个非常简单的应用程序,包括1个用于db表的模型类,1个jpa仓库类1个服务和1个控制器类。

我的服务类别是:

@Transactional
@Service
public class SomeService {

    private ServiceRepository serviceRepository;

    @Autowired
    public serviceService(ServiceRepository serviceRepository) {
        this.serviceRepository = serviceRepository;
    }


    public void getServiceById(Long id) {
        Model model = serviceRepository.getOne(id);
        return....
    }

}

它正在使用@Transactional注释。但是,如果我删除它,我会得到

  

org.hibernate.LazyInitializationException:无法初始化代理

如果我不希望使用任何事务方法或类该怎么办,为什么我必须使其成为事务性的?

1 个答案:

答案 0 :(得分:3)

发生此异常是因为您尝试访问未在事务内部加载的对象。

离开事务时,无法再从数据库加载对象。但是交易不是强制性的。

我认为您的对象具有OneToMany / ManyToMany关系,并且这些关系是lazyLoaded的。由于您的服务不是事务性的,因此与数据库的连接已关闭,您无法再访问对象。

您有2个选择:

  • 将“快速获取”设置为您的对象(您的对象始终会被加载)。
  • 使您的服务具有事务性(对象将按需加载)。

激活延迟加载(默认选项)时,应该注意性能问题。是否使用它确实取决于您的业务逻辑,但是最好不要对数据库具有多重访问。

您还可以检查Entity Graph以进行高级自定义: https://www.baeldung.com/jpa-entity-graph

此外,在开发时,请启用休眠SQL跟踪以查看后台发生了什么:https://www.mkyong.com/hibernate/hibernate-display-generated-sql-to-console-show_sql-format_sql-and-use_sql_comments/