一、测试环境
IDEA 2020.3
Java 11
PostgreSQL 12.3
二、开发环境搭建
pom.xml
不喜欢用parent引入的方式 , 所以自己引入了依赖并排除的冲突
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.mycloud</groupId> <artifactId>mycloud-core</artifactId> <version>0.0.0.1</version> <name>mycloud-core</name> <description>My Cloud Core</description> <properties> <java.version>11</java.version> <springboot.version>2.6.1</springboot.version> <log4j.version>2.16.0</log4j.version> <slf4j.version>1.8.0-beta4</slf4j.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>${springboot.version}</version> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-undertow</artifactId> <version>${springboot.version}</version> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> <version>${springboot.version}</version> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> <exclusion> <groupId>net.bytebuddy</groupId> <artifactId>byte-buddy</artifactId> </exclusion> <exclusion> <artifactId>jboss-logging</artifactId> <groupId>org.jboss.logging</groupId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <version>${springboot.version}</version> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <version>${springboot.version}</version> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> <exclusion> <groupId>jakarta.xml.bind</groupId> <artifactId>jakarta.xml.bind-api</artifactId> </exclusion> <exclusion> <groupId>net.bytebuddy</groupId> <artifactId>byte-buddy</artifactId> </exclusion> <exclusion> <artifactId>byte-buddy-agent</artifactId> <groupId>net.bytebuddy</groupId> </exclusion> </exclusions> <scope>test</scope> </dependency> <dependency> <groupId>net.bytebuddy</groupId> <artifactId>byte-buddy</artifactId> <version>1.11.22</version> </dependency> <dependency> <groupId>net.bytebuddy</groupId> <artifactId>byte-buddy-agent</artifactId> <version>1.11.22</version> </dependency> <dependency> <groupId>org.jboss.logging</groupId> <artifactId>jboss-logging</artifactId> <version>3.4.2.Final</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j2</artifactId> <version>${springboot.version}</version> </dependency> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <version>42.2.8</version> </dependency> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.9</version> </dependency> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>31.0.1-jre</version> </dependency> <dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> <version>2.3.1</version> </dependency> <dependency> <groupId>javax.activation</groupId> <artifactId>activation</artifactId> <version>1.1.1</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>${springboot.version}</version> </plugin> </plugins> </build> </project>
application.yml
server: port: 8081 undertow: io-threads: 32 worker-threads: 100 buffer-size: 1024 direct-buffers: true spring: profiles: active: dev
application-dev.yml
spring: devtools: restart: enabled: true #设置开启热部署 additional-paths: src/main/java,src/main/resources #重启目录 exclude: WEB-INF/** datasource: type: com.zaxxer.hikari.HikariDataSource driverClassName: org.postgresql.Driver url: jdbc:postgresql://127.0.0.1:5432/framework03 username: dbuser password: dbuserpwd # Hikari 连接池配置 # 最小空闲连接数量 hikari: minimum-idle: 5 # 空闲连接存活最大时间,默认600000(10分钟) idle-timeout: 180000 # 连接池最大连接数,默认是10 maximum-pool-size: 10 # 此属性控制从池返回的连接的默认自动提交行为,默认值:true auto-commit: true # 连接池名称 pool-name: Wanma-Cloud-Pool # 此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认1800000即30分钟 max-lifetime: 1800000 # 数据库连接超时时间,默认30秒,即30000 connection-timeout: 30000 connection-test-query: SELECT 1 jpa: datasource: postgresql show-sql: true hibernate: ddl-auto: update properties: hibernate: dialect: org.hibernate.dialect.PostgreSQL10Dialect temp: use_jdbc_metadata_defaults: false
三、主启动运行文件
Application.java
@SpringBootApplication /** 开启自动配置扫描 */ @EnableAutoConfiguration /** 自动扫描controller */ @ComponentScans(value = { @ComponentScan( value = "com.mycloud", useDefaultFilters = true, includeFilters = {@ComponentScan.Filter(type = FilterType.CUSTOM, classes = {IScanFilter.class})} ) }) /** 自动扫描entity */ @EntityScan(basePackages = {"com.mycloud"}) /** 自动扫描repository , basePackages集合不能有交集 */ @EnableJpaRepositories(basePackages = {"com.mycloud"}) public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
主要用来扫描过滤自动扫描的Controller类,增加效率
public class IScanFilter implements TypeFilter { private final static String CONTROLLER_PREFIX = "Controller"; @Override public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { String className = metadataReader.getClassMetadata().getClassName(); if (className.endsWith(CONTROLLER_PREFIX)) { return true; } return false; } }
四、JPA测试
1 . 首先建立Entity类 , 和数据库做直接映射 , 不要跟我说lombok , 最不喜欢这个插件
@Entity @Table(name = "ct_lib_book") public class CtLibBook { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "bookName", nullable = false) private String bookName; @Column(name = "description") private String description; @Column(name = "detail") private String detail; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getBookName() { return bookName; } public void setBookName(String bookName) { this.bookName = bookName; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getDetail() { return detail; } public void setDetail(String detail) { this.detail = detail; } @Override public String toString() { return bookName + "-" + description; } }
2.建立调用接口类(Repository)
@Repository public interface CtLibBookRepository extends JpaRepository<CtLibBook, Integer> { @Query(value = "select * from ct_lib_book", nativeQuery = true) List<CtLibBook> getAllBookData(); @Query(value = "select * from ct_lib_book where book_name = :bookName", nativeQuery = true) List<CtLibBook> getBooksByName(@Param("bookName") String bookName); }
3.建立Service层(非必须 , 但是必须要有)
@Service public class CtLibBookService { @Autowired private CtLibBookRepository ctLibBookRepository; public List<CtLibBook> getAll() { return ctLibBookRepository.getAllBookData(); } public List<CtLibBook> getNyBookname(String bookName) { return ctLibBookRepository.getBooksByName(bookName); } public void save(CtLibBook ctLibBook) { ctLibBookRepository.save(ctLibBook); } }
4.建立Controller层进行调用(测试用)
@RestController public class HelloController { @Autowired CtLibBookService ctLibBookService; @ResponseBody @RequestMapping("/hello") public String hello() { StringBuilder sb = new StringBuilder(); /// System.out.println("Get book All"); List<CtLibBook> temp = ctLibBookService.getAll(); for (int i = 0; i < temp.size(); i++) { CtLibBook book = temp.get(i); sb.append(IGson.format(book)); } /// System.out.println("Get book by Name"); temp = ctLibBookService.getNyBookname("AA"); for (int i = 0; i < temp.size(); i++) { CtLibBook book = temp.get(i); sb.append(IGson.format(book)); } return sb.toString(); } }
测试结果 :
PS :
当数据库中 , 没有表ct_lib_book是 , 会自动创建表 ,当表结构更新时 , 也会自动更新表结构
这个应该就是JPA最大的优势了 .
其他的优势 , 应该都被MyBatis-Plus给覆盖了.
5.鉴于JPA写复杂查询特别不方便的问题
写个Sql执行工具类
@Component public class SqlService { /// public static final SqlService me = new SqlService(); @PersistenceContext EntityManager em; public List<Map<String, Object>> query(String sql) { Query query = em.createNativeQuery(sql); @SuppressWarnings("unchecked") List<Map<String, Object>> list = query.unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).list(); return list; } public void excute(String sql) { Query query = em.createNativeQuery(sql); query.executeUpdate(); } }
如此 , 就能如此进行调用了
@RestController public class HelloController { @Autowired SqlService sqlService; @ResponseBody @RequestMapping("/hello") public String hello() { StringBuilder sb = new StringBuilder(); List<Map<String, Object>> results = sqlService.query("select * from ct_lib_book"); sb.append(IGson.format(results)); return sb.toString(); } }