Spring Boot + Hibernate Suchbeispiel

Hier erstellen wir ein Spring Boot-Webanwendungsbeispiel mit der Hibernate Search Thymeleaf-Vorlagen-Engine und stellen es als WAR für Wildfly 10.1 bereit.

Verwendete Technologien:

  1. Spring Boot 1.5.6. FREIZEIT

  2. Java 8

  3. Hibernate-Suche 5.6.1.Ende

  4. Embedded Tomcat, Wildfly 8.1 Finale

1. Projektstruktur

Eine Standard-Maven-Projektstruktur

image

1. Projektabhängigkeiten

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<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>com.techfou</groupId>
    <artifactId>spring-boot-web-wildfly-search</artifactId>
    <version>0.0.1</version>
    <packaging>war</packaging>
    <name>techfou-wildfly-spring-boot</name>
    <description>Spring Boot Web Hibernate Search Example</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <logback.version>1.1.9</logback.version>
    </properties>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <!--
            Comment out if deploy as WAR file
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
            </exclusions>
            -->
        </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>

        <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-search-engine -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-search-engine</artifactId>
            <version>5.6.1.Final</version>
            <exclusions>
                <exclusion>
                    <groupId>org.jboss.logging</groupId>
                    <artifactId>jboss-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-search-orm -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-search-orm</artifactId>
            <version>5.6.1.Final</version>
            <exclusions>
                <exclusion>
                    <groupId>org.jboss.logging</groupId>
                    <artifactId>jboss-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.hsqldb</groupId>
            <artifactId>hsqldb</artifactId>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.jboss.logging</groupId>
            <artifactId>jboss-logging</artifactId>
            <version>3.3.0.Final</version>
        </dependency>

        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>1.1.9</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <layout>WAR</layout>
                    <executable>true</executable>
                    <mainClass>com.mkyong.WildflySpringBootApplication</mainClass>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

2. Modell

Für diese Beispielanwendung erstellen wir eine Website, auf der Sie nach seltenen Baseballkarten suchen können. Also machen wir unser Modell zur Baseballkarte und kommentieren die durchsuchbaren Felder.

BaseballCard.java

package com.mkyong.model;

import org.hibernate.search.annotations.Field;
import org.hibernate.search.annotations.Indexed;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Indexed
@Entity
public class BaseballCard {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;
    @Field
    private String name;
    @Field
    private String rarityLevel;
    @Field
    private int year;

   //getters n setters

}

3. Repository

Hier haben wir ein Spring Data CrudRepository für das BaseballCard-Modell, mit dem wir die erforderlichen Erstellungs- und Lesefunktionen ausführen können.

BaseballCardRepository.java

package com.mkyong.dao;

import org.springframework.data.repository.CrudRepository;

import com.mkyong.model.BaseballCard;

public interface BaseballCardRepository extends CrudRepository<BaseballCard,Long> {
}

4. Suche im Ruhezustand

HibernateSearchService.java

package com.mkyong.service;

import com.mkyong.model.BaseballCard;
import org.apache.lucene.search.Query;
import org.hibernate.search.jpa.FullTextEntityManager;
import org.hibernate.search.jpa.Search;
import org.hibernate.search.query.dsl.QueryBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import java.util.List;

@Service
public class HibernateSearchService {


    @Autowired
    private final EntityManager centityManager;


    @Autowired
    public HibernateSearchService(EntityManager entityManager) {
        super();
        this.centityManager = entityManager;
    }


