Spring Boot Hibernate搜索错误

时间:2016-08-29 13:09:54

标签: spring-boot hibernate-search

我在Spring Boot中准备了一个应用程序,演示了使用和

Hibernate Search的功能。

问题/错误:当我尝试运行该应用程序时,它会给我一个错误:

Exception in thread "main" java.lang.IllegalArgumentException: java.lang.Object is not an indexed entity or a subclass of an indexed entity


I have referred the link : http://blog.netgloo.com/2014/10/27/using-mysql-in-spring-boot-via-spring-data-jpa-and-hibernate/

我的代码:

------------------------------ Application.java -------------- -----

package netgloo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

  public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
  }

}

------------------------------- BuildSearchIndex.java ------------- --------

package netgloo;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.hibernate.search.jpa.FullTextEntityManager;
import org.hibernate.search.jpa.Search;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;

/**
 * The only meaning for this class is to build the Lucene index at application
 * startup. This is needed in this example because the database is filled 
 * before and each time the web application is started. In a normal web 
 * application probably you don't need to do this.

 */
@Component
public class BuildSearchIndex implements ApplicationListener<ContextRefreshedEvent> {

    @PersistenceContext
    private EntityManager entityManager;

    /**
     * Create an initial Lucene index for the data already present in the
     * database.
     * This method is called during Spring's startup.
     * 
     * @param event Event raised when an ApplicationContext gets initialized or
     * refreshed.
     */
    @Override
    public void onApplicationEvent(final ContextRefreshedEvent event) {
        try {
            FullTextEntityManager fullTextEntityManager =
                    Search.getFullTextEntityManager(entityManager);
            fullTextEntityManager.createIndexer().startAndWait();
        }
        catch (InterruptedException e) {
            System.out.println(
                    "An error occurred trying to build the serach index: " +
                            e.toString());
        }
        return;
    }


} 

---------------------------------控制器------------- ------------

package netgloo.controllers;

import java.util.List;

import netgloo.models.Employee;
import netgloo.search.EmployeeSearch;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class MainController {
    @Autowired
    private EmployeeSearch emprSearch;

    @RequestMapping("/")
    @ResponseBody
    public String index() {
        return "Welcome !!!:)";
    }

    @RequestMapping("/search")
    public String search(String query, Model model) {
        List<Employee> searchResults = null;
        try {
            searchResults = emprSearch.search(query);
        } catch (Exception ex) {
            return "";
        }
        model.addAttribute("searchResults", searchResults);
        return "search";
    }
}

------------------------------模型---------------- ---------------

package netgloo.models;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;

@Entity
@Table(name = "employees")
public class Employee {

  // An autogenerated id (unique for each user in the db)
  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private long id;

  @NotNull
  private String email;

  @NotNull
  private String name;

  // Public methods

  public Employee() { }

  public Employee(long id) { 
    this.id = id;
  }

  public Employee(String email, String name) {
    this.email = email;
    this.name = name;
  }

  // Getter and setter methods
  // ...

}

/////////////////////////// EmployeeSearch.java///////////////// //////

package netgloo.search;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.transaction.Transactional;

import netgloo.models.Employee;

import org.hibernate.search.jpa.FullTextEntityManager;
import org.hibernate.search.query.dsl.QueryBuilder;
import org.springframework.stereotype.Repository;

@Repository
@Transactional
public class EmployeeSearch {

    // Spring will inject here the entity manager object
    @PersistenceContext
    private EntityManager entityManager;

    public List<Employee> search(String text) {

        // get the full text entity manager
        FullTextEntityManager fullTextEntityManager = org.hibernate.search.jpa.Search
                .getFullTextEntityManager(entityManager);

        // create the query using Hibernate Search query
        QueryBuilder queryBuilder = fullTextEntityManager.getSearchFactory().buildQueryBuilder().forEntity(Employee.class)
                .get();

        // a very basic query by keywords
        org.apache.lucene.search.Query query = queryBuilder.keyword().onFields("name", "city", "email").matching(text)
                .createQuery();

        // wrap Lucene query in an Hibernate Query object
        org.hibernate.search.jpa.FullTextQuery jpaQuery = fullTextEntityManager.createFullTextQuery(query, Employee.class);

        // execute search and return results (sorted by relevance as default)
        @SuppressWarnings("unchecked")
        List<Employee> results = jpaQuery.getResultList();

        return results;
    }

}

