近日学习了Spring Data系列,自己记录一下。

一、Spring Data JPA介绍

Spring Data JPA 是 Spring 基于 ORM 框架、JPA 规范的基础上封装的一套JPA应用框架,可使开发者用极简的代码即可实现对数据的访问和操作。它提供了包括增删改查等在内的常用功能,且易于扩展!学习并使用 Spring Data JPA 可以极大提高开发效率!

官方文档:https://docs.spring.io/spring-data/jpa/docs/2.1.4.RELEASE/reference/html/

二、Spring Boot 整合使用

1、创建Spring Boot 项目 添加依赖:需要web支持,jpa和mysql

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.46</version>
        </dependency>
    </dependencies>

2、application.yml文件:

spring:
  datasource:
    username: root
    password: 123
    url: jdbc:mysql://127.0.0.1:3306/shop?characterEncoding=UTF-8
    driverClassName: com.mysql.jdbc.Driver
  jpa:
    show-sql: true
    database: mysql
    hibernate:
      naming:
        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
#spring.japa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
#解决实体类变量驼峰命名报错问题

3.User实体类:

package com.wdg.springdatajpademo.pojo;

import javax.persistence.*;
import java.util.Date;

/**
 * @author WDG
 * @date 2019-2-4
 */
@Table(name="user")
@Entity
public class User {
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="userId")
    private Integer userId;
    private String username;
    private String password;
    @Column(name="regTime")
    private Date regTime;
    private Integer age;
    private String telephone;
    public Integer getUserId() {
        return userId;
    }
    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Date getRegTime() {
        return regTime;
    }

    public void setRegTime(Date regTime) {
        this.regTime = regTime;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getTelephone() {
        return telephone;
    }

    public void setTelephone(String telephone) {
        this.telephone = telephone;
    }
}

4、UserRepository代码:简单的CRUD操作和分页以及条件的动态查询,和自定义SQL以及遵循JPQL规范进行操作数据库,下面贴入代码:

package com.wdg.springdatajpademo.repository;

import com.wdg.springdatajpademo.pojo.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.util.List;

/**
 * @author WDG
 * @date 2019-2-4
 */
public interface UserRepository extends JpaRepository<User,Integer>, JpaSpecificationExecutor<User> {
    /**
     * 根据username修改用户信息
     * 加上nativeQuery = true 属性 表示自定义SQL
     * 传入参数对象类型 使用SPEL表达式
     * 官方文档 5.3.7. Using SpEL Expressions
     * 增删改操作 必须加上@Modifying 注解 5.3.8. Modifying Queries
     * @param user
     */
    @Query(value = "update user set userId =:#{#obj.userId},age=:#{#obj.age},password =:#{#obj.password}, regTime =:#{#obj.regTime}, telephone=:#{#obj.telephone} where username=:#{#obj.username} ",nativeQuery = true)
    @Modifying
    void updateUserByName(@Param("obj") User user);

    /**
     * 根据年龄查询
     * 遵循JPQL规则 5.3.2. Query Creation
     * @param age
     * @return
     */
    List<User> findUserByAge(int age);
}

5.UserService:

package com.wdg.springdatajpademo.service;

import com.wdg.springdatajpademo.pojo.User;


import com.wdg.springdatajpademo.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;

/**
 * @author WDG
 * @date 2019-2-4
 */
@Service
@Transactional
public class UserService {

    @Autowired
    private UserRepository userRepository;

    /**
     * 分页查询
     * @param page
     * @param size
     * @return
     */
    public Page<User> findByPage(int page,int size){
        PageRequest pageRequest = PageRequest.of(page - 1, size);
        return  userRepository.findAll(pageRequest);
    }
    /**
     * 根据主键查询
     * @param userId
     * @return
     */
    public User findById(int userId){
        return  userRepository.findById(userId).get();
    }

    /**
     * 条件查询+分页
     * @param page
     * @param size
     * @param user
     * @return
     */
    public Page<User> findByPageAndSelect(int page,int size,User user){
        return  userRepository.findAll(new Specification<User>() {
            /**
             *
             * @param root 根对象,也就是要把条件封装到哪个对象中, where
             * @param criteriaQuery 封装的都是查询关键字,比如group by order by等
             * @param criteriaBuilder 用来封装条件对象的,直接返回null,则为无条件查询
             * @return
             */
            @Override
            public Predicate toPredicate(Root<User> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                //创建Predicate集合,封装多个查询条件
                List<Predicate> list = new ArrayList<Predicate>();
                //假设查询用户年龄大于参数年龄,注册时间(regTime)在参数注册时间之前的,
                if(user !=null){
                    if(user.getAge()!=null){
                        list.add(criteriaBuilder.greaterThan(root.get("age").as(Integer.class), user.getAge()));
                    }
                    if(user.getRegTime()!=null){
                        list.add(criteriaBuilder.lessThan(root.get("regTime").as(Date.class), user.getRegTime()));
                    }
                }
                //集合转Predicate数组
                Predicate[] predicates = new Predicate[list.size()];
                return criteriaBuilder.and( list.toArray(predicates));
            }
        },PageRequest.of(page-1,size));
    }

