springboot 入门教程(6)— 整合Spring data JPA实现CRUD(附源码)
先说下什么是JPA吧,JPA其实是EJB3.0的一个规范,相信老程序员都知道啦,它是基于O/R映射的标准规范,目前最新版本是JPA2.1。既然是规范即只定义了标准规则,不提供实现,软件提供商按照标准进行实现,使用者只需要按照标准定义的方式进行使用即可(就像JDBC一样)。
今天的主角是Spring data JPA,它是spring data的一个分支,默认是使用Hibernate实现(当然还有EclipseLink、OpenJPA等都可以)。所以我们作为使用者只需要按照规范使用即可,如果需要深度的定制一些内容则研究一下源码,也没那么难(后续如果有空给大家写一遍自定义通用的Repository可以实现一些jpa默认实现里面不带有的根据用户传入的实体自动进行查询,类似mybaitis中的动态sql)。
废话不多说,先看步骤:
1、引入必要的包(maven必备,别告诉我你不会用)
2、配置JPA启动相关参数
3、编写实体(添加注解)
4、编写service和controller(业务简单可以直接省略service)
1、引入必要的包(maven必备,别告诉我你不会用)
<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/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.pxk</groupId> <artifactId>SpringBootDemo_JPA</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <name>SpringBootDemo_JPA Maven Webapp</name> <url>http://maven.apache.org</url> <build> <finalName>SpringBootDemo_JPA</finalName> </build> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.6.RELEASE</version> <relativePath /> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <!-- web容器 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>1.5.6.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>4.3.10.RELEASE</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.40</version> </dependency> <!--日志 --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <!-- druid连接池 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.0.18</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> </project>
2、配置JPA启动相关参数
大家可能会有疑问了,为什么启动类里面看不到任何JPA的影子呢,因为只要我们引入spring-boot-starter-data-jpa,Spring Boot就会启动JPA的默认配置。
详见org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration
package com.pxk.springboot; import javax.sql.DataSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import com.alibaba.druid.pool.DruidDataSource; @SpringBootApplication public class Application { private final static Logger log=LoggerFactory.getLogger(Application.class); @Bean @ConfigurationProperties(prefix = "spring.datasource") //覆盖默认数据源 使用druid数据源 public DataSource dataSource() { return new DruidDataSource(); } public static void main(String[] args) { SpringApplication.run(Application.class, args); log.info("启动成功"); } }
单写上面一个启动类还是不够的,还需要加入一些需要的配置参数到application.properties中
# 数据库访问配置 # 主数据源,默认的 spring.datasource.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/springboot_demo_jpa?useUnicode=true&characterEncoding=UTF-8 spring.datasource.username=root spring.datasource.password=pxk server.port=8081 spring.http.encoding.force=true spring.http.encoding.charset=UTF-8 spring.http.encoding.enabled=true server.tomcat.uri-encoding=UTF-8 spring.jpa.show-sql= true ## 建表方式 spring.jpa.properties.hibernate.hbm2ddl.auto=update # 方言 spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
3、编写实体(添加注解)
这里需要注意下,JPA实体注解,在Hibernate升级到4.0以后有一些变化,使用了javax的默认注解替代了Hiernate原本的注解,这里对使用老版本的朋友来说不注意就是一个小坑。至于注解的使用这里主要是主键的生成策略,属性如果不加注解name对应数据库的name字段,userName对应数据库的user_name。另外还有一些长度限制非空限定等都可以使用注解实现。(最好的一点可以直接结合Hibernate validator进行后台数据验证,数据完整性的保证–前台验证是不保险的【搞过爬虫的同学肯定知道,前端很脆弱的】)
package com.pxk.springboot.domain; import java.io.Serializable; import java.util.Date; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import com.fasterxml.jackson.annotation.JsonFormat; @Entity public class User implements Serializable{ /** * */ private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String name; private Integer age; private String passWord; private String gender; // json日期格式化 @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date regestDate; // 默认构造函数不能少 ,如果没有会报ibatis.executor.ExecutorException: No constructor found public User() { super(); } public User(String name) { this.name = name; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getPassWord() { return passWord; } public void setPassWord(String passWord) { this.passWord = passWord; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public Date getRegestDate() { return regestDate; } public void setRegestDate(Date regestDate) { this.regestDate = regestDate; } }
4、编写service和controller(业务简单可以直接省略service)
UserServiceImpl.java
package com.pxk.springboot.serivce.imp; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import com.pxk.springboot.dao.UserDao; import com.pxk.springboot.domain.User; import com.pxk.springboot.serivce.UserService; @Service//注入成service public class UserServiceImpl implements UserService { @Autowired private UserDao userDao; @Override public User getUser(String name) { return new User(name); } @Override public Page<User> findUserByPage(Pageable pageInfo) { Page<User> list=userDao.findAll(new PageRequest(pageInfo.getPageNumber(), pageInfo.getPageSize())); return list; } @Override public User getUserById(Long id) { return userDao.findOne(id); } @Override public User updateUser(User user) { return userDao.saveAndFlush(user); } @Override public void deleteUser(User user) { userDao.delete(user); } @Override public User addUser(User user) { return userDao.saveAndFlush(user); } }
UserController.java
如果看了我前一篇springboot 入门教程(5) 基于ssm框架的crud操作(后台部分-附源码)的同学肯定会发现这个后台无法和上一篇的前端整合在一起使用,为什么呢?就是因为我们前端用了Bootstap table,它自动发送的ajax请求参数和我们后台接受的参数名不统一,如果要实现整合提供两种思路
1、修改前端BootStrap table源码,优点是懂前端的修改起来简单,很快就改完了。缺点是修改源码意味着当BootStrap table升级后你不能很顺利的升级。
2、那肯定是修改后台咯,修改后台又有两种方式,一种是想前一篇一样,引入两个辅助分页的类,编写一个父类,进行统一的参数接收和结果集的转换。第二种就是硬编码,在controller的每个分页方法里面去手动实现一遍参数和结果集的转换。(当然第一种更适合了,后续有时间给大家补充上这一部分)
package com.pxk.springboot.conntroller; import java.util.Date; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; import com.pxk.springboot.domain.User; import com.pxk.springboot.serivce.UserService; @RestController @RequestMapping("/user") public class UserController { @Autowired // 依赖注入service UserService userService; @RequestMapping("/findUserByPage") @ResponseBody public Page<User> getStudents(Pageable pageInfo) { return userService.findUserByPage(pageInfo); } @RequestMapping("/getUserById") protected User getUserById(Long id) { return userService.getUserById(id); } @RequestMapping("/deleteUser") protected void deleteUser(Long id) { User user = new User(); user.setId(id); userService.deleteUser(user); } @RequestMapping(value="/addUser") protected User addUser(User user) { if(user.getId()!=null&&user.getId()!=0){ return userService.updateUser(user); }else{ user.setRegestDate(new Date()); return userService.addUser(user); } } }
代码都很简单没什么可介绍的了。
简单总结下:
其实小项目,用户并发量小的项目用JPA肯定比mybaitis快,而且逆向工程对开发这种小项目可以说是事半功倍。其实JPA还有很多高级特性,如:事务、自定义Repository,复杂的关联查询等等。后面有机会再介绍。
下集预告:Spring Boot 集成Jpa 和Shiro ,token方式实现 web和app鉴权
原文地址:https://my.oschina.net/u/1791512/blog/1542562