使用数据库是开发基本应用的基础. 借助于开发框架, 我们已经不用编写原始的访 问数据库的代码, 也不用调用 JDBC (Java Data Base Connectivity)或者连接池等诸如此 类的被称作底层的代码, 我们将在高级的层次上访问数据库. 而 Spring Boot 更是突破 了以前所有开发框架访问数据库的方法, 在前所未有的更加高级的层次上访问数据库. 因为 Spring Boot 包含一个功能强大的资源库, 为使用 Spring Boot 的开发者提供了更加 简便的接口进行访问.
本章将介绍怎样使用传统的关系型数据库, 以及近期一段时间异军突起的 NoSQL (Not Only SQL)数据库.
本章的实例工程使用了分模块的方式构建, 各模块的定义如表 2-1 所示.
image.PNG
2.1 使用 MySQL
对于传统关系型数据库来说, Spring Boot 使用 JPA ( Java Persistence API)资源库 Ordinary Java Object)提供持久化的标准规范, 即将 Java 的普通对象通过对象关系映射来实现对数据库的操作, 使用 MySQL 也是如此. 简单地说, JPA 就是为 POJO ( Plain(Object-Relational Mapping, ORM)持久化到数据库中.
2.1.1MySQL 依赖配置
为了使用 JPA 和 MySQL, 首先在工程中引入它们的 Maven 依赖, 如代码清单 2-1 所示. 其中, 指定了在运行时调用 MySQL 的依赖.
image.PNG
2.1.2 实体建模
首先创建一些普通对象, 用来与数据库的表建立映射关系, 接着演示如何使用 JPA 对数据库进行增删查改等存取操作.
假如现在有三个实体: 部门, 用户和角色, 并且它们具有一定的关系, 即一个用户 只能隶属于一个部门, 一个用户可以拥有多个角色. 它们的关系模型如图 2-1 所示.
image.PNG
Spring Boot 的实体建模与使用 Spring 框架时的定义方法一样, 同样比较方便的是使用了注解的方式来实现.
部门实体的建模如代码清单 2-2 所示, 其中注解 ©Table 指定关联的数据库的表名, 注解 @Id 定义一条记录的唯一标识, 并结合注解 @GeneratedValue 将其设置为自动 生成. 部门实体只有两个字段: id 和 nameo 程序中省略了 Getter 和 Setter 方法的定义, 这些方法可以使用 IDEA 的自动生成工具很方便地生成.
image.PNG
用户实体包含三个字段: id,name 和 createdate, 用户实体建模如代码清单 2-3 所 示. 其中注解 @ManyToOne 定义它与部门的多对一关系, 并且在数据库表中用字段 did 来表示部门的 ID, 注解 @ManyToMany 定义与角色实体的多对多关系, 并且用中间表 user_role 来存储它们各自的 ID, 以表示它们的对应关系. 日期类型的数据必须使用注 解 @DateTimeFormat 来进行格式化, 以保证它在存取时能提供正确的格式, 避免保存 失败. 注解 @JsonBackReference 用来防止关系对象的递归访问.
image.PNG
角色实体建模比较简单, 只要按设计的要求, 定义 id 和 name 字段即可, 当然同样必须保证 id 的唯一性并将其设定为自动生成. 角色实体的建模如代码清单 2-4 所示.
image.PNG
2.1.3 实体持久化
通过上面三个实体的定义, 实现了使用 Java 的普通对象 (POJO) 与数据库表建立映射关系(ORM), 接下来使用 JPA 来实现持久化. 用户实体使用 JPA 进行持久化的例子如代码清单 2.5 所示. 它是一个接口, 并继承于 JPA 资源库 JpaRepository 接口 , 使用注解 ©Repository 将这个接口也定义为一个资 源库, 使它能被其他程序引用, 并为其他程序提供存取数据库的功能.
使用相同的方法, 可以定义部门实体和角色实体的资源库接口. 接口同样继承于 JpaRepository 接口, 只要注意使用的参数是各自的实体对象即可.
image.PNG
这样就实现存取数据库的功能了. 现在可以对数据库进行增删查改, 进行分页查询 和指定排序的字段等操作.
或许你还有疑问, 我们定义的实体资源库接口并没有声 明一个方法, 也没有对接口有任何实现的代码, 甚至连一条 SQL 查询语句都没有写, 这怎么可能?
是的, 使用 JPA 就是可以这么简单. 我们来看看 JpaRepository 的继承关系, 你也许会明白一些. 如图 2-2 所示, JpaRepository 继承于 PagingAndSortingRepository, 它提供 了 分页和排序功能, PagingAndSortingRepository 继承于 Crud- Repository, 它提供了简单的增删查改功能.
因为定义的接口继承于 JpaRepository, 所以它传递性地继承上面所有这些接口, 并 拥有这些接口的所有方法, 这样就不难理解为何它包含那么多功能了. 这些接口提供的 一些方法如下:
image.PNG
image.PNG
JPA 还提供了一些自定义声明方法的规则, 例如, 在接口中使用关键字 findBy, readBy. getBy 作为方法名的前缀, 拼接实体类中的属性字段(首个字母大写), 并可选 择拼接一些 SQL 查询关键字来组合成一个查询方法. 例如, 对于用户实体, 下列查询 关键字可以这样使用:
image.PNG
又如下列对用户实体类自定义的方法声明, 它们都是符合 JPA 规则的, 这些方法也不用实现, JPA 将会代理实现这些方法.
image.PNG
2.1.4MySQL 测试
现在, 为了验证上面设计的正确性, 我们用一个实例来测试一下.
首先, 增加一个使用 JPA 的配置类, 如代码清单 2.6 所示. 其中 @EnableTransac- tionManagement 启用了 JPA 的事务管理;@EnableJpaRepositories 启用了 JPA 资源库并 指定了上面定义的接口资源库的位置;@EntityScan 指定了定义实体的位置, 它将导入 我们定义的实体. 注意, 在测试时使用的 JPA 配置类可能与这个配置略有不同, 这个配 置的一些配置参数是从配置文件中读取的, 而测试时使用的配置类把一些配置参数都包 含在类定义中了.
image.PNG
其次, 在 MySQL 数据库服务器中创建一个数据库 test, 然后配置一个可以访问这 个数据库的用户及其密码. 数据库的表结构可以不用创建, 在程序运行时将会按照实 体的定义自动创建. 如果还没有创建一个具有完全权限访问数据库 test 的用户, 可以 在连接 MySQL 服务器的查询窗口中执行下面指令, 这个指令假设你将在本地中访问数 据库.
image.PNG
然后, 在 Spring Boot 的配置文件 application.YAML 中使用如代码清单 2-7 所示的配置, 用来设置数据源和 JPA 的工作模式.
image.PNG
配置中将 ddl-atuo 设置为叩 date, 就是使用 Hibernate 来自动更新表结构的, 即如 果数据表不存在则创建, 或者如果修改了表结构, 在程序启动时则执行表结构的同步 更新.
最后, 编写一个测试程序, 如代码清单 2.8 所示. 测试程序首先初始化数据库, 创
建一个部门, 命名为 "开发部", 创建一个角色, 命名为 admin, 创建一个用户, 命名 为 user, 同时将它的所属部门设定为上面创建的部门, 并将现有的所有角色都分配给这 个用户. 然后使用分页的方式查询所有用户的列表, 并从查到的用户列表中, 打印岀用 户的名称, 部门的名称和第一个角色的名称等信息.
image.PNG
好了, 现在可以使用 JUnit 来运行这个测试程序了, 在 IDEA 的 Run/Debug Configuration 配置中增加一个 JUint 配置项, 模块选择 MySQL, 工作目录选择模块所在 的根目录, 程序选择 dbdemo.MySQL.test.MysqlTest, 并将配置项目名称保存为 mysqltest, 如图 2-3 所示.
用 Debug 方式运行测试配置项目 mysqltest, 可以在控制台中看到执行的过程和结 果. 如果状态栏中显示为绿色, 并且提示 "All Tests passed", 则表示测试全部通过. 在控制台中也可以查到下列打印信息:
image.PNG
这时如果在 MySQL 服务器中查看数据库 test, 不但可以看到表结构都已经创建了, 还可以看到上面测试生成的一些数据.
这是不是很激动人心? 在 Spring Boot 使用数据库, 就是可以如此简单和有趣. 到 目前为止, 我们不仅没有写过一条查询语句, 也没有实现一个访问数据库的方法, 但是 已经能对数据库执行所有的操作, 包括一般的增删查改和分页查询.
image.PNG
来源: http://www.jianshu.com/p/ab4d2623db67