无法通过hibernate search找到延迟初始化异常的解决方案
Can't find a solution to lazy initialization exception with hibernate search
我 运行 在 Spring 引导环境中使用休眠搜索进行搜索,但是在执行查询时我无法延迟初始化角色集合。
我已经尝试了其他类似问题中暴露的所有变体。我的实体与另外两个实体存在多对多关系。
@Entity
@Indexed
public class A extends AbstractAuditableEntity<D, Long> implements
Serializable {
@Column
@Field(index = Index.YES, analyze = Analyze.YES, store =
Store.NO)
private String name;
@ManyToMany(mappedBy = "a")
@IndexedEmbedded
private List<B> b;
@OneToMany(mappedBy = "a")
@IndexedEmbedded
private List<C> c;
}
我的控制器class:
@RestController
public class SearchController {
@Autowired
private SearchService searchService;
@GetMapping("/search")
public ResponseEntity<?> search(@RequestParam String terms){
List<A> aList = searchService.search(terms);
return aList.isEmpty() ? new ResponseEntity<>
(HttpStatus.NO_CONTENT) : new ResponseEntity<>(aList,
HttpStatus.OK);
}
}
我的服务class:
@Service
public class SearchService {
@Autowired
private aRepository aRepository;
@Transactional
public List<A> search(String terms) {
return aRepository.search(terms);
}
}
我的存储库层:
public interface ARepository extends JpaRepository<A, Long>,
IndexSearchARepository {
}
扩展接口:
@Transactional
public interface IndexSearchARepository {
public List<A> search(String terms);
}
好的部分,实施:
public class IndexSearchARepositoryImpl implements
IndexSearchARepository {
private final EntityManager entityManager;
@Autowired
public IndexSearchARepositoryImpl(EntityManager entityManager)
{
this.entityManager = entityManager;
}
@Override
@Transactional
public List<A> search(String terms) {
FullTextEntityManager fullTextEntityManager =
Search.getFullTextEntityManager(entityManager);
QueryBuilder queryBuilder =
fullTextEntityManager.getSearchFactory().buildQueryBuilder()
.forEntity(A.class).get();
Query luceneQuery = queryBuilder
.keyword()
.fuzzy()
.withEditDistanceUpTo(1)
.withPrefixLength(1)
.onFields("name")
.matching(terms)
.createQuery();
javax.persistence.Query jpaQuery = fullTextEntityManager
.createFullTextQuery(luceneQuery, A.class);
List<A> aList = null;
try {
aList = jpaQuery.getResultList();
} catch (NoResultException nre) {
log.debug(nre.getMessage());
}
return aList;
}
}
强调一下,如果我放置断点并逐步进行,它不会抛出异常。我不知道什么时候尝试访问之前会话关闭的关系,@Transactional 不应该处理这个?
输出:
"message": "Could not write JSON: failed to lazily initialize a
collection of role: com.xxxx.entity.A.b,
could not initialize proxy - no Session
Hibernate Session 存在于 @Transactional
的方法中。
在服务 class 之外传递实体是一种不好的做法,因为在离开您的 search
方法后会话将被关闭。另一方面,您的实体包含惰性初始化集合,一旦会话关闭就无法将其拉出。
好的做法是将实体映射到传输对象上,return那些传输对象在外面(不是原始实体)。
我 运行 在 Spring 引导环境中使用休眠搜索进行搜索,但是在执行查询时我无法延迟初始化角色集合。
我已经尝试了其他类似问题中暴露的所有变体。我的实体与另外两个实体存在多对多关系。
@Entity
@Indexed
public class A extends AbstractAuditableEntity<D, Long> implements
Serializable {
@Column
@Field(index = Index.YES, analyze = Analyze.YES, store =
Store.NO)
private String name;
@ManyToMany(mappedBy = "a")
@IndexedEmbedded
private List<B> b;
@OneToMany(mappedBy = "a")
@IndexedEmbedded
private List<C> c;
}
我的控制器class:
@RestController
public class SearchController {
@Autowired
private SearchService searchService;
@GetMapping("/search")
public ResponseEntity<?> search(@RequestParam String terms){
List<A> aList = searchService.search(terms);
return aList.isEmpty() ? new ResponseEntity<>
(HttpStatus.NO_CONTENT) : new ResponseEntity<>(aList,
HttpStatus.OK);
}
}
我的服务class:
@Service
public class SearchService {
@Autowired
private aRepository aRepository;
@Transactional
public List<A> search(String terms) {
return aRepository.search(terms);
}
}
我的存储库层:
public interface ARepository extends JpaRepository<A, Long>,
IndexSearchARepository {
}
扩展接口:
@Transactional
public interface IndexSearchARepository {
public List<A> search(String terms);
}
好的部分,实施:
public class IndexSearchARepositoryImpl implements
IndexSearchARepository {
private final EntityManager entityManager;
@Autowired
public IndexSearchARepositoryImpl(EntityManager entityManager)
{
this.entityManager = entityManager;
}
@Override
@Transactional
public List<A> search(String terms) {
FullTextEntityManager fullTextEntityManager =
Search.getFullTextEntityManager(entityManager);
QueryBuilder queryBuilder =
fullTextEntityManager.getSearchFactory().buildQueryBuilder()
.forEntity(A.class).get();
Query luceneQuery = queryBuilder
.keyword()
.fuzzy()
.withEditDistanceUpTo(1)
.withPrefixLength(1)
.onFields("name")
.matching(terms)
.createQuery();
javax.persistence.Query jpaQuery = fullTextEntityManager
.createFullTextQuery(luceneQuery, A.class);
List<A> aList = null;
try {
aList = jpaQuery.getResultList();
} catch (NoResultException nre) {
log.debug(nre.getMessage());
}
return aList;
}
}
强调一下,如果我放置断点并逐步进行,它不会抛出异常。我不知道什么时候尝试访问之前会话关闭的关系,@Transactional 不应该处理这个?
输出:
"message": "Could not write JSON: failed to lazily initialize a
collection of role: com.xxxx.entity.A.b,
could not initialize proxy - no Session
Hibernate Session 存在于 @Transactional
的方法中。
在服务 class 之外传递实体是一种不好的做法,因为在离开您的 search
方法后会话将被关闭。另一方面,您的实体包含惰性初始化集合,一旦会话关闭就无法将其拉出。
好的做法是将实体映射到传输对象上,return那些传输对象在外面(不是原始实体)。