SpringDataJPA入门

1. 项目构建

  1. 【Filt】->【new】 -> 【project】 -> 选择Spring Initializr -> 【next】,填写Group,Artifact,Type ->【next】

  2. 选择依赖包

    • 左边选择Core,右边勾选Lombok
    • 左边选择Web,右边勾选Web
    • 左边选择SQL,右边勾选JPAMySQL

    【next】->【finish】

2.配置文件

在配置文件resource.application.xml前,需要创建以下配置类

package com.example.springdatajpa.config;
public class MyDatabaseConfig extends MySQL5InnoDBDialect {
    @Override
    public String getTableTypeString() {
        // 设置创建表的存储引擎为 InnoDB,字符编码为 utf-8
        return " ENGINE=InnoDB DEFAULT CHARSET=utf8";
    }
}

resource.application.yml文件中添加如下配置

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/springdatajpa?useSSL=FALSE&serverTimezone=UTC
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver
  jpa:
    show-sql: true          # 打印sql语句
    hibernate:
      ddl-auto: update
    # 设置jsp存储引擎,使用上面的配置类
    database-platform: com.example.springdatajpa.config.MyDatabaseConfig

spring data jpa的配置说明:

  1. spring.jpa.show-sql:是否在日志打印sql语句

    同样的,可以在logback-spring.xml中配置如下可以打印sqlsql参数

     <!--开发环境:打印控制台-->
        <springProfile name="dev">
            <!-- 打印sql -->
            <logger name="org.hibernate.SQL" level="DEBUG"/>
            <!-- 打印sql的参数 -->
            <logger name="org.hibernate.type.descriptor.sql.BasicBinder" level="TRACE"/>
            <root level="info">
                <appender-ref ref="CONSOLE"/>
            </root>
        </springProfile>
    
  1. spring.jpa.hibernate.ddl-auto:是hibernate的配置属性,其主要作用是:自动创建、更新、验证数据库表结构。

    该参数的几种配置如下:

    • create:每次加载都会删除上一次的生成的表,然后根据model类再重新来生成新表,会导致数据库表数据丢失。
    • create-drop:每次加载时,根据model类生成表,但是sessionFactory一关闭,表就自动删除。
    • update:最常用的属性,第一次加载时根据model类会创建表的结构(前提是先建立好数据库),以后加载时根据model类自动更新表结构,即使表结构改变了但表中的行仍然存在不会删除以前的行。要注意的是当部署到服务器后,表结构是不会被马上建立起来的,是要等应用第一次运行起来后才创建。
    • validate:每次加载时,验证创建数据库表结构,只会和数据库中的表进行比较,不会创建新表,但是会插入新值。
  2. spring.jpa.database-platform:SpringBoot 2.0版本中创建数据表的时候,默认存储引擎是 MyISAM 。这个参数值org.hibernate.dialect.MySQL5InnoDBDialect是在建表的时候,将默认的存储引擎切换为 InnoDB,但默认的字符编码为latin1,所以一般都是自定义配置类继承MySQL5InnoDBDialect来指定字符编码,或者手动创建表指定字符编码,或者创建表后,修改表字符编码。

3.建立数据实体类

数据库实体类是一个 POJO Bean 对象。这里我们先建立一个 UserDO 的数据库实体。数据库实体的源码如下

package com.example.springdatajpa.entity;
@Entity
@Table(name = "User")   // 指定表名,不指定使用实体类名称
@Getter
@Setter
@JsonIgnoreProperties(ignoreUnknown = true, value = {"hibernateLazyInitializer", "handler", "fieldHandler"})
public class UserDO {
    @Id     // 主键id
    @GeneratedValue(strategy = GenerationType) // 主键生成策略
    @Column(name = "id")
    private Long id;

    @Column(name = "username", length = 50) // 表列的字段名,长度50
    private String username;

    @Column(name = "age", length = 3)   // 表列的字段名,长度3
    private Integer age;
}

