在Spring引导中编写自定义查询 [英] writing custom queries in Spring boot

查看:134
本文介绍了在Spring引导中编写自定义查询的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  package util; 

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

public class HibernateUtil {
private static final SessionFactory sessionFactory = buildSessionFactory();
private static SessionFactory buildSessionFactory(){
try {
//从hibernate.cfg.xml创建SessionFactory
Configuration configuration = new Configuration()。configure(hibernate.cfg .XML);返回configuration.buildSessionFactory(new
StandardServiceRegistryBuilder()。applySettings(configuration.getProperties()).build());
}
catch(Throwable ex){
//确保您记录异常,因为它可能被吞噬System.err.println(Initial SessionFactory creation failed。+ ex);抛出新的ExceptionInInitializerError(ex);


public static SessionFactory getSessionFactory(){return sessionFactory; }
}



hibernate.cfg.xml


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

< hibernate-configuration>
< session-factory>

<! - 数据库连接设置 - >
< 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>密码< / property>

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

<! - 使用映射元数据自动创建/更新表格 - >
< property name =hbm2ddl.auto>更新< / property>

<! - 使用基于注解的映射元数据 - >
< mapping class =entity.Author/>
< mapping class =entity.Article/>
< / session-factory>
< / hibernate-configuration>

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();

尝试{
txn.begin();
作者author = new Author(name,listOfArticlesWritten);
文章文章=新文章(文章标题,作者);
session.save(作者);
session.save(article);

Query query = session.createQuery(从文章s
中选择不同的a.authorName,其中s.author像Joe%和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();}}
}
}

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



我是什么试图完成,至少在这篇文章是能够在春季启动执行上述查询。我可以创建一个属性文件

application.properties

 #= ============================== 
#=数据源
#======= ========================

#设置数据库连接的配置
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
#======================= ========

#指定DBMS
spring.jpa.database = MYSQL

#显示或不记录每个sql查询
spring.jpa.show-sql = true

#必须将Ddl auto设置为create以确保Hibernate将在应用程序启动时运行
#import.sql文件

#create-drop |更新|验证| none
spring.jpa.hibernate.ddl-auto =更新

#用于生成优化查询的SQL方言
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect .MySQL5Dialect

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

spring.thymeleaf.cache = false
#debug = true

我可以将所有映射移至属性文件,但那么我不清楚如何编写查询,因为不再有会话对象。

解决方案

如果您使用Spring Boot + Spring Data JPA,然后通过使用<数据JPA>配置您的数据源(您现在放入 hibernate.cfg.xml )到 application.properties a href =http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html =noreferrer> spring.datasource。 * 属性。



这应该会自动创建一个为您提供实体经理。如果您需要使用查询,则可以使用Spring Data JPA的存储库,例如:

  public interface ArticleRepository扩展了JpaRepository< Article,龙> {
@Query(从第s条中选择s,其中s.author喜欢?1和s.title =?2)
List< Article> findByAuthorAndTitle(String author,String title);

$ / code>

现在您可以自动装入资源库并使用给定的查询,如下所示:

 列表< Article> articles = repository.findByAuthorAndTitle(Joe%,Spring boot); 

如果您确实需要自定义查询,则可以使用JPA的Predicate / Criteria API。 Spring提供了这些谓词的包装版本,称为 Specifications 为此,您将 ArticleRepository 扩展为另一个称为 JpaSpecificationExecutor< Article> 的接口。这为您的存储库添加了一些额外的方法:

 规范< Article> ((root,query,cb) - > {
return cb.and(
cb.like(root.get(author),Joe% ),
cb.equal(root.get(title),Spring boot));
});
列表<文章> articles = repository.findAll(spec);

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


I have recently started using Spring boot, and have run into a bit of a problem. before, when i was just using Spring data with hibernate and JPA, I could create a hibernate.cfg.xml file that would give a bunch of configuration that could be passed to a config object and then ultimately create a SessionFactory object that would create a Session object that could be used to pass the query to hibernate:

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

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>

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

This is where the issue appears. I don't know how to avoid creating a hibernate.cfg.xml file or session factory for custom queries. in the Spring guides page, and some tutorials i have worked through, they take their DAO and extend the CrudRepository interface which gives a bunch of methods already, as well as a way to name the method so that Hibernate can build the sql on its own.

what i am trying to accomplish, at least in this post is to be able to execute the above query in spring boot. I can create a properties file

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

I can move all but the mapping to a properties file, but then I am unclear how to write the query because there is no longer a session object.

解决方案

If you use Spring Boot + Spring Data JPA, then you configure your datasource (which you now put in hibernate.cfg.xml) into the application.properties, by using the spring.datasource.* properties.

This should automatically create an entity manager for you. If you need to use queries, you can use Spring Data JPA's repositories, for example:

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

Now you can autowire the repository and use the given query, like this:

List<Article> articles = repository.findByAuthorAndTitle("Joe%", "Spring boot");

If you really need custom queries, you can use the Predicate/Criteria API from JPA. Spring offers a wrapped version of these predicates, called Specifications.

To do that, you extend your ArticleRepository with another interface called JpaSpecificationExecutor<Article>. This adds some extra methods to your repository:

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

This allows you to dynamically create queries, though from your question it doesn't look like you really need it.

这篇关于在Spring引导中编写自定义查询的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