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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>per.qiao</groupId>
<artifactId>springbootdemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springbootdemo</name>
<description>sprnigboot学习</description> <properties>
<java.version>1.8</java.version>
</properties> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- 扩展JPA包 -->
<dependency>
<groupId>com.slyak</groupId>
<artifactId>spring-data-jpa-extra</artifactId>
<version>2.1.2.RELEASE</version>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency> <dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build> </project>

得益于spring-data-jpa-extra 包

先编写两个文件

@Configuration
@EnableConfigurationProperties(SpringJpaExtraProperties.class)
@AutoConfigureAfter({ DataSourceAutoConfiguration.class })
public class JpaExtraAutoConfiguration { @Autowired
private SpringJpaExtraProperties springJpaProperties; @Bean
protected FreemarkerSqlTemplates freemarkerSqlTemplates() {
FreemarkerSqlTemplates sqlTemplates = new FreemarkerSqlTemplates();
String templateBasePackage = springJpaProperties.getTemplateBasePackage();
if (templateBasePackage != null) {
sqlTemplates.setTemplateBasePackage(templateBasePackage);
}
String templateLocation = springJpaProperties.getTemplateLocation();
if (templateLocation != null) {
sqlTemplates.setTemplateLocation(templateLocation);
}
// 默认是xml
sqlTemplates.setSuffix(".sftl");
return sqlTemplates;
}
}
@ConfigurationProperties(prefix = "spring.jpa.extra")
public class SpringJpaExtraProperties { /**
* 源码看 FreemarkerSqlTemplates.resolveSqlResource
* 例如 templateLocation:classpath:/sqltemplates 那么 扫描路径为 classpath:/sqltemplates/** /*.sftl
* templateLocation:classpath:/sqltemplates/Test.sftl 那么将只扫描这个一个文件
* 例如 templateBasePackage:sqltemplates.mysql 那么扫描路径为 classpath*: sqltemplates/sql/** /*.sftl
*
* 两个属性可以共存
*/
private String templateLocation; private String templateBasePackage; public String getTemplateLocation() {
return templateLocation;
} public void setTemplateLocation(String templateLocation) {
this.templateLocation = templateLocation;
} public String getTemplateBasePackage() {
return templateBasePackage;
} public void setTemplateBasePackage(String templateBasePackage) {
this.templateBasePackage = templateBasePackage;
}
}

再写一个facoties文件

META-INF/spring.facotries

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
per.qiao.config.JpaExtraAutoConfiguration

yml文件

debug: false
spring:
main:
banner-mode: "off"
jpa:
database: mysql
show-sql: true
hibernate:
ddl-auto: update
naming:
#命名策略
strategy: org.hibernate.cfg.ImprovedNamingStrategy
properties:
hibernate:
dialect: org.hibernate.dialect.MySQL5Dialect
extra:
#源码看 FreemarkerSqlTemplates.resolveSqlResource
#templateLocation: classpath: sqltemplates
templateBasePackage: sqltemplates
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/test?characterEncoding=utf8
username: root
password: 123456

Dao文件

public interface TestRepository extends GenericJpaRepository<Test, Long>, JpaSpecificationExecutor {

    @TemplateQuery
List<Test> getData(); @TemplateQuery
List<Test> getList(@Param("id") Integer id); @TemplateQuery
List<Test> getListByPage(Test test, Pageable pageable); @TemplateQuery
List<Map<String, Object>> getListMap(@Param("id") Integer id); @TemplateQuery
Page<Test> findByName(String name, Pageable pageable); // 这个是JPA默认的支持@Query使用原生sql
@Query(nativeQuery = true, value = "select * from test where name like ?1")
List<Test> findTest(String name);
}

sql的文件 Test.sftl

该文件使用freemarker的语法 FreeMarker基础语法

--getData
select id, name, subject from test where 1 = 1
<#--<#if content??>-->
<#--AND id = ${id}-->
<#--</#if>--> --getList
select * from test where 1 = 1
<#if id??>
AND id = ${id}
</#if> --getListByPage
select * from test where 1 = 1
<#if id??>
AND id = ${id}
</#if> --getListMap
select name, birthday from test t left join test2 t2 on t.id = t2.id where 1 = 1
<#if id??>
And t.id = ${id}
</#if> --findByName
select * from test
<#if name??>
And name = ${name}
</#if>

entity

@Entity
@ToString
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Test implements Serializable { @Id
private Long id; private String name;
private String subject;
private Integer score;
}

spirngBoot启动类上要加上@EnableJpaRepositories

@SpringBootApplication
@RestController
@ComponentScan({"per.qiao.entity"})
@EnableJpaRepositories(
basePackages = {"per.qiao.**.dao"},
repositoryFactoryBeanClass = GenericJpaRepositoryFactoryBean.class,
repositoryBaseClass = GenericJpaRepositoryImpl.class)
public class App {

调用


public void say() {
// getData
List<Test> data = testRepository.getData();
//
List<Test> tests = testRepository.getList(1);
//
Test test = Test.builder().id(1L).build();
PageRequest pageRequest = new PageRequest(1, 2, new Sort(Sort.Direction.ASC, "id"));
List<Test> pageDatas = testRepository.getListByPage(test, pageRequest);
System.out.println(pageDatas);
//
List<Map<String, Object>> listMap = testRepository.getListMap(1); //
Page<Test> page = testRepository.findByName("张三", pageRequest);
List<Test> content = page.getContent();
System.out.println(content); // 使用jpa的默认@Query注解
List<Test> tests = testRepository.findTest("张%");
System.out.println(tests);
}

注意sftl配置文件的名字要与实体类的名字一样

可以自定义修改一些东西,比如文件名与类名一样这点,关键类在FreemarkerTemplateQuery

源码地址: spring-data-jpa-extra

JPA扩展(自定义sql)的更多相关文章

