SpringBoot学习之旅(六)---JPA基础篇

什么是JPA

JPA是Java Persistence API的简称,中文名Java持久层API,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。JPA并不是ORM框架,它只是一个规范,制定了一套ORM的标准。

源码下载

点击开源中国下载源码

由于代码内容比较多多,建议优先下载代码,对着代码读更加快捷

其他文章

SpringBoot学习之旅(七)—JPA进阶篇之自定义查询、修改、分页
SpringBoot学习之旅(八)—JPA进阶篇之联表操作

基础工作
基础项目创建
  • 创建
    File–>new–>project–>Spring Initializr–>next
  • 默认配置
    查看pom.xml,会看见以下默认加入的配置
            <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>
                <scope>runtime</scope>
            </dependency>
    
  • 添加其他相关引入
    在pom.xml下添加一下配置文件
            <!--用于对象自动生成get set方法的插件-->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.18.6</version>
            </dependency>
        	<!--使用阿里巴巴的druid的mysql连接池-->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid-spring-boot-starter</artifactId>
                <version>1.1.10</version>
            </dependency>
            <!--json工具类-->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.2.47</version>
            </dependency>    
    
  • 创建测试库

    创建脚本
    DROP TABLE IF EXISTS `user_info`;
    CREATE TABLE `user_info` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `name` varchar(50) NOT NULL DEFAULT '' COMMENT '用户名(昵称)',
      `sex` tinyint(4) NOT NULL DEFAULT '2' COMMENT '性别  0:女 1:男 2:未知',
      `age` int(11) NOT NULL DEFAULT '0',
      `telphone` varchar(15) DEFAULT NULL COMMENT '手机号码(唯一键),null数据是不受唯一键约束的,防止用户是使用三方登录的',
      `email` varchar(20) NOT NULL DEFAULT '' COMMENT '用户的邮箱',
      `register_mode` varchar(20) NOT NULL DEFAULT '' COMMENT '注册方式:手机号、微信注册、支付宝',
      `third_party_id` varchar(64) NOT NULL DEFAULT '' COMMENT '第三方的id',
      `avatar` varchar(50) NOT NULL DEFAULT '' COMMENT '用户头像',
      PRIMARY KEY (`id`),
      UNIQUE KEY `电话号码唯一` (`telphone`) USING HASH
    ) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8;
    
  • 配置application.yml
    #当前服务的端口
    server:
      port: 9004
    
    spring:
      application:
        #当前服务的名称
        name: spring-boot-jpa
      #数据库连接相关配置
      datasource:
        url: jdbc:mysql://192.168.1.208:3307/jpa_db?useSSL=false&serverTimezone=UTC
        username: root
        password: 123456
        #阿里巴巴的druid的mysql连接池
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.jdbc.Driver
    
使用IDEA工具生成数据库实体对象
  • 配置Mysql的连接
    在这里插入图片描述

  • 数据库测试
    配置完之后,可以直接通过IDEA对数据库进行基础的操作

  • 添加自动生成工具
    file–>project Structure

  • 生成数据库关联实体

    • 创建数据库实体文件夹

    • 生成映射对象


