SpringData 基于SpringBoot快捷入门

SpringBoot 连接池配置疑惑

大家只是在全局配置文件中装置了有关值,就到位了连接池的布置,想必咱们都有着疑惑。其实当大家在pom.xml文件中投入spring-boot-starter-data-jpa
倚重时,SpringBoot就会活动使用tomcat-jdbc连接池。
本来大家也得以采纳任何的连接池。
https://www.cnblogs.com/gslblog/p/7169481.html
(springBoot数据库连接池常用配备)
https://www.cnblogs.com/xiaosiyuan/p/6255292.html (SpringBoot使用c3p0)

Repository接口层

开创UserRepository,这是SpringData 的中心知识点,我们先看代码

import java.util.List;
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.PagingAndSortingRepository;
import org.springframework.data.repository.query.Param;
import com.itdragon.pojo.User;

/**
 * 核心知识:SpringData Repository 接口
 * 
 * CrudRepository 接口提供了最基本的对实体类的添删改查操作 
 * - T save(T entity);                  //保存单个实体 
 * - T findOne(ID id);                  // 根据id查找实体         
 * - void delete(ID/T/Iterable);        // 根据Id删除实体,删除实体,批量删除 
 * PagingAndSortingRepository 提供了分页与排序功能
 * - <T, ID extends Serializable>           // 第一个参数传实体类,第二个参数传注解数据类型
 * - Iterable<T> findAll(Sort sort);        // 排序 
 * - Page<T> findAll(Pageable pageable);    // 分页查询(含排序功能)
 * JpaSpecificationExecutor 提供了Specification(封装 JPA Criteria查询条件)的查询功能
 * - List<T> findAll(Specification<T> spec);
 * - Page<T> findAll(Specification<T> spec, Pageable pageable);
 * - List<T> findAll(Specification<T> spec, Sort sort);
 * 
 * 开发建议
 * 1. 这里值列出的是常用方法
 * 2. CrudRepository 中的findAll() 方法要慎用。当数据库中数据量大,多线程脚本调用findAll方法,系统可能会宕机。
 * 3. CrudRepository 中的deletAll()方法要慎用。这是物理删除,现在企业一般采用逻辑删除。
 * 4. PagingAndSortingRepository 和 JpaSpecificationExecutor 能满足大部分业务需求。
 */
public interface UserRepository extends PagingAndSortingRepository<User, Long>, 
    JpaSpecificationExecutor<User>{

    /**
     * 重点知识:SpringData 查询方法定义规范
     * 
     * 1. 查询方法名一般以 find | read | get 开头,建议用find
     *  findByAccount : 通过account查询User
     *  account是User的属性,拼接时首字母需大写
     * 2. 支持的关键词有很多比如 Or,Between,isNull,Like,In等
     *  findByEmailEndingWithAndCreatedDateLessThan : 查询在指定时间前注册,并以xx邮箱结尾的用户
     *  And : 并且
     *  EndingWith : 以某某结尾
     *  LessThan : 小于
     * 
     * 注意
     * 若有User(用户表) Platform(用户平台表) 存在一对一的关系,且User表中有platformId字段
     * SpringData 为了区分:
     * findByPlatFormId     表示通过platformId字段查询
     * findByPlatForm_Id    表示通过platform实体类中id字段查询
     * 
     * 开发建议
     * 表的设计,尽量做单表查询,以确保高并发场景减轻数据库的压力。
     */

    // 1 通过账号查用户信息
    User findByAccount(String account);
    // 2 获取指定时间内以xx邮箱结尾的用户信息
    List<User> findByEmailEndingWithAndCreatedDateLessThan(String email, String createdDate);

    /**
     * 重点知识:使用 @Query 注解
     * 
     * 上面的方法虽然简单(不用写sql语句),但它有最为致命的问题-----不支持复杂查询,其次是命名太长
     * 1. 使用@Query 注解实现复杂查询,设置 nativeQuery=true 使查询支持原生sql
     * 2. 配合@Modifying 注解实现创建,修改,删除操作
     * 3. SpringData 默认查询事件为只读事务,若要修改数据则需手动添加事务注解
     * 
     * 注意
     * 若@Query 中有多个参数,SpringData 提供两种方法:
     * 第一种 ?1 ... ?2        要求参数顺序一致
     * 第二种 :xxx ... :yyy    xxx 和 yyy 必须是实体类对应的属性值,不要求参数顺序但参数前要加上@Param("xxx")
     * 模糊查询可使用 %xxx%
     * 
     * 开发建议
     * 1. 参数填写的顺序要保持一致,不要给自己添加麻烦
     * 2. 建议使用@Query,可读性较高
     */
    // 3 获取某平台活跃用户数量
    @Query(value="SELECT count(u.id) FROM User u WHERE u.platform = :platform AND u.updatedDate <= :updatedDate")
    long getActiveUserCount(@Param("platform")String platform, @Param("updatedDate")String updatedDate);

    // 4 通过邮箱或者手机号模糊查询用户信息
    @Query(value="SELECT u FROM User u WHERE u.email LIKE %?1% OR u.iphone LIKE %?2%")
    List<User> findByEmailAndIhpneLike(String email, String iphone);

    // 5 修改用户邮箱
    @Modifying
    @Query("UPDATE User u SET u.email = :email WHERE u.id = :id")
    void updateUserEmail(@Param("id") Long id, @Param("email") String email);

}