  1. mybatis的sqlprovider用法扩展自定义sql

    SqlProvider使用 public class MemberRewardSqlProvider { private static final Logger log = LoggerFactory ...

  2. JPA中自定义的插入、更新、删除方法为什么要添加@Modifying注解和@Transactional注解?

    前几天,有个同事在使用JPA的自定义SQL方法时,程序一直报异常,捣鼓了半天也没能解决,咨询我的时候,我看了一眼他的程序,差不多是这个样子的: @Repository public interface ...

  3. JPA 开发写SQL时候遇见的困难点

    官方文档 https://docs.spring.io/spring-data/jpa/docs/1.11.16.RELEASE/reference/html/#repositories.specia ...

  4. spring-jpa通过自定义sql执行修改碰到的问题

    在编写自定义SQL的时候需要注意 @Query 注解只能用来查询,想要进行添加.修改和删除操作需要配合 @Modifying 注解一同使用 @Modifying @Query("update ...

  5. phpcmsv9自定义sql语句查询模型实现

    在phpcmsv9中,自定义sql语句查询可不太好实现,传入sql语句查询很容易被内部转入生成一系列莫名其妙的sql语句,比如最佳前缀等等,直接造成sql语句查询错误,在此也提供两种解决办法,1修改底 ...

  6. thinkjs中自定义sql语句

    一直以为在使用thinkjs时,只能是它自带的sql语句查询,当遇到类似于这样的sql语句时,却不知道这该怎样来写程序,殊不知原来thinkjs可以执行自定义sql语句 SELECT * from a ...

  7. 11月16日《奥威Power-BI基于SQL的存储过程及自定义SQL脚本制作报表》腾讯课堂开课啦

           上周的课程<奥威Power-BI vs微软Power BI>带同学们全面认识了两个Power-BI的使用情况,同学们已经迫不及待想知道这周的学习内容了吧!这周的课程关键词—— ...

  8. springboot2.0 JPA配置自定义repository,并作为基类BaseRepository使用

    springboot2.0 JPA配置自定义repository,并作为基类BaseRepository使用 原文链接:https://www.cnblogs.com/blog5277/p/10661 ...

  9. django不定义model,直接执行自定义SQL

    如果不想定义model,直接执行自定义SQL,可如下操作: 1. 通过 connections获取db连接,如果是多个数据库,connections['dbName'] 来选择 2. 获取游标 cur ...

  10. Python Django 之 直接执行自定义SQL语句(二)

    转载自:https://my.oschina.net/liuyuantao/blog/712189 一般来说,最好用 Django 自带的模型来实现这些操作.这里仅仅只是为了学习使用原始 SQL 而做 ...

随机推荐

  1. vue中的父组件传值给子组件

    以上父组件以及父组件里面的代码 下面是子组件以及里面的代码

  2. mysql插入数据自动生成主键uuid

    DemoMapper.java //注意方法的返回值必须是void; void add(Demo demo); ============================================ ...

  3. Nexus 3搭建及备份恢复

    Nexus 3搭建 官网下载相应的软件版本:Nexus官网 配置仓库存放地址 # tar xf xxxx # more bin/nexus.vmoptions -Xms500M -Xmx500M -X ...

  4. Django 测试开发1

    笔者用的版本的是django==1.8.2,这个版本的学习资料最多,文档最完整.首先创建项目:django-admin startproject 项目名. guest/__init__.py 一个空的 ...

  5. Java并发包线程池之ForkJoinPool即ForkJoin框架(二)

    前言 前面介绍了ForkJoinPool相关的两个类ForkJoinTask.ForkJoinWorkerThread,现在开始了解ForkJoinPool.ForkJoinPool也是实现了Exec ...

  6. HTML5Audio/Video全解(疑难杂症)

    1.mp4格式视频无法在chrome中播放 Chrome浏览器支持HTML5,它支持原生播放部分的MP4格式(不用通过Flash等插件).为 什么是部分MP4呢?MP4有非常复杂的含义(见http:/ ...

  7. Oracle 11g 监听很慢,由于监听日志文件太大引起的问题(Windows 下)

    现象:Windows 操作系统的Oracle 数据库,使用sqlplus 连接(不指定实例名)连接很快,程序连接或使用连接工具或在Net Manager 中测试连接都需要花费约三四十秒的时间(程序连接 ...

  8. web自动化01-自动化解决的问题-环境搭建-元素定位

    自动化测试 概念:由程序代码代替人工完成验证系统功能的过程 解决的问题: 回归测试 压力测试 兼容性测试 提高测试效率,提升产品质量 自动化测试分类 web自动化测试 移动自动化测试 接口自动化测试 ...

  9. Delphi下Treeview控件基于节点编号的访问1

    有时我们需要保存和重建treeview控件,本文提供一种方法,通过以树结构节点的编号访问树结构,该控件主要提供的方法如下:      function GetGlobeNumCode(inNode:T ...

  10. 生成对抗网络GAN详解与代码

    1.GAN的基本原理其实非常简单,这里以生成图片为例进行说明.假设我们有两个网络,G(Generator)和D(Discriminator).正如它的名字所暗示的那样,它们的功能分别是: G是一个生成 ...