JAP常用注解说明
  • @Entity
    标识当前对象为一个实体类,映射到数据库的一张表,
    该注解使用在类上

  • @Table
    如:@Table(name = “user_info”)
    用于指明当前类映射到数据库的表名user_info;如对象为:UserInfo,表明为:user_info,该注解可以不用加,默认可以识别
    该注解使用在类上
    属性列表

    属性名属性说明默认值示例
    name当前类映射到数据库的表名“”@Table(name = “user_info”)
    catalog所属的数据库目录“”
    schema库名“”@Table(name = “user_info”, schema = “jpa_db”)
    uniqueConstraints唯一键或者联合唯一建[]@Table(name = “user_info”, schema = “jpa_db”, catalog = “”,uniqueConstraints = {@UniqueConstraint(columnNames={“a”,“b”}),@UniqueConstraint(columnNames={“c”,“d”})})
    Index索引列表[]@Table(name = “user_info”, indexes = {@Index(columnList = “telphone”)})
  • @Id
    用于表明对应的字段为主键ID

  • @GeneratedValue
    逐渐生成策略,默认自动增长:@GeneratedValue(strategy=GenerationType.AUTO)

    策略说明
    GenerationType.AUTOJPA自动选择合适的策略,是默认选项
    GenerationType.IDENTITY采用数据库 ID自增长的方式来自增主键字段,Oracle 不支持这种方式
    GenerationType.SEQUENCE通过序列产生主键,通过 @SequenceGenerator 注解指定序列名,MySql 不支持这种方式
    GenerationType.TABLE通过表产生主键,框架借由表模拟序列产生主键,使用该策略可以使应用更易于数据库移植。
  • @Basic
    表示一个简单的属性到数据库表的字段的映射
    fetch: 表示该属性的读取策略,有 EAGER 和 LAZY 两种,分别表示主支抓取和延迟加载,默认为 EAGER.
    optional:表示该属性是否允许为null, 默认为true

  • @Column
    用于指明当前字段与数据库列的映射关系如:@Column(name = “name”) 表示当前字段映射到数据库的name列
    属性说明:

    属性名含义默认值
    name当前字段与数据库列的映射关系“”
    unique是否唯一false
    nullable是否允许为null true
    insertable在使用“INSERT”脚本插入数据时,是否需要插入该字段的值true
    updatable在使用“UPDATE”脚本插入数据时,是否需要更新该字段的值。insertable和updatable属性一般多用于只读的属性,例如主键和外键等。这些字段的值通常是自动生成的true
    columnDefinition创建表时,该字段创建的SQL语句,一般用于通过Entity生成表定义时使用“”
    table当映射多个表时,指定表的表中的字段“”
    length字段的长度,当字段的类型为varchar时,该属性才有效255
    precision表示精度,当字段类型为double时,precision表示数值的总长度0
    scale表示精度,当字段类型为double时,scale表示小数点所占的位数0
  • @Transient
    字段什么注解都没有的时候默认会有@Basic注解,如果一个字段不需要和数据库的列做关联,则添加@Transient注解

  • @Temporal
    时间精度
    数据库中对时间的精度分别有:DATE, TIME, 和 TIMESTAMP 三种精度(即单纯的日期,时间,或者两者 兼备);而java中并没有涉及到时间的进度问题,因此可以通过该注解进行标明
    TemporalType的类型

    类型说明
    TemporalType.DATEyyyy-HH-dd
    TemporalType.TIMEhh:mm:ss
    TemporalType.TIMESTAMPyyyy-HH-dd hh:mm:ss
  • 使用lombok,简化对象
    lombok可以自动生成get set方法;同时我们使用规范的驼峰命名及数据库名创建,对象及列的映射根据默认规则关联即可,因此使用起默认的注解即可;让数据库对象能够更加清晰简洁

    package com.lupf.springbootjpa.dbobject;
    
    import lombok.Data;
    
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    
    //lombok数据对象注解
    @Data
    @Entity
    public class UserInfo {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Integer id;
        private String name;
        private Byte sex;
        private Integer age;
        private String telphone;
        private String email;
        private String registerMode;
        private String thirdPartyId;
        private String avatar;
    }
    
Repository创建
  • 创建UserRepository继承JpaRepository
    JpaRepository两个泛型值分别问数据库关联对象及主键类型
    import com.lupf.springbootjpa.dbobject.UserInfo;
    import org.springframework.data.jpa.repository.JpaRepository;
    import org.springframework.stereotype.Repository;
    
    @Repository
    public interface UserRepository extends JpaRepository<UserInfo,Integer> {
    }
    
  • 查看UserRepository 继承关系图

    这样使得UserRepository 能使用到父类的各种基础的数据库操作方法
  • 默认方法的列表
    以下为Repository默认的一些方法,根据方法名和字面意思,基本就可以判断他的功效
