在 Spring Boot 中编写自定义查询

     2023-02-26     271

关键词:

【中文标题】在 Spring Boot 中编写自定义查询【英文标题】:writing custom queries in Spring boot 【发布时间】:2016-03-22 02:11:31 【问题描述】:

我最近开始使用 Spring boot,但遇到了一些问题。以前,当我只是将 Spring 数据与 hibernate 和 JPA 一起使用时,我可以创建一个 hibernate.cfg.xml 文件,该文件将提供一堆可以传递给配置对象的配置,然后最终创建一个 SessionFactory 对象,该对象将创建一个可用于将查询传递给休眠的会话对象:

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

这就是问题出现的地方。我不知道如何避免为自定义查询创建 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

我可以将除映射之外的所有内容移至属性文件,但由于不再有会话对象,我不清楚如何编写查询。

【问题讨论】:

也许你需要自定义方法实现。 this is an *** answer 我在这里解释了解决方案,可能对你有帮助***.com/a/48854352/4720910 【参考方案1】:

如果您使用 Spring Boot + Spring Data JPA,则使用 spring.datasource.* properties 将数据源(现在放入 hibernate.cfg.xml)配置到 application.properties

这应该会自动为您创建一个实体管理器。如果需要使用查询,可以使用 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);

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

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

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

为此,您可以使用另一个名为 JpaSpecificationExecutor&lt;Article&gt; 的接口扩展您的 ArticleRepository。这会为您的存储库添加一些额外的方法:

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

这允许您动态创建查询,尽管从您的问题来看,您似乎并不真正需要它。

【讨论】:

【参考方案2】:

在 Spring Boot 应用程序中,您无需创建 xml 配置,您必须自己配置 java 文件。 看看这个例子,

import java.util.Properties;

import javax.sql.DataSource;

import org.hibernate.annotations.common.util.impl.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;

@Configuration
public class DatabaseConfig 

 private org.jboss.logging.Logger log = LoggerFactory.logger(DatabaseConfig.class);

 @Value("$db.driver")
 private String DB_DRIVER;

 @Value("$db.username")
 private String DB_USERNAME;

 @Value("$db.password")
 private String DB_PASSWORD;

 @Value("$db.url")
 private String DB_URL;

 @Value("$hibernate.dialect")
 private String HIBERNATE_DIALECT;

 @Value("$hibernate.show_sql")
 private String HIBERNATE_SHOW_SQL;

 @Value("$hibernate.hbm2ddl.auto")
 private String HIBERNATE_HBM2DDL_AUTO;

 @Value("$entitymanager.packagesToScan")
 private String ENTITYMANAGER_PACKAGES_TO_SCAN;

 @Bean
 public DataSource dataSource() 
  DriverManagerDataSource dataSource = null;
  try 
   dataSource = new DriverManagerDataSource();
   dataSource.setDriverClassName(DB_DRIVER);
   dataSource.setUrl(DB_URL);
   dataSource.setUsername(DB_USERNAME);
   dataSource.setPassword(DB_PASSWORD);
   catch (Exception e) 
   e.getMessage();
  
  return dataSource;
 

 @Bean
 public LocalSessionFactoryBean sessionFactory() 
  LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
  sessionFactoryBean.setDataSource(dataSource());
  sessionFactoryBean.setPackagesToScan(ENTITYMANAGER_PACKAGES_TO_SCAN);
  Properties hibernateProps = new Properties();
  hibernateProps.put("hibernate.dialect", HIBERNATE_DIALECT);
  hibernateProps.put("hibernate.show_sql", HIBERNATE_SHOW_SQL);
  hibernateProps.put("hibernate.hbm2ddl.auto", HIBERNATE_HBM2DDL_AUTO);
  sessionFactoryBean.setHibernateProperties(hibernateProps);
  return sessionFactoryBean;
 

 @Bean
 public HibernateTransactionManager transactionManager() 
  HibernateTransactionManager transactionManager = new HibernateTransactionManager();
  transactionManager.setSessionFactory(sessionFactory().getObject());
  return transactionManager;
 

【讨论】:

有啥比在 Java Spring Boot 中使用自定义查询更好的方法?

】有啥比在JavaSpringBoot中使用自定义查询更好的方法?【英文标题】:WhatisthebetterwaythanusingcustomizedqueryinJavaSpringBoot?有什么比在JavaSpringBoot中使用自定义查询更好的方法?【发布时间】:2018-11-0620:18:54【问题描述】:这是在我的Ser... 查看详情

在具有多个连接的 Spring Boot Rest API 中公开自定义查询

】在具有多个连接的SpringBootRestAPI中公开自定义查询【英文标题】:ExposecustomqueryinSpringBootRestAPIwithmultiplejoins【发布时间】:2020-12-2921:11:45【问题描述】:我有一个SpringRESTApi和一个MySQL数据库,现在我想公开具有多个连接的自定... 查看详情

如何在 Spring Boot 中注册自定义转换器?

】如何在SpringBoot中注册自定义转换器?【英文标题】:Howtoregistercustomconvertersinspringboot?【发布时间】:2016-03-1807:31:31【问题描述】:我使用spring-boot-starter-jdbc(v1.3.0)编写应用程序。我遇到的问题:BeanPropertyRowMapper的实例失败,因... 查看详情

是否可以在 Spring Boot 运行时构建自定义查询?

】是否可以在SpringBoot运行时构建自定义查询?【英文标题】:IsitpossibletobuildcustomizedqueryatruntimeinSpringBoot?【发布时间】:2016-12-2505:02:32【问题描述】:这就是我想要做的,我有一个实体,@EntitypublicclassJobEntity@Id@GeneratedValueprivateLo... 查看详情