    /**
     * 添加用户
     * @param user
     */
    public void addUser(User user){
        //设置注册时间
        user.setRegTime(new Date());
        userRepository.save(user);
    }
    /**
     * 修改
     * @param user
     */
    public void updateUser(User user){
        //更新注册时间
        user.setRegTime(new Date());
        userRepository.save(user);
    }
    /**
     * 删除用户
     * @param userId
     */
    public void deleteUser(int userId){
        userRepository.deleteById(userId);
    }

    /**
     * 根据用户名修改
     * @param user
     */
    public void updateUserByName(User user){
        userRepository.updateUserByName(user);
    }

    /**
     * 根据年龄查询
     * @param age
     * @return
     */
    public List<User> findUserByAge(int age){
        return  userRepository.findUserByAge(age);
    }
}

6.UserController 代码:

package com.wdg.springdatajpademo.controller;

import com.wdg.springdatajpademo.pojo.User;
import com.wdg.springdatajpademo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author WDG
 * @date 2019-2-4
 */
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    /**
     * 分页查询
     * @param page
     * @param size
     * @return
     */
    @GetMapping("/page/{page}/{size}")
    public List<User> findByPage(@PathVariable Integer page,@PathVariable Integer size){
        return userService.findByPage(page,size).getContent();
    }

    /**
     * id查询用户
     * @param userId
     * @return
     */
    @GetMapping("/{userId}")
    public User findByUserId(@PathVariable Integer userId){
        return userService.findById(userId);
    }
    /**
     * 注册用户
     * @param user
     * @return
     */
    @PostMapping("/addUser")
    public Map<String,Object> addUser(@RequestBody User user){
        Map map = new HashMap();
       try{
           userService.addUser(user);
       }catch (Exception e){
           e.printStackTrace();
           map.put("result",false);
           map.put("message","添加失败");
           return  map;
       }
        map.put("result",true);
        map.put("message","添加成功");
        return  map;
    }

    /**
     * 分页+条件查询
     * @param page
     * @param size
     * @param user
     * @return
     */
    @PostMapping("/pageandselect/{page}/{size}")
    public Map<String,Object> findByPageAndSelect(@PathVariable Integer page,
                                          @PathVariable Integer size,
                                          @RequestBody  User user){
        Map<String,Object> map = new HashMap<String,Object>();
        Page<User> result = userService.findByPageAndSelect(page, size, user);
        map.put("total",result.getTotalElements());
        map.put("totalPages",result.getTotalPages());
        map.put("data",result.getContent());
        return map;
    }

    /**
     * 修改用户
     * @param user
     * @return
     */
    @PutMapping("/updateUser")
    public Map<String,Object> updateUser(@RequestBody  User user){
        Map map = new HashMap();
        try{
            userService.updateUser(user);
        }catch (Exception e){
            e.printStackTrace();
            map.put("result",false);
            map.put("message","修改失败");
            return  map;
        }
            map.put("result",true);
            map.put("message","修改成功");
        return  map;
    }

    /**
     * 删除用户
     * @param userId
     * @return
     */
    @DeleteMapping("/deleteUser/{userId}")
    public Map<String,Object> deleteUser(@PathVariable  Integer userId){
        Map map = new HashMap();
        try{
            userService.deleteUser(userId);
        }catch (Exception e){
            e.printStackTrace();
            map.put("result",false);
            map.put("message","删除失败");
            return  map;
        }
        map.put("result",true);
        map.put("message","删除成功");
        return  map;
    }

    /**
     * 根据用户名修改用户
     * @param user
     * @return
     */
    @PutMapping("/updateUserByName")
    public Map<String,Object> updateUserByName(@RequestBody  User user){
        Map map = new HashMap();
        try{
            userService.updateUserByName(user);
        }catch (Exception e){
            e.printStackTrace();
            map.put("result",false);
            map.put("message","修改失败");
            return  map;
        }
        map.put("result",true);
        map.put("message","修改成功");
        return  map;

    }

    /**
     * 根据年龄查询用户信息
     * @param age
     * @return
     */
    @GetMapping("/findUserByAge/{age}")
    public List<User> findUserByAge(@PathVariable  Integer age){
        return  userService.findUserByAge(age);
    }
}

7、用postman进行测试即可,亲测可用。controller层对于异常处理代码不够简洁,下节总结SpringBoot 中使用全局异常处理器返回处理结果