Service相关定义
领域模型创建
  • 创建管理数据模型的领域模型
    package com.lupf.springbootjpa.service.model;
    
    import lombok.Data;
    
    /**
     * 用户的领域模型对象
     */
    @Data
    public class UserInfoModel {
        private Integer id;
        private String name;
        private Byte sex;
        private Integer age;
        private String telphone;
        private String email;
        private String avatar;
    }
    
定义UserService
  • 定义用户的基础操作
    package com.lupf.springbootjpa.service;
    
    import com.lupf.springbootjpa.service.model.UserInfoModel;
    import org.springframework.data.domain.Page;
    import org.springframework.data.domain.Pageable;
    import org.springframework.data.domain.Sort;
    
    import java.util.List;
    
    /**
     * 用户数据操作的接口
     */
    public interface UserService {
        //添加
        UserInfoModel save(UserInfoModel userInfoModel);
    
        //查询所有
        List<UserInfoModel> getAll();
    
        //根据id查询
        UserInfoModel getUserById(Integer id);
    
        //分页查询
        Page<UserInfoModel> getPageInfo(Pageable pageable);
    
        //排序
        List<UserInfoModel> getUserInfoBySort(Sort sort);
    }
    
接口实现
  • 基础操作的实现
    package com.lupf.springbootjpa.service.impl;
    
    import com.lupf.springbootjpa.dbobject.UserInfo;
    import com.lupf.springbootjpa.repository.UserRepository;
    import com.lupf.springbootjpa.service.UserService;
    import com.lupf.springbootjpa.service.model.UserInfoModel;
    import org.springframework.beans.BeanUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.domain.Page;
    import org.springframework.data.domain.PageImpl;
    import org.springframework.data.domain.Pageable;
    import org.springframework.data.domain.Sort;
    import org.springframework.stereotype.Service;
    
    import java.util.List;
    import java.util.Optional;
    import java.util.stream.Collectors;
    
    @Service
    public class UserServiceImpl implements UserService {
        @Autowired
        UserRepository userRepository;
    
        @Override
        public UserInfoModel save(UserInfoModel userInfoModel) {
            UserInfo userInfo = model2dbo(userInfoModel);
            if (null != userInfo) {
                userInfo.setRegisterMode("byManager");
                userInfo.setThirdPartyId("123456");
                UserInfo saveUserInfo = userRepository.save(userInfo);
                return dbo2model(saveUserInfo);
            }
            return null;
        }
    
        @Override
        public List<UserInfoModel> getAll() {
            List<UserInfo> userInfos = userRepository.findAll();
            if (null != userInfos && userInfos.size() > 0) {
                List<UserInfoModel> userInfoModels = userInfos.stream().map(userInfo -> dbo2model(userInfo)).collect(Collectors.toList());
                return userInfoModels;
            }
            return null;
        }
    
        @Override
        public UserInfoModel getUserById(Integer id) {
            Optional<UserInfo> userInfoOptional = userRepository.findById(id);
            if (null != userInfoOptional && userInfoOptional.isPresent()) {
                return dbo2model(userInfoOptional.get());
            }
            return null;
        }
    
        @Override
        public Page<UserInfoModel> getPageInfo(Pageable pageable) {
            Page<UserInfo> userInfoPage = userRepository.findAll(pageable);
            if (null != userInfoPage) {
                return pagedbo2model(userInfoPage);
            }
            return null;
        }
    
        @Override
        public List<UserInfoModel> getUserInfoBySort(Sort sort) {
            List<UserInfo> userInfos = userRepository.findAll(sort);
            if (userInfos.size() > 0) {
                List<UserInfoModel> userInfoModels = userInfos.stream().map(userInfo -> dbo2model(userInfo)).collect(Collectors.toList());
                return userInfoModels;
            }
            return null;
        }
    
        //将领域模型对象转换为数据库模型对象
        private UserInfo model2dbo(UserInfoModel userInfoModel) {
            if (null == userInfoModel) {
                return null;
            }
    
            UserInfo userInfo = new UserInfo();
            BeanUtils.copyProperties(userInfoModel, userInfo);
            return userInfo;
        }
    
        //将数据库对象转换为领域模型对象
        private UserInfoModel dbo2model(UserInfo userInfo) {
            if (null == userInfo) {
                return null;
            }
            UserInfoModel userInfoModel = new UserInfoModel();
            BeanUtils.copyProperties(userInfo, userInfoModel);
            return userInfoModel;
        }
    
        //将从数据库中获取page对象 转换成领域page对象
        private PageImpl<UserInfoModel> pagedbo2model(Page<UserInfo> userInfoPage) {
            if (null == userInfoPage)
                return null;
            long t = userInfoPage.getTotalElements();
            List<UserInfo> userInfos = userInfoPage.getContent();
            List<UserInfoModel> userInfoModels = userInfos.stream().map(userInfo -> dbo2model(userInfo)).collect(Collectors.toList());
            PageImpl<UserInfoModel> userInfoModelPage = new PageImpl<>(userInfoModels, userInfoPage.getPageable(), t);
            return userInfoModelPage;
        }
    }
    
    