    public void initializeHibernateSearch() {

        try {
            FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(centityManager);
            fullTextEntityManager.createIndexer().startAndWait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Transactional
    public List<BaseballCard> fuzzySearch(String searchTerm) {

        FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(centityManager);
        QueryBuilder qb = fullTextEntityManager.getSearchFactory().buildQueryBuilder().forEntity(BaseballCard.class).get();
        Query luceneQuery = qb.keyword().fuzzy().withEditDistanceUpTo(1).withPrefixLength(1).onFields("name")
                .matching(searchTerm).createQuery();

        javax.persistence.Query jpaQuery = fullTextEntityManager.createFullTextQuery(luceneQuery, BaseballCard.class);

       //execute search

        List<BaseballCard> BaseballCardList = null;
        try {
            BaseballCardList = jpaQuery.getResultList();
        } catch (NoResultException nre) {
            ;//do nothing

        }

        return BaseballCardList;


    }
}

Dadurch wird der HibernateSearchService so konfiguriert, dass auf ihn zugegriffen werden kann.

HibernateSearchConfiguration.java

package com.mkyong;

import javax.persistence.EntityManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.mkyong.service.HibernateSearchService;
@EnableAutoConfiguration
@Configuration
public class HibernateSearchConfiguration {

    @Autowired
    private EntityManager bentityManager;

    @Bean
    HibernateSearchService hibernateSearchService() {
        HibernateSearchService hibernateSearchService = new HibernateSearchService(bentityManager);
        hibernateSearchService.initializeHibernateSearch();
        return hibernateSearchService;
    }
}

5. Service für das Modell

Dies ist ein einfacher Service, der unserem Repository drei Karten hinzufügt. Zur Veranschaulichung der SOLID-Programmierprinzipien gibt es eine separate Schnittstelle für den Dienst.

CardService.java

package com.mkyong.service;

public interface CardService {

    void addCards();

}

CardServiceImpl.java

package com.mkyong.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.mkyong.dao.BaseballCardRepository;
import com.mkyong.model.BaseballCard;

@Service
public class CardServiceImpl implements CardService {

    @Autowired
    BaseballCardRepository cardrepository;

    BaseballCard TedWilliams = new BaseballCard();
    BaseballCard BobGibson = new BaseballCard();
    BaseballCard HonusWagner = new BaseballCard();

    public void addCards() {
        TedWilliams.setName("Ted Williams");
        TedWilliams.setYear(1954);
        TedWilliams.setRarityLevel("Very Rare");

        cardrepository.save(TedWilliams);

        BobGibson.setName("Bob Gibson");
        BobGibson.setYear(1959);
        BobGibson.setRarityLevel("Very Rare");

        cardrepository.save(BobGibson);

        HonusWagner.setName("Honus Wagner");
        HonusWagner.setYear(1909);
        HonusWagner.setRarityLevel("Rarest");

        cardrepository.save(HonusWagner);

        System.out.println("Cards have been added : " + cardrepository.findAll());

    }
}

6. Controller

Der Controller ist für die Verbindung der Backend-Services mit unserer Thymeleaf-Vorlage für das Frontend verantwortlich.

CardController.java

package com.mkyong.controller;

import com.mkyong.model.BaseballCard;
import com.mkyong.service.CardService;
import com.mkyong.service.HibernateSearchService;
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.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.List;

@Controller
public class CardController {

    @Autowired
    private HibernateSearchService searchservice;

    @Autowired
    private CardService cardservice;

    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String search(@RequestParam(value = "search", required = false) String q, Model model) {
        List<BaseballCard> searchResults = null;
        try {
            cardservice.addCards();
            searchResults = searchservice.fuzzySearch(q);

        } catch (Exception ex) {
           //here you should handle unexpected errors
           //...
           //throw ex;
        }
        model.addAttribute("search", searchResults);
        return "index";

    }

}

7. Konfiguration

Jetzt müssen wir unsere Thymeleaf- und Hibernate-Suche konfigurieren.

application.properties

#==================================
# = Thymeleaf configurations
#==================================
spring.thymeleaf.check-template-location=true
spring.thymeleaf.prefix=classpath:/templates/spring.thymeleaf.suffix=.html
spring.thymeleaf.content-type=text/html
spring.thymeleaf.cache=false
server.contextPath=/#===================================
#=
# Specify 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
spring.jpa.properties.hibernate.search.default.indexBase = indexpath

8. Thymeleaf-Vorlage

Für unsere Thymeleaf-Vorlage haben wir zwei Zwecke: Erlauben Sie dem Benutzer, die Suchergebnisse zu suchen und anzuzeigen, sobald eine Suche abgeschlossen ist.

Glücklicherweise hat Thymeleaf bedingte Anweisungen, die es uns ermöglichen, Ergebnisse anzuzeigen, wenn die Suche eines Benutzers Elemente zurückgibt.

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <!-- META SECTION -->
    <title>Mkyong Wildfly Example</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
    <meta name="viewport" content="width=device-width, initial-scale=1"/>
    <!-- END META SECTION -->
    <!--  BEGIN STYLE -->
    <style>
        table, th, td {
            border: 1px solid black;
            padding: 1px;
        }
    </style>
    <!--  END STYLE -->

</head>
<body>
<form action="#" th:action="@{/}" th:object="${search}">
    <label for="search__input">Search:</label> <input name="search"
                                                     id="search">
    </input>
    <div th:if="${not #lists.isEmpty(search)}">
        <h2>Search Results</h2>
        <table>
            <thead>
            <tr>
                <th>ID</th>
                <th>name</th>
                <th>rarity level</th>
                <th>year</th>
            </tr>
            </thead>
            <tbody>
            <tr th:each="search : ${search}">
                <td th:text="${search.id}">Text ...</td>
                <td th:text="${search.name}">Text ...</td>
                <td th:text="${search.rarityLevel}">Text ...</td>
                <td th:text="${search.year}">Text...</td>
            </tr>
            </tbody>
        </table>
    </div>
</form>
</body>
</html>

9. SpringBootApplication

WildflySpringBootApplication.java

package com.mkyong;

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

@SpringBootApplication
public class WildflySpringBootApplication {

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

}

10. Demo

Starten Sie Spring Boot Application mit dem eingebetteten Tomcat-Standardcontainer.

$ mvn spring-boot:run

Zugriff auf http://localhost : 8080/

image

Ich habe nach "Ted" gesucht und die Ergebnisse werden in der Tabelle http://localhost : 8080/? Search = ted angezeigt

image

11. Stellen Sie die WAR-Datei für Wildfly bereit

Der Wildfly ist ein JBoss-Open-Source-Anwendungsserver. Wildfly kann von% E2% 80% heruntergeladen werden 9Chttp://wildfly.org/downloads/%E2%80%9C[offizielle Website]

11.1 Schließen Sie den eingebetteten Tomcat-Container aus.

pom.xml

    <dependency>
           <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

11.2 Erweitert SpringBootServletInitializer

WildflySpringBootApplication.java

package com.mkyong;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.support.SpringBootServletInitializer;

@SpringBootApplication
public class WildflySpringBootApplication extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(WildflySpringBootApplication.class);
    }

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

}

11.3 Maven erstellt und kopiert die WAR-Datei in JBoss Wildfly und startet sie.

Terminal

$ mvn package

11.4 Überlegungen zu Wildfly 10

Für Wildfly 10 müssen wir aufgrund der vorinstallierten Technologien zusätzliche Änderungen vornehmen. In unserem Fall verwenden wir die Hibernate-Suche, die in Wildfly 10 verpackt ist.

Für Benutzer von Wildfly 10 müssen Sie eine persistence.xml -Datei erstellen und Folgendes eingeben:

persistence.xml

wildfly.jpa.hibernate.search.module = none

Erledigt.

Quellcode herunterladen

Referenzen

+ Frühling]. link://spring-boot/spring-boot-deploy-war-datei zu tomcat/

  • Bereitstellen der WAR-Datei für Tomcat]

Link://Tag/Hibernate-Suche/[Hibernate-Suche] springboot wildfly