代码中共有六个办法,每个方法都饱含了无数的知识点。
格局一和模式二关键介绍的是SpringData关键字的用法。
1 一言九鼎字的分析
那里用findByPlatFormId() 方法来介绍SpringData 解析查询艺术的流水线。
首先步:去除关键字findBy
第二步:剩下的PlatFormId
首字母小写并在User对象中找是否有该属性,若有则查询并截止。若没有则第三步
其三步:platFormId,从右到左截取到第一个大写字母,再判断剩下的platForm是否为User对象,如此循环直到截至停止。
2 级联属性区分
若查询的习性是实体类,为了防止误会和争持,用”_”表示属性中的属性
3 询问分页排序
若findByPlatFormId()方法想要排序或者分页,是能够在末端加Pageable,Sort参数。
findByPlatFormId(String platFormId, Pageable pageable)
findByPlatFormId(String platFormId, Sort sort)
4 其余的显要字
图片 1

方法三到点子五最紧要介绍的是 @Query 讲明的行使。
1 传参情势
目录参数:?n
,n从1起先,表示第一个参数。方法传入的参数的照顺序和个数要和 n
保持一致。
命名参数::key ,传参必须有 @Param(“key”) 讲明修饰
2 原生的sql
@Query 申明帮忙地方查询,即用原生的sql语句。如:@Query(value=”xxxx”,
nativeQuery=true)
3 Modifying
若间接执行修改操作,SpringDataJPA 会提醒错误消息 Executing an
update/delete query 。是因为Spring Data
默认所有的查询均声称为只读事务。
故而我们要在瑟维斯(Service)(Service)层添加 @Transactional 注明。

SpringDataJPA 大旨知识Repository接口
1 Repository:
空接口,标识成效,阐明任何继承它的均为Repository接口类
2 CrudRepository: 继承 Repository,实现了一组 CRUD 相关的法子 
3 PagingAndSortingRepository: 继承
CrudRepository,实现了一组分页排序相关的主意
4 JpaRepository: 继承 PagingAndSortingRepository,实现一组 JPA
规范相关的章程
5 JpaSpecificationExecutor: 不属于Repository系列,实现一组 JPA
Criteria 查询相关的不二法门 
PagingAndSortingRepository 和 JpaSpecificationExecutor
基本满足公司中多数的需要。也得以自定义Repository,只需连续
JpaRepository 即可享有了通用的数码访问控制层的能力。
跻身各自接口类中,使用高效键 Ctrl + o
即可查看当前类的装有办法,所以这边就不贴出来了。

Service层

创设UserService 并加上注脚 @Transactional

import javax.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.itdragon.common.ItdragonResult;
import com.itdragon.pojo.User;
import com.itdragon.repository.UserRepository;

@Service
@Transactional
public class UserService {

    @Autowired
    private UserRepository userRepository;

    public ItdragonResult registerUser(User user) {
        // 检查用户名是否注册,一般在前端验证的时候处理,因为注册不存在高并发的情况,这里再加一层查询是不影响性能的
        if (null != userRepository.findByAccount(user.getAccount())) {
            return ItdragonResult.build(400, "");
        }
        userRepository.save(user);
        // 注册成功后选择发送邮件激活。现在一般都是短信验证码
        return ItdragonResult.build(200, "");
    }

