在Spring启动时编写自定义查询

Sti*_*ode 4 hibernate hql spring-boot

我最近开始使用Spring启动,并遇到了一些问题.之前,当我刚刚使用Spring数据和hibernate和JPA时,我可以创建一个hibernate.cfg.xml文件,该文件可以提供一系列可以传递给配置对象的配置,然后最终创建一个SessionFactory对象来创建一个可用于将查询传递给hibernate的Session对象:

package util;

import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder; 
import org.hibernate.cfg.Configuration;

public class HibernateUtil {
    private static final SessionFactory sessionFactory = buildSessionFactory();
    private static SessionFactory buildSessionFactory() { 
        try {
        // Create the SessionFactory from hibernate.cfg.xml
        Configuration configuration = new Configuration().configure("hibernate.cfg.xml"); return configuration.buildSessionFactory( new
        StandardServiceRegistryBuilder().applySettings( configuration.getProperties() ).build() ); 
        }
        catch (Throwable ex) {
        // Make sure you log the exception, as it might be swallowed System.err.println("Initial SessionFactory creation failed." + ex); throw new ExceptionInInitializerError(ex);
        } 
    }
    public static SessionFactory getSessionFactory() { return sessionFactory; }
}
Run Code Online (Sandbox Code Playgroud)

的hibernate.cfg.xml

<?xml version='1.0' encoding='utf-8'?>
 <!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN" 
    "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration> 
    <session-factory>

        <!-- Database connection settings -->
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property> 
        <property name="connection.url">jdbc:mysql://localhost:3306/hello-world</property> 
        <property name="connection.username">root</property>
        <property name="connection.password">password</property>

        <!-- SQL dialect -->
        <property name="dialect">org.hibernate.dialect.MySQLDialect</property> 

        <!-- Create/update tables automatically using mapping metadata -->
        <property name="hbm2ddl.auto">update</property> 

        <!-- Use Annotation-based mapping metadata -->
        <mapping class="entity.Author"/> 
        <mapping class="entity.Article"/> 
    </session-factory>
</hibernate-configuration>
Run Code Online (Sandbox Code Playgroud)

Main.java

    public class HelloWorldClient {

    public static void main(String[] args) {
        Session session = HibernateUtil.getSessionFactory().openSession(); 
        Transaction txn = session.getTransaction();

        EntityManagerFactory emf = Persiscance.createEntityManagerFactory("hibernate.cfg.xml");
        EntityManager em = emf.createEntityManager();
        EntityTransaction txn = em.getTransaction();

        try {
            txn.begin();
            Author author = new Author("name", listOfArticlesWritten);
            Article article = new Article("Article Title", author);
            session.save(author);
            session.save(article);

            Query query = session.createQuery("select distinct a.authorName from Article s
                                                where s.author like "Joe%" and title = 'Spring boot');

            List<Article> articles = query.list();

            txn.commit();
        } catch(Exception e) {
            if(txn != null) { txn.rollback(); }
            e.printStackTrace();
        } finally {
            if(session != null) { session.close(); } }
    } 
}
Run Code Online (Sandbox Code Playgroud)

这就是出现问题的地方.我不知道如何避免为自定义查询创建hibernate.cfg.xml文件或会话工厂.在Spring指南页面,以及我已经完成的一些教程中,他们采用了他们的DAO并扩展了CrudRepository接口,该接口已经提供了一堆方法,以及一种命名方法的方法,以便Hibernate可以自己构建sql .

我想要完成的是,至少在这篇文章中是能够在spring boot中执行上述查询.我可以创建一个属性文件

application.properties

# ===============================
# = DATA SOURCE
# ===============================

# Set here configurations for the database connection
spring.datasource.url = jdbc:mysql://localhost:3306/spring-boot-demo
spring.datasource.username = test
spring.datasource.password = test

# Mysql connector
spring.datasource.driverClassName = com.mysql.jdbc.Driver



# ===============================
# = JPA / HIBERNATE
# ===============================

# Specify the DBMS
spring.jpa.database = MYSQL

# Show or not log for each sql query
spring.jpa.show-sql = true

# Ddl auto must be set to "create" to ensure that Hibernate will run the
# import.sql file at application startup

#create-drop| update | validate | none
spring.jpa.hibernate.ddl-auto = update

# SQL dialect for generating optimized queries
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect

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

spring.thymeleaf.cache = false
#debug=true
Run Code Online (Sandbox Code Playgroud)

我可以将除映射之外的所有映射移动到属性文件,但后来我不清楚如何编写查询,因为不再有会话对象.

g00*_*00b 13

如果您使用Spring Boot + Spring Data JPA,那么您可以使用属性将数据源(现在放在hibernate.cfg.xml中)配置到其中.application.propertiesspring.datasource.*

这应该会自动为您创建实体管理器.如果需要使用查询,可以使用Spring Data JPA的存储库,例如:

public interface ArticleRepository extends JpaRepository<Article, Long> {
    @Query("select s from Article s where s.author like ?1 and s.title = ?2")
    List<Article> findByAuthorAndTitle(String author, String title);
}
Run Code Online (Sandbox Code Playgroud)

现在您可以自动装配存储库并使用给定的查询,如下所示:

List<Article> articles = repository.findByAuthorAndTitle("Joe%", "Spring boot");
Run Code Online (Sandbox Code Playgroud)

如果您确实需要自定义查询,则可以使用JPA中的Predicate/Criteria API.Spring提供了这些谓词的包装版本,称为规范.

为此,您可以ArticleRepository使用另一个名为的接口扩展您的扩展JpaSpecificationExecutor<Article>.这为您的存储库添加了一些额外的方法:

Specification<Article> spec = Specifications.<Article>where((root, query, cb) -> {
    return cb.and(
         cb.like(root.get("author"), "Joe%"),
         cb.equal(root.get("title"), "Spring boot"));
});
List<Article> articles = repository.findAll(spec);
Run Code Online (Sandbox Code Playgroud)

这允许您动态创建查询,但从您的问题来看,它看起来并不像您真正需要它.