2009-12-21 4 views
4

내 프로젝트에서 최대 절전 모드 검색을 통합하려고합니다. 내 모델에 대한 색인이 생성되지만 내 검색어로 인해 결과가 반환되지 않는 이유가 있습니다. 나는 지금 몇 시간 동안이 문제를 해결하려고 노력해 왔지만 내가하는 일은 아무 것도없는 것처럼 보인다.최대 절전 모드 검색 + spring3 + jpa

도메인 개체 :

@Entity 
@Table(name = "roles") 
@Indexed 
public class Role implements GrantedAuthority { 
private static final long serialVersionUID = 8227887773948216849L; 

    @Id @GeneratedValue 
    @DocumentId 
    private Long ID; 

    @Column(name = "authority", nullable = false) 
    @Field(index = Index.TOKENIZED, store = Store.YES) 
    private String authority; 

    @ManyToMany 
    @JoinTable(name = "user_roles", joinColumns = { @JoinColumn(name = "role_id") }, inverseJoinColumns = { @JoinColumn(name = "username") }) 
    @ContainedIn 
    private List<User> users; 

    ... 

} 

DAO :

public abstract class GenericPersistenceDao<T> implements IGenericDao<T> { 

@PersistenceContext 
private EntityManager entityManager; 

... 

    @Override 
    public FullTextEntityManager getSearchManager() { 
     return Search.getFullTextEntityManager(entityManager); 
    } 

} 

서비스 :

@Service(value = "roleService") 
public class RoleServiceImpl implements RoleService { 

    @Autowired 
    private RoleDao roleDAO; 

    ... 

    @Override 
    @SuppressWarnings("unchecked") 
    public List<Role> searchRoles(String keyword) throws ParseException { 
     FullTextEntityManager manager = roleDAO.getSearchManager(); 
     TermQuery tquery = new TermQuery(new Term("authority", keyword)); 
     FullTextQuery query = manager.createFullTextQuery(tquery, Role.class); 
     return query.getResultList(); 
    } 

} 

테스트 :

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = { "classpath:applicationContext.xml" }) 
@Transactional 
public class TestRoleService extends Assert { 

    @Autowired 
    private RoleService roleService; 

    @Test 
    public void testSearchRoles() { 
     roleService.saveRole(/* role with authority="test" */); 
     List<Role> roles = roleService.searchRoles("test"); 
     assertEquals(1, roles.size()); // returns 0 
    } 

} 

구성

<persistence-unit name="hibernatePersistence" transaction-type="RESOURCE_LOCAL"> 
     <provider>org.hibernate.ejb.HibernatePersistence</provider> 
     <properties> 
      <property name="hibernate.search.default.directory_provider" value="org.hibernate.search.store.FSDirectoryProvider" /> 
      <property name="hibernate.search.default.indexBase" value="indexes" /> 
     </properties> 
</persistence-unit> 

<!-- Entity manager --> 
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean"> 
    <property name="persistenceUnitName" value="hibernatePersistence" /> 
</bean> 

<!-- Transaction manager --> 
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 
    <property name="entityManagerFactory" ref="entityManagerFactory" /> 
</bean> 

<!-- Enable the configuration of transaction behavior based on annotations --> 
<tx:annotation-driven transaction-manager="transactionManager" /> 

<context:component-scan base-package="org.myproject" /> 

실제로 데이터베이스는 해당 기관 필드 값과 일치하는 역할로 채워집니다. 엔티티 관리자는 내 모든 정규 CRUD 테스트가 성공할 때만 유효합니다. 오류가 전적으로 최대 절전 모드 검색 (3.1.1.GA)과 관련되어 있음을 의미하지만 잘못된 위치는 어디입니까?

+0

DB가 전체 텍스트 검색을 지원합니까? – Roman

+0

HSQLDB를 사용하고 있습니다. – Jeroen

+0

수정 : 도메인 개체의 색인이 올바르게 지정되지 않았습니다. – Jeroen