    public ItdragonResult editUserEmail(String email) {
        // 通过Session 获取用户信息, 这里假装从Session中获取了用户的id,后面讲解SOA面向服务架构中的单点登录系统时,修改此处代码 FIXME
        long id = 3L;
        // 添加一些验证,比如短信验证
        userRepository.updateUserEmail(id, email);
        return ItdragonResult.ok();
    }

}

总结

1 SpringDataJPA 是简化JPA开发的框架,SpringBoot是简化项目支出的框架。
2 spring-boot-starter-parent 是SpringBoot项目标注明
3 SpringBootApplication 讲明是SpringBoot项目标输入
4 SpringData 通过询问关键字和 @Query阐明实现对数据库的拜访
5 SpringData 通过PagingAndSortingRepository
实现分页,排序和常用的crud操作

源码地址:https://github.com/ITDragonBlog/daydayup/tree/master/SpringBoot/SpringData

到这边 SpringData
基于SpringBoot急忙入门就寿终正寝了,倘诺有哪些问题请指教,如果以为不错可以点一下推介。

或许存在的题材

配备全局文件

再看看SpringBoot项目全局配置文件 application.properties

# 配置tomcat端口号
server.port=8081

# 配置SpringMVC视图解析器
spring.mvc.view.prefix=/WEB-INF/views/
spring.mvc.view.suffix=.jsp

# 配置连接池,默认使用的是tomcat的连接池,但实际很少用tomcat的连接池
spring.datasource.url=jdbc:mysql://localhost:3306/jpa?useUnicode=true&characterEncoding=UTF8
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
# 配置方言 否则提示:Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set
spring.jpa.database-platform=org.hibernate.dialect.MySQL5Dialect
# 自动更新数据库表结构,也可以是 validate | update | create | create-drop
spring.jpa.properties.hibernate.hbm2ddl.auto=update
# 显示sql语句
spring.jpa.show-sql=true

全局配置文件可以是application.properties 也得以是
application.yml,提出坐落resources目录下。更多安排:
https://github.com/ITDragonBlog/daydayup/blob/master/SpringBoot/SpringData/springbootStudy/src/main/resources/springboot.properties

SpringData 基于SpringBoot急迅入门

本章通过学习SpringData 和SpringBoot
相关文化将面向服务架构(SOA)的单点登录系统(SSO)需要的代码实现。那样可以从实战中学习六个框架的知识,又足以为单点登录系统打下基础。通过本章你将左右
SpringBoot项目标搭建,Starter
pom的行使,配置全局文件,核心表明SpringBootApplication 介绍以及单元测试
SpringBootTest注明的选择。SpringData
的入门使用,Repository接口的使用,查询办法重要字的规则定义,@Query,@Modifying
讲明的利用,最终是付出中的提议和遭逢的问题。小说底部提供源码。

POJO层

创办实体类User 表,对应数据库表名是
itdragon_user,id作为自增长的主键,plainPassword是不保留到数据库的精晓密码。

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;

/**
 * 用户实体类
 * @author itdragon
 *
 */
@Table(name="itdragon_user")
@Entity
public class User {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;                        // 自增长主键
    private String account;                 // 登录的账号
    private String userName;                // 注册的昵称
    @Transient
    private String plainPassword;           // 登录时的密码,不持久化到数据库
    private String password;                // 加密后的密码
    private String salt;                    // 用于加密的盐
    private String iphone;                  // 手机号
    private String email;                   // 邮箱
    private String platform;                // 用户来自的平台
    private String createdDate;             // 用户注册时间
    private String updatedDate;             // 用户最后一次登录时间

    // 省略get/set/toString 方法
}

主干评释

终极是SpringBoot
HelloWorld项目标入口类,只需要下边一个java文件,执行main方法,即可实现页面的跳转和数量再次来到的效果。

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@SpringBootApplication
public class SpringbootStudyApplication {

    @RequestMapping("/")
    public String index() {
        return "index";
    }

    @RequestMapping("hello")
    @ResponseBody
    public String helloWorld() {
        return "Hello SpringBoot !";
    }

