springBoot04 - 使用spring data JPA 自定义Repository接口,使用原生sql语句查询数据库,返回自定义的类型数据

参考文档:https://blog.csdn.net/xiao_xuwen/article/details/53579353 

在一些特殊时候,我们会设计到对Spring Data JPA中的方法进行重新实现,这将会面临一个问题,如果我们新创建一个实现类。如果这个实现类实现了JpaRepository接口,这样我们不得不实现该接口中的所有方法,如果不实现该接口,那意味着我们就无法使用Spring Data JPA中给我们提供的那些好用的方法。所以在扩展的时候我们需要按照如下方法进行。

 

这些需要注意的是,接口和实现类的名称必须遵循spring data jpa的命名规范,如果要为接口StudentBaseRepository写自定义的接口,首先需要创建一个接口名称为StudentBaseRepositoryCustom,这表示是自定义接口,实现类的名称必须是StudentBaseRepositoryImpl,此时当StudentBaseRepository实现StudentBaseRepositoryCustom之后就可以使用我们自己实现的方法了,同理StudentBaseRepository也可以继承JpaRepository来获取Spring Data Jpa 给我们的方法。(以上为参考信息)

1.项目结构

2. pom文件修改

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 3     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 4     <modelVersion>4.0.0</modelVersion>
 5 
 6     <groupId>com.lch</groupId>
 7     <artifactId>springboot04</artifactId>
 8     <version>0.0.1-SNAPSHOT</version>
 9     <packaging>jar</packaging>
10 
11     <name>springboot04</name>
12     <description>Demo project for Spring Boot</description>
13 
14     <parent>
15         <groupId>org.springframework.boot</groupId>
16         <artifactId>spring-boot-starter-parent</artifactId>
17         <version>2.0.2.RELEASE</version>
18         <relativePath/> <!-- lookup parent from repository -->
19     </parent>
20 
21     <properties>
22         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
23         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
24         <java.version>1.8</java.version>
25     </properties>
26 
27     <dependencies>
28         <dependency>
29             <groupId>org.springframework.boot</groupId>
30             <artifactId>spring-boot-starter-data-jpa</artifactId>
31         </dependency>
32         <dependency>
33             <groupId>org.springframework.boot</groupId>
34             <artifactId>spring-boot-starter-web</artifactId>
35         </dependency>
36 
37         <dependency>
38             <groupId>mysql</groupId>
39             <artifactId>mysql-connector-java</artifactId>
40         </dependency>
41 
42         <dependency>
43             <groupId>org.springframework.boot</groupId>
44             <artifactId>spring-boot-starter-test</artifactId>
45             <scope>test</scope>
46         </dependency>
47         <!-- 对象转json依赖包 -->
48         <!-- https://mvnrepository.com/artifact/net.sf.json-lib/json-lib -->
49         <dependency>
50             <groupId>net.sf.json-lib</groupId>
51             <artifactId>json-lib</artifactId>
52             <version>2.4</version>
53             <!--不加下面这一项会报错,是因为json-lib支持版本是jdk1.5,所以要指定下版本-->
54             <classifier>jdk15</classifier>
55         </dependency>
56 
57 
58     </dependencies>
59 
60     <build>
61         <plugins>
62             <plugin>
63                 <groupId>org.springframework.boot</groupId>
64                 <artifactId>spring-boot-maven-plugin</artifactId>
65             </plugin>
66         </plugins>
67     </build>
68 
69 
70 </project>

修改完毕,在IDEA 工具栏 依次点击view , toolwindows, maven projects 打开maven管理窗口,点击刷新按钮,下载pom文件配置的依赖jar包

3.  数据库配置文件:连接本机mysql数据库 

 1 spring.datasource.url=jdbc:mysql://127.0.0.1/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=true
 2 spring.datasource.username=root
 3 spring.datasource.password=root
 4 spring.datasource.driver-class-name=com.mysql.jdbc.Driver
 5 
 6 spring.jpa.properties.hibernate.hbm2ddl.auto=update
 7 spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
 8 spring.jpa.show-sql= true
 9 #关闭thymeleaf的缓存,不然在开发过程中修改页面不会立刻生效需要重启,生产可配置为true
10 spring.thymeleaf.cache=false

4.  实体类映射数据库表,主键策略使用 GenerationType.AUTO ,即由hibernate选择主键策略

 1 package com.lch.springboot04.domain;
 2 
 3 import javax.persistence.*;
 4 
 5 /**
 6  * 实体类映射数据库表
 7  */
 8 @Entity
 9 @Table(name="user_test")
