Spring 引导 - 事务管理不工作
Spring Boot - Transaction Management is not working
期望 - 延迟加载不应该在事务范围之外工作(例如在 rest 控制器中),但它有效。
问题是 在 @Transactional 中,它在我的配置中没有被 spring 应用程序使用。我该如何解决?
...Rest 控制器没有任何事务性方法,它仅使用指定的服务来加载实体。如果未在服务中加载,则依赖集合应为空。
应用程序启动器class:
@SpringBootApplication
@EntityScan("com.vl.pmanager.domain.model")
@EnableJpaRepositories("com.vl.pmanager.domain.repository")
@EnableTransactionManagement
public class ProjectManagerApplication {
public static void main(String[] args) {
SpringApplication.run(ProjectManagerApplication.class, args);
}
}
我知道 spring 启动自动配置存储库和扫描实体,但我希望添加...
@EntityScan("com.vl.pmanager.domain.model")
@EnableJpaRepositories("com.vl.pmanager.domain.repository")
我也尝试将 @Transactional 添加到存储库界面,但它对我不起作用
package com.vl.pmanager.domain.repository;
import com.vl.pmanager.domain.model.Tag;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
@Repository
@Transactional
public interface TagRepository extends PagingAndSortingRepository<Tag, Long> {
}
所以我从存储库中删除了 @Transactional,创建了其他服务层以使用注释管理它并将服务注入控制器:
package com.vl.pmanager.domain.db.service.api;
import com.vl.pmanager.domain.model.Tag;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
public interface ITagManager {
Page<Tag> findAll(Pageable pageable);
Tag findOne(Long id);
}
// ======================== TAG SERVICE WRAPPED WITH TRANSACTION ==========================
package com.vl.pmanager.domain.db.service;
import com.vl.pmanager.domain.db.service.api.ITagManager;
import com.vl.pmanager.domain.model.Tag;
import com.vl.pmanager.domain.repository.TagRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional
public class TagManager implements ITagManager {
@Autowired
private TagRepository tagRepository;
@Override
public Page<Tag> findAll(Pageable pageable) {
return tagRepository.findAll(pageable);
}
@Override
public Tag findOne(Long id) {
return tagRepository.findOne(id);
}
}
// ====================== REST CONTROLLER ============================
package com.vl.pmanager.web;
import com.vl.pmanager.domain.db.service.api.ITagManager;
import com.vl.pmanager.domain.model.Tag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping(value = "/tags")
public class TagController {
private static final int DEFAULT_PAGE_SIZE = 50;
@Autowired
private ITagManager tagManager;
@RequestMapping(method = RequestMethod.GET, consumes = MediaType.ALL_VALUE)
public Page<Tag> getTags(@PageableDefault(size = DEFAULT_PAGE_SIZE) Pageable pageable) {
return tagManager.findAll(pageable);
}
@RequestMapping(value = "/{id}", method = RequestMethod.GET, consumes = MediaType.ALL_VALUE)
public Tag getTag(@PathVariable("id") Long id) {
return tagManager.findOne(id);
}
}
标记实体有一个字段 Set projectInfo 映射到具有 @ManyToMany 与 FetchType fetch() 关系的其他实体默认 LAZY; 所以 return 结果不能包含依赖实体,但它是。
我还监控了数据库日志:
// make request - load data using db service to controller level
Hibernate: select count(tag0_.id) as col_0_0_ from tag tag0_
Hibernate: select tag0_.id as id1_6_, tag0_.description as descript2_6_, tag0_.name as name3_6_ from tag tag0_ limit ?
// converting data to JSON automatically
Hibernate: select projectinf0_.tags as tags1_6_0_, projectinf0_.project_info as project_2_7_0_, projectinf1_.id as id1_4_1_, projectinf1_.description as descript2_4_1_, projectinf1_.name as name3_4_1_ from tag_project_info projectinf0_ inner join project_info projectinf1_ on projectinf0_.project_info=projectinf1_.id where projectinf0_.tags=?
Hibernate: select projectinf0_.tags as tags1_6_0_, projectinf0_.project_info as project_2_7_0_, projectinf1_.id as id1_4_1_, projectinf1_.description as descript2_4_1_, projectinf1_.name as name3_4_1_ from tag_project_info projectinf0_ inner join project_info projectinf1_ on projectinf0_.project_info=projectinf1_.id where projectinf0_.tags=?
Hibernate: select projectinf0_.tags as tags1_6_0_, projectinf0_.project_info as project_2_7_0_, projectinf1_.id as id1_4_1_, projectinf1_.description as descript2_4_1_, projectinf1_.name as name3_4_1_ from tag_project_info projectinf0_ inner join project_info projectinf1_ on projectinf0_.project_info=projectinf1_.id where projectinf0_.tags=?
Hibernate: select projectinf0_.tags as tags1_6_0_, projectinf0_.project_info as project_2_7_0_, projectinf1_.id as id1_4_1_, projectinf1_.description as descript2_4_1_, projectinf1_.name as name3_4_1_ from tag_project_info projectinf0_ inner join project_info projectinf1_ on projectinf0_.project_info=projectinf1_.id where projectinf0_.tags=?
Hibernate: select projectinf0_.tags as tags1_6_0_, projectinf0_.project_info as project_2_7_0_, projectinf1_.id as id1_4_1_, projectinf1_.description as descript2_4_1_, projectinf1_.name as name3_4_1_ from tag_project_info projectinf0_ inner join project_info projectinf1_ on projectinf0_.project_info=projectinf1_.id where projectinf0_.tags=?
而且我知道只有 5 个额外请求,因为我只有 5 个依赖于 tag project_info。
因此,作为结论,我的事务级别不管理事务。
...我检查了数据源和注入 bean 的 transactionManager - 已经创建了。
没有错误,开始时间或 运行 时间没有警告...
@JBNizet
这不是交易问题。在文档中查找 属性 spring.jpa.open-in-view 如果您不想要它,请将其设置为 false
我已添加此答案以将问题标记为已关闭。如果我关闭 jpa open in view 交易就像我预期的那样工作。
版主请将作者回答更改为@JBNizet
期望 - 延迟加载不应该在事务范围之外工作(例如在 rest 控制器中),但它有效。
问题是 在 @Transactional 中,它在我的配置中没有被 spring 应用程序使用。我该如何解决?
...Rest 控制器没有任何事务性方法,它仅使用指定的服务来加载实体。如果未在服务中加载,则依赖集合应为空。
应用程序启动器class:
@SpringBootApplication
@EntityScan("com.vl.pmanager.domain.model")
@EnableJpaRepositories("com.vl.pmanager.domain.repository")
@EnableTransactionManagement
public class ProjectManagerApplication {
public static void main(String[] args) {
SpringApplication.run(ProjectManagerApplication.class, args);
}
}
我知道 spring 启动自动配置存储库和扫描实体,但我希望添加...
@EntityScan("com.vl.pmanager.domain.model")
@EnableJpaRepositories("com.vl.pmanager.domain.repository")
我也尝试将 @Transactional 添加到存储库界面,但它对我不起作用
package com.vl.pmanager.domain.repository;
import com.vl.pmanager.domain.model.Tag;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
@Repository
@Transactional
public interface TagRepository extends PagingAndSortingRepository<Tag, Long> {
}
所以我从存储库中删除了 @Transactional,创建了其他服务层以使用注释管理它并将服务注入控制器:
package com.vl.pmanager.domain.db.service.api;
import com.vl.pmanager.domain.model.Tag;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
public interface ITagManager {
Page<Tag> findAll(Pageable pageable);
Tag findOne(Long id);
}
// ======================== TAG SERVICE WRAPPED WITH TRANSACTION ==========================
package com.vl.pmanager.domain.db.service;
import com.vl.pmanager.domain.db.service.api.ITagManager;
import com.vl.pmanager.domain.model.Tag;
import com.vl.pmanager.domain.repository.TagRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional
public class TagManager implements ITagManager {
@Autowired
private TagRepository tagRepository;
@Override
public Page<Tag> findAll(Pageable pageable) {
return tagRepository.findAll(pageable);
}
@Override
public Tag findOne(Long id) {
return tagRepository.findOne(id);
}
}
// ====================== REST CONTROLLER ============================
package com.vl.pmanager.web;
import com.vl.pmanager.domain.db.service.api.ITagManager;
import com.vl.pmanager.domain.model.Tag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping(value = "/tags")
public class TagController {
private static final int DEFAULT_PAGE_SIZE = 50;
@Autowired
private ITagManager tagManager;
@RequestMapping(method = RequestMethod.GET, consumes = MediaType.ALL_VALUE)
public Page<Tag> getTags(@PageableDefault(size = DEFAULT_PAGE_SIZE) Pageable pageable) {
return tagManager.findAll(pageable);
}
@RequestMapping(value = "/{id}", method = RequestMethod.GET, consumes = MediaType.ALL_VALUE)
public Tag getTag(@PathVariable("id") Long id) {
return tagManager.findOne(id);
}
}
标记实体有一个字段 Set projectInfo 映射到具有 @ManyToMany 与 FetchType fetch() 关系的其他实体默认 LAZY; 所以 return 结果不能包含依赖实体,但它是。
我还监控了数据库日志:
// make request - load data using db service to controller level
Hibernate: select count(tag0_.id) as col_0_0_ from tag tag0_
Hibernate: select tag0_.id as id1_6_, tag0_.description as descript2_6_, tag0_.name as name3_6_ from tag tag0_ limit ?
// converting data to JSON automatically
Hibernate: select projectinf0_.tags as tags1_6_0_, projectinf0_.project_info as project_2_7_0_, projectinf1_.id as id1_4_1_, projectinf1_.description as descript2_4_1_, projectinf1_.name as name3_4_1_ from tag_project_info projectinf0_ inner join project_info projectinf1_ on projectinf0_.project_info=projectinf1_.id where projectinf0_.tags=?
Hibernate: select projectinf0_.tags as tags1_6_0_, projectinf0_.project_info as project_2_7_0_, projectinf1_.id as id1_4_1_, projectinf1_.description as descript2_4_1_, projectinf1_.name as name3_4_1_ from tag_project_info projectinf0_ inner join project_info projectinf1_ on projectinf0_.project_info=projectinf1_.id where projectinf0_.tags=?
Hibernate: select projectinf0_.tags as tags1_6_0_, projectinf0_.project_info as project_2_7_0_, projectinf1_.id as id1_4_1_, projectinf1_.description as descript2_4_1_, projectinf1_.name as name3_4_1_ from tag_project_info projectinf0_ inner join project_info projectinf1_ on projectinf0_.project_info=projectinf1_.id where projectinf0_.tags=?
Hibernate: select projectinf0_.tags as tags1_6_0_, projectinf0_.project_info as project_2_7_0_, projectinf1_.id as id1_4_1_, projectinf1_.description as descript2_4_1_, projectinf1_.name as name3_4_1_ from tag_project_info projectinf0_ inner join project_info projectinf1_ on projectinf0_.project_info=projectinf1_.id where projectinf0_.tags=?
Hibernate: select projectinf0_.tags as tags1_6_0_, projectinf0_.project_info as project_2_7_0_, projectinf1_.id as id1_4_1_, projectinf1_.description as descript2_4_1_, projectinf1_.name as name3_4_1_ from tag_project_info projectinf0_ inner join project_info projectinf1_ on projectinf0_.project_info=projectinf1_.id where projectinf0_.tags=?
而且我知道只有 5 个额外请求,因为我只有 5 个依赖于 tag project_info。 因此,作为结论,我的事务级别不管理事务。 ...我检查了数据源和注入 bean 的 transactionManager - 已经创建了。 没有错误,开始时间或 运行 时间没有警告...
@JBNizet
这不是交易问题。在文档中查找 属性 spring.jpa.open-in-view 如果您不想要它,请将其设置为 false
我已添加此答案以将问题标记为已关闭。如果我关闭 jpa open in view 交易就像我预期的那样工作。
版主请将作者回答更改为@JBNizet