在 Spring Boot 中创建自定义查询时出错

】在SpringBoot中创建自定义查询时出错【英文标题】:Errorwhilecreatingcustomqueriesinspringboot【发布时间】:2018-05-2805:21:47【问题描述】:我是SpringBoot新手,在向我的代码添加查询时遇到以下错误,org.springframework.beans.factory.UnsatisfiedDep... 查看详情

带有 Java/Spring Boot 的 GraphQL 无法从传递的查询中选择定义为在模式中的字段上定义的自定义指令

】带有Java/SpringBoot的GraphQL无法从传递的查询中选择定义为在模式中的字段上定义的自定义指令【英文标题】:GraphQLwithJava/SpringbootunabletopickcustomdirectivedefinedasonFieldinschemafrompassedquery【发布时间】:2021-08-1120:42:52【问题描述】:已... 查看详情

Spring Boot JPA中的自定义查询问题

】SpringBootJPA中的自定义查询问题【英文标题】:ProblemwithcustomQueryinSpringbootJPA【发布时间】:2020-07-0502:06:49【问题描述】:我正在尝试按范围计算记录数,但在运行服务时出现错误:Causedby:org.hibernate.hql.internal.ast.QuerySyntaxException:... 查看详情

如何在自定义反序列化器 Spring Boot 中读取路径变量或 URL 参数

】如何在自定义反序列化器SpringBoot中读取路径变量或URL参数【英文标题】:HowtoreadpathvariablesorURLparametersinCustomdeserializerSpringBoot【发布时间】:2017-11-2514:06:47【问题描述】:我已经为SpringBoot应用程序中的实体编写了一个自定义反... 查看详情

Spring Boot 中的自定义异常

】SpringBoot中的自定义异常【英文标题】:CustomExceptioninSprinBoot【发布时间】:2019-12-1209:54:06【问题描述】:我在SPRINGBOOT中编写了以下自定义错误处理程序@RestControllerAdvicepublicclassCustomGlobalExceptionHandlerextendsResponseEntityExceptionHandler@... 查看详情

在 Spring Boot MVC 测试中自定义 bean

】在SpringBootMVC测试中自定义bean【英文标题】:customizebeansinspringbootMVCtest【发布时间】:2017-06-2101:34:51【问题描述】:我正在使用Spring-boot1.4.0.RELEASE。已按照建议构建了一个MVCint测试https://docs.spring.io/spring-boot/docs/current/reference/htm... 查看详情

在 Spring Boot 中使用 ':' 作为查询字符串的一部分编写 JPQL 查询

】在SpringBoot中使用\\\':\\\'作为查询字符串的一部分编写JPQL查询【英文标题】:WritingJPQLqueryinSpringbootwith\':\'asapartofthequerystring在SpringBoot中使用\':\'作为查询字符串的一部分编写JPQL查询【发布时间】:2018-09-1802:10:02【问题描述】:... 查看详情

Spring Boot 自定义查询 MongoDB

】SpringBoot自定义查询MongoDB【英文标题】:SpringbootcustomqueryMongoDB【发布时间】:2019-07-0704:31:56【问题描述】:我有这个MongoDb查询:db.getCollection(\'user\').find($and:["status":"ACTIVE","last_modified":$lt:newDate(),$gte:newDate(newDate().setDate 查看详情

Spring Boot请建议自定义查询

】SpringBoot请建议自定义查询【英文标题】:SpringBootpleasesuggestcustomQueryfor【发布时间】:2017-11-1707:33:02【问题描述】:select*fromngb.subsidywhere(有效开始日期,有效结束日期)重叠(\'2017-08-01\'::DATE,\'2017-08-01\'::DATE)按有效开始日期asc... 查看详情

如何在 Spring Boot Health 中添加自定义健康检查?

】如何在SpringBootHealth中添加自定义健康检查?【英文标题】:Howtoaddacustomhealthcheckinspringboothealth?【发布时间】:2017-12-0414:20:05【问题描述】:<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-st 查看详情

企业级spring-boot案例-自定义springbootstarter(代码片段)

文章目录1.未使用SpringBootStarter前的情况2.SpringBootStarter简介2.1什么是SpringBootStarter(启动器)2.2Starter模块整体结构2.3Spring官方提供的Starter和Starter命名规范3.自定义SpringBootStarter3.1根据starter命名规范创建一个springboot项目3.2... 查看详情

在 Spring Boot 中使用自定义错误 html 文件

】在SpringBoot中使用自定义错误html文件【英文标题】:Usingacustomerrorhtmlfileinspringboot【发布时间】:2019-05-0818:00:45【问题描述】:我有一个/error的url映射到我的errorPage.html,但它没有重定向到这个,我得到了正常的默认springboot错误... 查看详情

Spring Boot:考虑到用户角色,如何编写自定义 Pre Filter?

】SpringBoot:考虑到用户角色,如何编写自定义PreFilter?【英文标题】:SpringBoot:WhotowriteacustomPrefilter,consideringtheuserrole?【发布时间】:2019-03-1305:39:53【问题描述】:我需要某种@preFilter(或者,如果不可能,则比@postFilter)来过滤... 查看详情

在 Spring Boot 中使用 prometheus 自定义指标

】在SpringBoot中使用prometheus自定义指标【英文标题】:UsingprometheuscustommetricswithSpringBoot【发布时间】:2020-08-2222:11:49【问题描述】:我不确定这是一个错误,但我在过去一天尝试实现这个库,但没有任何结果。我认为这可能与依... 查看详情