10 public class User {
11     @Id
12     @GeneratedValue(strategy = GenerationType.AUTO) //hibernate选择主键策略
13     private Long id;
14 
15     @Column(nullable = false)
16     private String password;
17     //name="username" 设置userName属性映射到数据库的username字段,而不是默认的user_name
18     @Column(name = "username", nullable = false)
19     private String userName;
20 
21     @Column(nullable = false)
22     private int age;
23 
24     public Long getId() {
25         return id;
26     }
27 
28     public void setId(Long id) {
29         this.id = id;
30     }
31 
32     public String getPassword() {
33         return password;
34     }
35 
36     public void setPassword(String password) {
37         this.password = password;
38     }
39 
40     public String getUserName() {
41         return userName;
42     }
43 
44     public void setUserName(String userName) {
45         this.userName = userName;
46     }
47 
48     public int getAge() {
49         return age;
50     }
51 
52     public void setAge(int age) {
53         this.age = age;
54     }
55 
56     public User() {
57     }
58 
59     public User(String password, String userName, int age) {
60         this.password = password;
61         this.userName = userName;
62         this.age = age;
63     }
64 }

5. 在 repository 包下 自定义原生sql 查询接口

 1 package com.lch.springboot04.repository;
 2 
 3 import org.springframework.data.jpa.repository.JpaRepository;
 4 import org.springframework.data.repository.NoRepositoryBean;
 5 
 6 import java.io.Serializable;
 7 import java.util.List;
 8 import java.util.Map;
 9 
10 /**
11  * 原生sql 查询接口
12  * @param <T>
13  * @param <ID>
14  */
15 @NoRepositoryBean
16 public interface BaseRepository<T,ID extends Serializable> extends JpaRepository<T,ID> {
17 
18     List<T> listBySql(String sql);
19 
20     List listObjectBySql(String sql);
21 
22     <S> List<S> listBySql(String sql,Class<T> clazz);
23 
24     List<Map<String,Object>> listMapBySql(String sql);
25 
26     Object getObjectBySql(String sql);
27 
28     int executeSql(String sql);
29 
30 }

6. 在repo包下建立  UserRepository ,继承BaseRepository

1 package com.lch.springboot04.repo;
2 
3 import com.lch.springboot04.domain.User;
4 import com.lch.springboot04.repository.BaseRepository;
5 
6 public interface UserRepository extends BaseRepository<User,Long> {
7 }

7. 在repo包下建base包,建BaseRepositoryImpl 类 和 BaseRepositoryFactoryBean 类

 1 package com.lch.springboot04.repo.base;
 2 
 3 import com.lch.springboot04.repository.BaseRepository;
 4 import org.hibernate.SQLQuery;
 5 import org.hibernate.criterion.CriteriaSpecification;
 6 import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
 7 
 8 import javax.persistence.EntityManager;
 9 import java.io.Serializable;
10 import java.util.List;
11 import java.util.Map;
12 
13 public class BaseRepositoryImpl<T, ID extends Serializable>
14         extends SimpleJpaRepository<T, ID>
15         implements BaseRepository<T, ID> {
16 
17     private final EntityManager entityManager;
18     private Class<T> clazz;
19 
20     public BaseRepositoryImpl(Class<T> domainClass, EntityManager entityManager) {
21         super(domainClass, entityManager);
22         this.clazz = domainClass;
23         this.entityManager = entityManager;
24     }
25 
26     @Override
27     public List<T> listBySql(String sql) {
28         return entityManager.createNamedQuery(sql, clazz).getResultList();
29     }
30 
31     @Override
32     public List listObjectBySql(String sql) {
33         return entityManager.createNativeQuery(sql).getResultList();
34     }
35 
36     @Override
37     public <S> List<S> listBySql(String sql, Class<T> clazz) {
38         return entityManager.createNativeQuery(sql, clazz).getResultList();
39     }
40 
41     @Override
42     public List<Map<String, Object>> listMapBySql(String sql) {
43         return entityManager.createNativeQuery(sql).unwrap(SQLQuery.class).setResultTransformer(CriteriaSpecification.ALIAS_TO_ENTITY_MAP).list();
44     }
45 
46     @Override
47     public Object getObjectBySql(String sql) {
48         List<Object[]> list = entityManager.createNativeQuery(sql).getResultList();
49         if (list != null && list.size() > 0 && list.get(0) != null) {
50             return list.get(0);
51         }
52         return null;
53     }
54 
55     @Override
56     public int executeSql(String sql) {
57         return entityManager.createNativeQuery(sql).executeUpdate();
58     }
59 }
 1 package com.lch.springboot04.repo.base;
 2 
 3 import org.springframework.data.jpa.repository.JpaRepository;
 4 import org.springframework.data.jpa.repository.support.JpaRepositoryFactory;
 5 import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean;
 6 import org.springframework.data.repository.core.RepositoryInformation;
 7 import org.springframework.data.repository.core.RepositoryMetadata;
 8 import org.springframework.data.repository.core.support.RepositoryFactorySupport;
 9 