编写测试用例
  • 快速创建方式
  • 编写测试用例
    package com.lupf.springbootjpa.service.impl;
    
    import com.alibaba.fastjson.JSON;
    import com.lupf.springbootjpa.service.UserService;
    import com.lupf.springbootjpa.service.model.UserInfoModel;
    import lombok.extern.slf4j.Slf4j;
    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.test.context.junit4.SpringRunner;
    
    import java.util.List;
    
    @RunWith(SpringRunner.class)
    @SpringBootTest
    @Slf4j
    public class UserServiceImplTest {
    
        @Autowired
        UserService userService;
    
        //测试添加
        @Test
        public void save() {
            for (int i = 0; i < 20; i++) {
                UserInfoModel userInfoModel = new UserInfoModel();
                userInfoModel.setAge(i);
                userInfoModel.setAvatar("https://aaa.com/a.png");
                userInfoModel.setEmail("a@qq.com");
                userInfoModel.setName("测试添加" + i);
                userInfoModel.setSex(new Byte("1"));
                userInfoModel.setTelphone("13612345678" + i);
                UserInfoModel dbUserInfoModel = userService.save(userInfoModel);
                log.info(JSON.toJSONString(dbUserInfoModel));
            }
        }
    
        //查询所有
        @Test
        public void getAll() {
            List<UserInfoModel> userInfoModels = userService.getAll();
            log.info(JSON.toJSONString(userInfoModels));
        }
    
        //根据ID查询
        @Test
        public void getUserById() {
            UserInfoModel userInfoModel = userService.getUserById(19);
            log.info(JSON.toJSONString(userInfoModel));
        }
    
        //分页查询
        @Test
        public void getPageInfo() {
            //这里的page是页码-1 比如第一页,就是1-1=0  第二页就是2-1=1
            //size是表示单页显示的行数
            PageRequest pageRequest = new PageRequest(0, 3);
            Page<UserInfoModel> userInfoModelPage = userService.getPageInfo(pageRequest);
            log.info(JSON.toJSONString(userInfoModelPage));
        }
    
        //降序查询
        @Test
        public void getUserInfoBySort() {
            Sort sort = new Sort(Sort.Direction.ASC, "age");
            List<UserInfoModel> userInfoModels = userService.getUserInfoBySort(sort);
            log.info(JSON.toJSONString(userInfoModels));
        }
    }
    
基础操作测试
  • 测试添加

  • 测试查询所有

  • 根据ID查询

  • 分页查询
    在这里插入图片描述

  • 升降序查询

Controller定义

略!

本篇的核心是Jpa操作数据库,因此这里就不啰嗦了…

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一行Java

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值