Не удается найти решение для исключения отложенной инициализации с помощью поиска в спящем режиме - PullRequest
0 голосов
/ 13 апреля 2019

Я выполняю поиск с поиском в спящем режиме в среде Spring Boot, но при выполнении запроса мне не удается лениво инициализировать коллекцию ролей.

Я перепробовал все варианты, представленные в других подобных вопросах. Моя сущность имеет много-много отношений с двумя другими.

@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;

}

Мой класс контроллеров:

@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);
}

}

Мой класс обслуживания:

@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

1 Ответ

1 голос
/ 13 апреля 2019

Hibernate Session существует в методе с @Transactional.
Передача сущности за пределы класса Service является плохой практикой, поскольку сеанс закрывается после выхода из вашего метода search. С другой стороны, ваша сущность содержит отложенные инициализированные коллекции, которые не могут быть извлечены после закрытия сессии.

Хорошей практикой является отображение объекта на транспортный объект и возврат этих транспортных объектов за пределы (не необработанных объектов).

...