注意点:

  • @JsonIgnoreProperties:忽略Hibernate的延迟加载的一些属性"hibernateLazyInitializer", "handler", "fieldHandler",这些属性在实体类里没有所以要忽略掉,否则转换为Json会报错。

  • @GeneratedValue:设置主键id的生成策略。Jpa支持4种生成策略:

    • TABLE:使用一个特定的数据库表格来保存主键
    • SEQUENCE:根据底层数据库的序列来生成主键,需要数据库支持序列。
    • IDENTITY:主键由数据库自动生成(主要是自动增长型)
    • AUTO:主键由程序控制(JPA默认)

    四种数据库支持情况:

    数据库名称 支持的id策略
    mysql GenerationType.TABLE GenerationType.AUTO GenerationType.IDENTITY 不支持GenerationType.SEQUENCE
    oracle GenerationType.AUTO GenerationType.SEQUENCE GenerationType.TABLE 不支持GenerationType.IDENTITY
    postgreSQL GenerationType.TABLE GenerationType.AUTO GenerationType.IDENTITY GenerationType.SEQUENCE 都支持
    kingbase GenerationType.TABLE GenerationType.SEQUENCE GenerationType.IDENTITY GenerationType.AUTO 都支持

    上面的生成策略都是自增id,移植和在分布式下都不方便,JPA可以使用UUID生成策略:

    @Id
    @GenericGenerator(name = "system-uuid", strategy = "uuid")
    @GeneratedValue(generator = "system-uuid")
    @Column(name = "id")
    private String id;    // uuid必须为String类型
    

4.实现持久层服务

JPA中,实现持久层服务很简单。只需要新建接口继承org.springframework.data.jpa.repository.JpaRepository<T, ID>类即可,其中T是数据库实体类,ID是数据库实体类的主键类型

package com.example.springdatajpa.repository;
/**
 * 符合SpringDataJpa的Dao层接口规范
 *      JpaRepository<操作的实体类类型,实体类中主键属性的类型>
 *          * 封装了基本curd操作
 *      JpaSpecificationExecutor<操作的实体类类型>
 *          * 封装了复杂查询(如分页等)
 */
@Repository
public interface UserRepository extends JpaRepository<UserDO, Long>, JpaSpecificationExecutor<UserDO> {
    // 如果需要自定义方法查询,可以添加
    User findByUsername(String username);
}

一行代码也不用写。UserDO 这个实体类,拥有父类的如下功能:

Snipaste_2019-04-07_14-39-09.png

5.创建Service服务

  1. UserService接口

    package com.example.springdatajpa.service;
    public interface UserService {
        UserDO saveUser(UserDO userDO);
        UserDO findById(long id);
    }
    
  2. UserService接口的实现类UserServiceImpl

    package com.example.springdatajpa.service.impl;
    @Service
    public class UserServiceImpl implements UserService {
        @Autowired
        private UserRepository userRepository;
    
         /**
         * save: 保存或更新
         *          根据传递的对象是否存在主键id,
         *          如果没有id主键属性,则保存
         *          存在id主键属性,根据id查询数据,再更新数据
         */
        @Override
        public UserDO saveUser(UserDO userDO) {
            UserDO save = userRepository.save(userDO);
            return save;
        }
    
        @Override
        public UserDO findById(long id) {
            UserDO byId = userRepository.findById(id).get();
            return byId;
        }
    }
    

6.controller

package com.example.springdatajpa.controller;
@RestController
public class UserController {
    @Autowired
    private UserService userService;

    @PostMapping("/add-user")
    public UserDO addPerson(@RequestBody UserDO user){
        return userService.saveUser(user);
    }

    @GetMapping("/get-user")
    public UserDO getPerson(@RequestParam Long id){
        return userService.findById(id);
    }
}

启动程序,如果数据库中的表不存在时,会自动创建表,在Postman中执行

  • 添加用户
Snipaste_2019-04-07_15-04-32.png
  • 通过id获取用户
Snipaste_2019-04-07_15-06-31.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 193,812评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,626评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,144评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,052评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,925评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,035评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,461评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,150评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,413评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,501评论 2 307
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,277评论 1 325
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,159评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,528评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,868评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,143评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,407评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,615评论 2 335

推荐阅读更多精彩内容