SpringBoot使用SpringDataJPA完成CRUD

SpringBoot已经为我们提供了很多种的数据库来做数据存储以及读取,如关系型数据库:MySQL,oracle,sqlserver。非关系型数据库:redis,mongodb等。
本项目学习并且使用SpringBoot访问MySQL数据库,并且结合SpringDataJPA完成CRUD(Create,Read,Update,Delete)简单操作。
Maven依赖:
<!-- 通过JPA方式操作数据库 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
YML配置:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8
username: root
password: root
jpa:
hibernate:
#create 代表在数据库创建表,update 代表更新,首次启动需要create ,如果你想通过hibernate 注解的方式创建数据库的表的话,之后需要改为 update.
ddl-auto: update
#打印sql
show-sql: true

创建实体类:基于JPA/Hibernate注解,优先基于JPA注解,便于移植
User:
package com.po;
import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;
/**
* 客户
*/
@Entity
public class User{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)//主键递增
private Integer id;
private String userName;
private Integer userAge;
private String userAddress;
private Integer gender;
//一对多那方设置懒加载
/**
* @OneToMany注解
* mappedBy:肯定是定义在被拥有方的(一的一方),指向拥有方,表示由拥有方(多的一方)来自动维护和被拥有方的关系
* cascade:用户描述级联关系,可能值有none/all/save-update/delete
* none:表示所有情况下均不进行关联操作。这是默认值
* all:表示所有情况下均进行关联操作,即save-update/delete
* save-update:表示仅在执行save/update/saveOrupdate时进行关联操作
* delete:表示在执行delete时关联操作
* fetch:用来指定加载方式,是延迟加载(lazy),还是急加载(eager)
* eager:急加载好理解,在加载一个实体的时候,急加载的属性或者字段会立即从数据库中加载出来
* lazy:会经常遇到一个问题,为什么定义了延迟加载,但却没有作用,相关的属性或者字段还是会立即加载出来
*
*
*/
@OneToMany(mappedBy="user",cascade= CascadeType.ALL,fetch=FetchType.LAZY)
private Set<Account> accounts = new HashSet<Account>();
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Integer getUserAge() {
return userAge;
}
public void setUserAge(Integer userAge) {
this.userAge = userAge;
}
public String getUserAddress() {
return userAddress;
}
public void setUserAddress(String userAddress) {
this.userAddress = userAddress;
}
public Integer getGender() {
return gender;
}
public void setGender(Integer gender) {
this.gender = gender;
}
public Set<Account> getAccounts() {
return accounts;
}
public void setAccounts(Set<Account> accounts) {
this.accounts = accounts;
}
}
Account:
package com.po;
import com.fasterxml.jackson.annotation.JsonIgnore;
import javax.persistence.*;
/**
* 账户
*/
@Entity
public class Account {
@Id//主键
@GeneratedValue(strategy = GenerationType.IDENTITY)//主键递增
private Integer id;
private String accountNumber;
private Integer bankId;
@ManyToOne(cascade={CascadeType.MERGE,CascadeType.REFRESH},targetEntity = User.class)
/**
* @JoinColumn注解
* name:account表中用来关联user表的外键,设置之后会在account表中生成user_id字段
* referencedColumnName:用来标注关联的是user表的哪一个字段,这里关联的是user表的id字段
*/
@JoinColumn(name="userId", referencedColumnName="id", insertable=false, updatable=false)
@JsonIgnore //jackjson序列化时,忽略该字段,防止递归循环解析
private User user;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getAccountNumber() {
return accountNumber;
}
public void setAccountNumber(String accountNumber) {
this.accountNumber = accountNumber;
}
public Integer getBankId() {
return bankId;
}
public void setBankId(Integer bankId) {
this.bankId = bankId;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
创建DAO接口:
package com.dao;
import com.po.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import java.util.List;
/**
*/
//注意JpaRepository和CrudRepository的区别
public interface UserDAO extends JpaRepository<User,Integer>,JpaSpecificationExecutor {
//简单一点的查询:可以通过方法名称(JPA命名规则)判别
public List<User> findByGender(Integer gender);
//稍微复杂一点的用@Query注解
@Query("from User where gender=?1 and userAge>20 and userName like ?2")
public List<User> findByAgeAndGender(Integer gender,String userName);
}
如果只是简单的增删查询,只要继承JpaRepository<Girl,Integer>就行。springboot 将接口类会自动注解到spring容器中,不需要我做任何配置。
如果需要复杂查询(分页、多表联查),则考虑同时继承JpaSpecificationExecutor

创建控制器:
package com.web;
import com.po.User;
import com.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
*/
@RequestMapping("/user")
@RestController
public class UserController {
@Autowired
private UserService userService;
//访问/hello或者/hi任何一个地址,都会返回一样的结果
@RequestMapping(value = {"/all"},method = RequestMethod.GET)
public List<User> findAll(){
List<User> userList = userService.getUserDAO().findAll();
return userList;
}
@Transactional //添加事物,如果执行save()方法中发生了异常,则回滚。 @RequestMapping("/save") public void save(){ User user_0 = new User(); user_0.setGender(0); user_0.setUserName("王五"); user_0.setUserAddress("江苏常州区"); user_0.setUserAge(30); User user_1 = new User(); user_1.setGender(0); user_1.setUserName("麻子"); user_1.setUserAddress("江苏常州区"); user_1.setUserAge(30); userService.getUserDAO().save(user_0); int a = 2/0; userService.getUserDAO().save(user_1); } @RequestMapping("/info") public User info(){ User user = userService.getUserDAO().findOne(1);//这里用findOne,getOne返回的只是一个引用,对象的属性值都是空的 return user; } @RequestMapping("/delete") public void delete(){ userService.getUserDAO().delete(3); } @RequestMapping("/findByGender") public List<User> findByGender(){ return userService.getUserDAO().findByGender(0); } @RequestMapping("/findByAgeAndGender") public List<User> findByGenderAndAge(){ return userService.getUserDAO().findByAgeAndGender(0,"%李四%"); } @RequestMapping("/query") public Page<User> query(){ Page<User> page = userService.query("张三",0,10); return page; } }