    public static void main(String[] args) {
        SpringApplication.run(SpringbootStudyApplication.class, args);
    }
}

@SpringBootApplication:是 SpringBoot
的中坚声明,一般用在入口类上。它是一个结缘注脚,其中重点内容有刹那间两个
@SpringBootConfiguration:是一个类级注释,提醒对象是一个bean定义的源,可以领略为xml中的beans,一般和
@Bean 注明一起使用。
@EnableAutoConfiguration:启用 Spring
应用程序上下文的自动配置,试图估摸和安排您可能需要的bean。自动配置类一般使用基于你的
classpath 和曾经定义的 beans 对象进行应用。
@ComponentScan:该阐明会自行扫描指定包下的所有标有
@Component、@Service(Service)、@Repository、@Controller阐明 的类,并登记成bean

SpringData入口类

package com.itdragon;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class StartApplication {

    public static void main(String[] args) {
        SpringApplication.run(StartApplication.class, args);
    }

}

SpringBoot 知识

SpringBoot
是一个用于简化Spring应用搭建开发的框架。开发进程中,大家平时通过安排xml文件来组合第三方技术。而这么些重新整合的办事付出了SpringBoot完成。SpringBoot使用”习惯优于配备”的视角帮大家很快搭建并运行项目。对主流的支付框架能无配置集成。笔者用的开发工具是sts(Spring
Tool
Suite),其操作和eclipse几乎同一。若没有这些工具,创建Maven项目是一样的。

图片 2

Starter pom

先看看Maven项目基本配置文件 pom.xml

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.itdragon</groupId>
    <artifactId>springbootStudy</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>
    <name>springbootStudy</name>
    <description>Demo project for Spring Boot</description>
    <!-- 
        添加 spring boot的父级依赖,它是SpringBoot项目的标志
        spring-boot-starter-parent 它是一个特殊的starter,提供了很多相关的Maven依赖,不用再为version而头疼了,大大简化了开发
    -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.9.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency><!-- 添加web依赖 ,包含spring和springmvc等-->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency><!-- 添加对jpa的支持,包含spring-data和Hibernate -->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency><!-- mysql连接的jar包 -->
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency><!-- 因为SpringBoot内嵌的tomcat不支持jsp页面,同时SpringBoot也不推荐用jsp -->
           <groupId>org.apache.tomcat.embed</groupId>
           <artifactId>tomcat-embed-jasper</artifactId>
           <scope>provided</scope>
        </dependency>
        <dependency><!-- jsp标签库 -->
           <groupId>javax.servlet</groupId>
           <artifactId>jstl</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin><!-- SpringBoot 编译插件 -->
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

密切的同学会发现该文件中冒出大量的 spring-boot-starter-*
的话语。SpringBoot之所以能简化开发的秘闻就在此间—— Starter pom
spring-boot-starter-parent
:父级依赖,SpringBoot项目标标志。里面封装了成百上千jar的本子
spring-boot-starter-web
:对web项目的支撑,其中蕴蓄了SpringMVC和tomcat
spring-boot-starter-data-jpa
:对JPA的帮助,其中蕴含了常用的SpringData和Hibernate,没有Mybatis哦
spring-boot-starter-tomcat :使用tomcat作为Servlet容器
spring-boot-starter-test :对常用测试框架的支撑,如JUnit
还有很多……

品类启动时指示 Unknown character set: ‘utf8mb4’

导致的原故想必是mysql服务器版本安装不科学,解决措施有二种。
首先种:换mysql-connector-java jar包版本为 5.1.6 (不引进);
当前jar版本为 5.1.44。
其次种:重装mysql版本,当前时尚版本是5.7。教程都准备好了。
https://www.cnblogs.com/sshoub/p/4321640.html (mysql安装)
http://blog.csdn.net/y694721975/article/details/52981377 (mysql卸载)

SpringDataJPA 知识

SpringData
是一个用于简化数据库访问,并协助云服务的开源框架。帮忙非关系型数据库(NoSQL)
和 关系型数据库。其关键目标是使数据库的走访变得方便急迅。
SpringData JPA
是由Spring提供的简化JPA开发的框架,致力于裁减数额访问层的开发量。

单元测试

SpringBoot 的单元测试,需要用到 @RunWith 和
@SpringBootTest注脚,代码注释中有详实介绍。