답변

1

마지막으로 작동하도록 관리 ... 분명히 개체가 자동으로 인덱싱되지 않거나 커밋되지 않습니다. 색인을 수행함으로써

public List<Role> searchRoles(String keyword) { 
     // Index domain object (works) 
     EntityManager manager = factory.createEntityManager(); 
     FullTextEntityManager ftManager = Search.getFullTextEntityManager(manager); 
     ftManager.getTransaction().begin(); 

     List<Role> roles = ftManager.createQuery("select e from " + Role.class.getName() + " e").getResultList(); 
     for (Role role : roles) { 
      ftManager.index(role); 
     } 
     ftManager.getTransaction().commit(); 

     // Retrieve element from search (works) 
     TermQuery tquery = new TermQuery(new Term("authority", keyword)); 
     FullTextQuery query = ftManager.createFullTextQuery(tquery, Role.class); 
     return query.getResultList(); 
} 

및 getTransactionCommit는 인덱스가 제대로 내 인덱스 폴더에 저장되어있는 기능은 다음과 같습니다 내 구현은 이제 보인다. 그러나이 구현은 텍스트 검색을위한 대체 엔티티 관리자를 만들면서 매우 부자연 스럽습니다. @Transactional 주석을 사용하여 레코드를 색인화하고 커밋하는 "클리너 (cleaner)"방법이 있습니까 ??? 이론적으로

+1

나는 이것이 조금 늦다는 것을 알고 있지만, 인터넷에서 누군가를 돕기를 희망한다고 언급 할 것이다. 런타임에 Spring에 의해로드되는 클래스를 사용하고 애플리케이션이 시작할 때 기존 데이터를 다시 인덱싱합니다 (내 메소드에서 @PostConstruct 주석 사용). – schmimd04

2

모두 작동하지만이있을 수있는 몇 가지 문제 :

  • 인덱스 기존의 객체를 처음 당신을 했습니까? Hibernate Search는 모든 새로운 변경을 색인화하는 반면, 기존의 객체를 인식하지 못하기 때문에 초기에 색인을 붙일 필요가있다 (ftem # index() 사용)
  • 기본적으로 HSearch는 Hibernate 또는 JTA 트랜잭션을 수신하기 위해 후크한다. 트랜잭션 이벤트 전후에. 어쩌면 당신의 Spring tx 설정은 그것을 무시할 것이고 따라서 HSearch는 트리거되지 않기 때문에 색인을 생성 할 수 없다. 최선의 접근법은 실제 JTA 트랜잭션 관리자를 사용하고 이러한 facades를 피하는 것입니다.
  • 초기 색인 생성 (index() 사용)에 대해 이야기하고 있다면 tx가 확약되지 않아도 #flushToIndexes()를 사용하여 색인 생성을 강제 수행 할 수 있습니다.
  • 마지막으로 중요한 것은 코드를 인덱싱하기 전에 메모리에있는 모든 객체를로드하기 때문에 OutOfMemoryException을 던질 가능성이 높습니다. 대량의 객체를 일괄 적으로 색인화하는 방법에 대한 Hibernate Search 참조 문서를 확인하십시오. Hibernate Search in Action (저자이기도하다)의 Manning은 또한이 모든 것을 깊이 파고들 것이다.
1

이 결국 내 문제는 다음과 같은 속성을 부착하여 해결되었다 : hibernate.search.worker.batch_size = 1

내가 지속 할 때마다뿐만 아니라 지금은 제대로 쿼리하지만, 인덱스도 자동으로 업데이트됩니다 수 있습니다 내 도메인 개체. 지금 가지고있는 유일한 문제는 import.sql을 통해 삽입 된 데이터가 자동으로 인덱싱되지 않는다는 것입니다. 어떤 종류의 "마술"동면 상태가 있습니까?이 문제에 사용 가능한 검색 속성 또는 수동으로 색인을 생성해야합니까?

관련 문제