///////////////////////// search.html /////////////////// ///////////////

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">

<head>
  <title>Search</title>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>

<body>

  <ol>
    <li th:each="employee : ${searchResults}">
      <b><span th:text="${employee.username}"></span></b> - 
      <span th:text="${employee.city}"></span> -
      <span th:text="${employee.email}"></span>
    </li>
  </ol>

  <p th:if="${searchResults.isEmpty()}">
    <strong>Hint</strong>: the query "<a href='/search?query=amy'>amy</a>" 
    should return some results.
  </p>

</body>

</html>

/////////////////////////// application.properties///////////////// //////

# Datasource settings 
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/myschema
spring.datasource.username=root
spring.datasource.password=admin123

# Hibernate settings
spring.jpa.hibernate.ddl-auto=create
spring.jpa.database-platform=org.hibernate.dialect.MySQL5Dialect
spring.jpa.hibernate.naming_strategy =org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.show-sql = true

# Specify the DirectoryProvider to use (the Lucene Directory)
spring.jpa.properties.hibernate.search.default.directory_provider = filesystem

# Using the filesystem DirectoryProvider you also have to specify the default
# base directory for all indexes (make sure that the application have write
# permissions on such directory)
spring.jpa.properties.hibernate.search.default.indexBase = c:\\indexeFiles


# ===============================
# = THYMELEAF
# ===============================

spring.thymeleaf.cache = false
server.port=9001

///////////////////////////////的pom.xml ///////////// //////////////

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>netgloo</groupId>
  <artifactId>spring-boot-hibernate-search</artifactId>
  <version>0.0.1-SNAPSHOT</version>

  <name>spring-boot-hibernate-search</name>
  <description>How to integrate Hibernate Search in Spring Boot</description>

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.2.3.RELEASE</version>
    <relativePath />
  </parent>

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
    </dependency>

    <!-- Maven artifact identifier for Hibernate Search -->
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-search-orm</artifactId>
      <version>4.5.1.Final</version>
    </dependency>

    <!-- Optional: to use JPA 2.1 -->
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-entitymanager</artifactId>
    </dependency>

  </dependencies>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <start-class>netgloo.Application</start-class>
    <java.version>1.7</java.version>
  </properties>

  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>

</project>

我的Stacktrace:

Exception in thread "main" java.lang.IllegalArgumentException: java.lang.Object is not an indexed entity or a subclass of an indexed entity
    at org.hibernate.search.impl.MassIndexerImpl.toRootEntities(MassIndexerImpl.java:102)
    at org.hibernate.search.impl.MassIndexerImpl.<init>(MassIndexerImpl.java:74)
    at org.hibernate.search.impl.DefaultMassIndexerFactory.createMassIndexer(DefaultMassIndexerFactory.java:47)
    at org.hibernate.search.impl.FullTextSessionImpl.createIndexer(FullTextSessionImpl.java:181)
    at org.hibernate.search.jpa.impl.FullTextEntityManagerImpl.createIndexer(FullTextEntityManagerImpl.java:349)
    at netgloo.BuildSearchIndex.onApplicationEvent(BuildSearchIndex.java:38)
    at netgloo.BuildSearchIndex.onApplicationEvent(BuildSearchIndex.java:1)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:151)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:128)
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:331)
    at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:773)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.finishRefresh(EmbeddedWebApplicationContext.java:140)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:483)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:686)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:320)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:957)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:946)
    at netgloo.Application.main(Application.java:10)

谢谢!!!

1 个答案:

答案 0 :(得分:3)

至少可以说,您的实体应注明@Indexed。您还应根据您的要求使用@Field注释实体类的字段。