10 import javax.persistence.EntityManager;
11 import java.io.Serializable;
12 
13 /**
14  * 参考 https://www.tianmaying.com/tutorial/spring-jpa-custom-all
15  * @param <R>
16  * @param <T>
17  * @param <I>
18  */
19 public class BaseRepositoryFactoryBean<R extends JpaRepository<T, I>, T, I extends Serializable>
20         extends JpaRepositoryFactoryBean<R, T, I> {
21 
22     public BaseRepositoryFactoryBean(Class<? extends R> repositoryInterface) {
23         super(repositoryInterface);
24     }
25 
26     @Override
27     protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
28         return new BaseRepositoryFactory(entityManager);
29     }
30 
31     private static class BaseRepositoryFactory<T,I extends Serializable> extends JpaRepositoryFactory {
32         private final EntityManager entityManager;
33 
34         public BaseRepositoryFactory(EntityManager entityManager) {
35             super(entityManager);
36             this.entityManager = entityManager;
37         }
38 
39         @Override
40         protected Object getTargetRepository(RepositoryInformation information) {
41             return new BaseRepositoryImpl<T,I>((Class<T>) information.getDomainType(),entityManager);
42         }
43 
44         @Override
45         protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
46             return BaseRepositoryImpl.class;
47         }
48     }
49 
50 }

8.  建立config包,编写配置类

 1 package com.lch.springboot04.config;
 2 
 3 import com.lch.springboot04.repo.base.BaseRepositoryFactoryBean;
 4 import org.springframework.context.annotation.Configuration;
 5 import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
 6 
 7 /**
 8  * 配置类,不配置,会报错,找不到bean
 9  */
10 @Configuration
11 //指定自己的工厂类
12 @EnableJpaRepositories(basePackages = {"com.lch.springboot04"},
13         repositoryFactoryBeanClass = BaseRepositoryFactoryBean.class)
14 public class RepositoryConfig {
15 }

9. service层 ,注入 UserRepository  实例,这里实现查询所有user, 以 List<Map<String, Object>> 格式返回数据

 1 package com.lch.springboot04.service;
 2 
 3 import com.lch.springboot04.repo.UserRepository;
 4 import org.springframework.beans.factory.annotation.Autowired;
 5 import org.springframework.stereotype.Service;
 6 
 7 import java.util.List;
 8 import java.util.Map;
 9 
10 @Service
11 public class UserService {
12     @Autowired
13     UserRepository userRepository;
14 
15     public List<Map<String, Object>> getAll() {
16         String sql = "select * from user";
17         return userRepository.listMapBySql(sql);
18     }
19 
20 }

10.controller层

 1 package com.lch.springboot04.controller;
 2 
 3 import com.lch.springboot04.service.UserService;
 4 import net.sf.json.JSONArray;
 5 import org.springframework.beans.factory.annotation.Autowired;
 6 import org.springframework.web.bind.annotation.RequestMapping;
 7 import org.springframework.web.bind.annotation.RestController;
 8 
 9 import java.util.List;
10 import java.util.Map;
11 
12 
13 @RestController
14 @RequestMapping("/user")
15 public class UserController {
16 
17     @Autowired
18     UserService userService;
19 
20     @RequestMapping("/index")
21     public String index(){
22         return "success";
23     }
24     @RequestMapping("/getall")
25     public String getAll(){
26         List<Map<String, Object>> users = userService.getAll();
27         return JSONArray.fromObject(users).toString();
28     }
29 
30 }
JSONArray.fromObject(users).toString(); 把list 转换为json数组返回给请求调用者。

11.springboot 启动类,不用动

 1 package com.lch.springboot04;
 2 
 3 import org.springframework.boot.SpringApplication;
 4 import org.springframework.boot.autoconfigure.SpringBootApplication;
 5 
 6 @SpringBootApplication
 7 public class Springboot04Application {
 8     public static void main(String[] args) {
 9         SpringApplication.run(Springboot04Application.class, args);
10     }
11 }

启动项配置

配好之后启动项目,启动完成,会显示所使用的端口号

访问  http://localhost:8080/user/getall 结果如下:(数据库中事先有数据)

猜你喜欢

转载自www.cnblogs.com/enjoyjava/p/9142697.html