import java.util.List;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.test.context.junit4.SpringRunner;
import com.itdragon.StartApplication;
import com.itdragon.common.ItdragonUtils;
import com.itdragon.pojo.User;
import com.itdragon.repository.UserRepository;
import com.itdragon.service.UserService;

/**
 * @RunWith 它是一个运行器
 * @RunWith(SpringRunner.class) 表示让测试运行于Spring测试环境,不用启动spring容器即可使用Spring环境
 * @SpringBootTest(classes=StartApplication.class)  表示将StartApplication.class纳入到测试环境中,若不加这个则提示bean找不到。
 * 
 * @author itdragon
 *
 */
@RunWith(SpringRunner.class)
@SpringBootTest(classes=StartApplication.class)
public class SpringbootStudyApplicationTests {

    @Autowired
    private UserService userService;
    @Autowired
    private UserRepository userRepository;

    @Test
    public void contextLoads() {
    }

    @Test   // 测试注册,新增数据
    public void registerUser() {
        User user = new User();
        user.setAccount("gitLiu");
        user.setUserName("ITDragonGit");
        user.setEmail("itdragon@git.com");
        user.setIphone("12349857999");
        user.setPlainPassword("adminroot");
        user.setPlatform("github");
        user.setCreatedDate(ItdragonUtils.getCurrentDateTime());
        user.setUpdatedDate(ItdragonUtils.getCurrentDateTime());
        ItdragonUtils.entryptPassword(user);
        userService.registerUser(user);
    }

    @Test   // 测试SpringData 关键字
    public void findByEmailEndingWithAndCreatedDateLessThan() {
        List<User> users = userRepository.findByEmailEndingWithAndCreatedDateLessThan("qq.com", ItdragonUtils.getCurrentDateTime());
        System.out.println(users.toString());
    }

    @Test   // 测试SpringData @Query 注解和传多个参数
    public void getActiveUserCount() {
        long activeUserCount = userRepository.getActiveUserCount("weixin", ItdragonUtils.getCurrentDateTime());
        System.out.println(activeUserCount);
    }

    @Test   // 测试SpringData @Query 注解,传多个参数 和 like 查询
    public void findByEmailAndIhpneLike() {
        List<User> users = userRepository.findByEmailAndIhpneLike("163.com", "6666");
        System.out.println(users.toString());
    }

    @Test   // 测试SpringData @Query 注解 和 @Modifying 注解
    public void updateUserEmail() {
        /**
         * org.springframework.dao.InvalidDataAccessApiUsageException:Executing an update/delete query; nested exception is javax.persistence.TransactionRequiredException: Executing an update/delete query
         * userRepository.updateUserEmail(3L, "update@email.com");
         */
        userService.editUserEmail("update@email.com");
    }

    @Test   // 测试SpringData PagingAndSortingRepository 接口
    public void testPagingAndSortingRepository() {
        int page = 1;   // 从0开始,第二页
        int size = 3;   // 每页三天数据
        PageRequest pageable = new PageRequest(page, size, new Sort(new Order(Direction.ASC, "id")));
        Page<User> users = userRepository.findAll(pageable);
        System.out.println(users.getContent().toString()); // 当前数据库中有5条数据,正常情况可以打印两条数据,id分别为4,5 (先排序,后分页)
    }

    @Test   // 测试SpringData JpaSpecificationExecutor 接口
    public void testJpaSpecificationExecutor(){
        int pageNo = 1;
        int pageSize = 3;
        PageRequest pageable = new PageRequest(pageNo, pageSize);
        Specification<User> specification = new Specification<User>() {
            @Override
            public Predicate toPredicate(Root<User> root,
                    CriteriaQuery<?> query, CriteriaBuilder cb) {
                Predicate predicate = cb.gt(root.get("id"), 1); // 查询id 大于 1的数据
                return predicate;
            }
        };
        Page<User> users = userRepository.findAll(specification, pageable);
        System.out.println(users.getContent().toString());  // 当前数据库中有5条数据,正常情况可以打印一条数据,id为5
    }

}

STS工具 ctrl + shift + o 重新导包快捷键失效

化解措施:preference -> general -> keys ,找到 Organize Imports
,然后 在 When 里面选用 Editing Java Source

网站地图xml地图