前言
Spring Data JPA相信很多JavaEE开发人员都不会陌生,他是Spring Data下的一个模块,主要是基于repositories,实现了JPA规范。这里不讨论SpringData的知识及Spring Data JPA的用法,只对Spring Data JPA与SpringBoot集成做一个简单的demo练习。更多关于SpringData的学习请移步官网:http://projects.spring.io/spring-data/。 接下来我们进行Spring Data JPA与SpringBoot的集成开发。
SpringBoot集成SpringDataJPA
1.跟SpringBoot集成其他Spring Projects类似,只需要在pom.xml中引入相应的依赖即可
org.springframework.boot
spring-boot-starter-data-jpa
2.创建本地数据库并进行项目的基本配置
我使用的是mysql数据库,新建一个数据库,命名为 test
接下来在application.properties中配置数据源和jpa。可通过spring.datasource前缀和spring.jpa前缀查看更多配置信息。
##数据源配置 spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/test spring.datasource.username=root spring.datasource.password=root ##JPA配置 ##通过前缀可以看出,是通过hibernate实现的 ##项目启动对实体映射的表的操作,这里设置每次启动都是重新创建 spring.jpa.hibernate.ddl-auto=create ##是否打印sql信息 spring.jpa.show-sql=true
不要忘了引入mysql驱动的jar包,不然在配置数据源的driver时,会报错:最后新建一个data.sql文件放在我们的src/main/recources目录下,作为我们初始化的数据录入,至于具体为什么要在该目录下创建该名称的文件,后面会有说明。
mysql mysql-connector-java 5.1.34 INSERT INTO PERSON(id,name,age,address) VALUES (11,'张三',21,'LA'); INSERT INTO PERSON(id,name,age,address) VALUES (22,'哈哈',12,'北京'); INSERT INTO PERSON(id,name,age,address) VALUES (33,'爱回家',54,'安徽'); INSERT INTO PERSON(id,name,age,address) VALUES (44,'请问',51,'南京');
3.创建实体类
(@Table,@Id,@GeneratedValue都是jdk的注解,这里的具体实现是由hibernate完成的,这只是Hibernate的基本用法,由实体生成表,也是正向工程的一种体现)
package com.example.demo.bean; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; @Entity public class Person { @Id @GeneratedValue private Long id; private String name; private String address; private Integer age; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Person(){} public Person(Long id, String name, String address, Integer age) { this.id = id; this.name = name; this.address = address; this.age = age; } }
4.编写DAO层接口:PersonDao
package com.example.demo.dao; import com.example.demo.bean.Person; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import org.springframework.transaction.annotation.Transactional; import java.util.List; /** * Created by Joker on 2017/9/4. */ public interface PersonDao extends JpaRepository
{ /** * 根据地址查询人员信息 * @param address 地址 * @return 人员列表,因为一个地方的人可能有多个 */ List findByAddress(String address); /** * 根据地址和姓名查询一个人的信息 * @param address 地址 * @param name 姓名 * @return 返回一个人的信息,这里只是假设一个地方没有同名的人员 */ Person findByAddressAndName(String address, String name); /** * 自定义查询 也是根据地址和姓名查询一个人的信息 不过这里的实现方式是自定义查询 * @param name * @param address * @return */ @Query("select p from Person p where p.name=:name and p.address=:address") Person findByCustomQuery(@Param("name") String name, @Param("address") String address); /** * 根据人员ID修改其住址信息 * @param address 住址 * @param id id * @return update语句影响的行数 */ @Modifying @Query("update Person p set p.address=:address where p.id=:id") @Transactional int updatePersonAddress(@Param("address") String address, @Param("id") Long id); }
5.编写Controller:PersonController
package com.example.demo.controller; import com.example.demo.bean.Person; import com.example.demo.dao.PersonDao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Created by Joker on 2017/9/4. */ @RestController public class PersonController { @Autowired PersonDao personDao; /** * 保存 * @param name * @param address * @param age * @return */ @RequestMapping("/save") public Person save(String name, String address, Integer age) { return personDao.save(new Person(null, name, address, age)); } /** * 根据地址查询 * @param address * @return */ @RequestMapping("/queryByAddress") public List
queryByAddress(String address) { return personDao.findByAddress(address); } /** * 根据地址和名称查询 * @param name * @param address * @return */ @RequestMapping("/queryByNameAndAddress") public Person queryByNameAndAddress(String name, String address) { return personDao.findByAddressAndName(address, name); } /** * 根据地址和名称查询2 * @param name * @param address * @return */ @RequestMapping("/queryByNameAndAddress2") public Person queryByNameAndAddress2(String name, String address) { return personDao.findByCustomQuery(address, name); } /** * 根据personId更新一个人员的地址 * @param address * @param id * @return */ @RequestMapping("/update") public Map updateById(String address, Long id) { int ret = personDao.updatePersonAddress(address, id); Map map = new HashMap (); if (ret > 0) { map.put("success", "update success!"); } else { map.put("error", "update fail!"); } return map; } /** * 排序 * @return */ @RequestMapping("/sort") public List sort() { return personDao.findAll(new Sort(Sort.Direction.ASC, "age")); } /** * 分页 * @param address * @param name * @return */ @RequestMapping("/page") public Page page(String address, String name) { return personDao.findAll(new PageRequest(1, 2)); } }
6.启动项目,查看springboot和springdata给我们做的初始化工作
创建表及初始化表数据
可以看到这里已经重新创建一个person表,注意几点:
1.这是配置了spring.jpa.hibernate.ddl-auto=create所带来的结果;
2.为id设置了@Id注解和@GeneratedValue注解,会自动将这个属性映射为数据表的中的主键,并且根据数据库的特性自动生成主键值。如果给@GeneratedValue注解加上具体的主键生成策略的话,那就只能适应相应的数据库了,否则会报错,生成策略有四种:TABLE,SEQUENCE,IDENTITY,AUTO,属于GenerationType的枚举类型
3.没有设置其他注解的字段,会自动映射为数据库表中的对应名称的字段,驼峰标识的会自动转成下划线拼接。
这里自动的执行了类路径下的data.sql的脚本
数据的初始化如上图所示,自动生成的表和表数据的主键都是正确的。
7.访问url,查看CRUD的结果是否正确
保存:
根据名称查询:
根据名称和地址查询1:
根据名称和地址查询2:
根据id更新地址(测试id=1)
排序(JPA自己的实现)
分页(JPA自己的实现)
8.总结。
1.springboot自动加载类路径下的data.sql文件并且执行
以上摘自springboot官方文档,以下是本人的翻译:
SpringJDBC拥有数据源初始化的特性。SpringBoot默认启用加载了类路径下的schema.sql和data.sql脚本。同时,当数据源的平台改变的时候,SpringBoot也支持加载schema-${platform}.sql和data-{platform}.sql文件(如果存在的话)。比如你可能想设置成为数据库供应商的名称(hssqldb,h2,oracle,mysql,postgresql等)。SpringBoot默认启用SpringJDBC初始化器的fail-fast特性,所以如果执行的脚本发生了异常,那么应用将会启动失败。脚本的位置可以通过spring.datasource.schema和spring.datasource.data设置,但如果设置了spring.datasource.initialize=false的话,这两个设置都不会起作用了。
在本例中,我们的表结构初始化时通过hibernate完成的,所以不需要配置schema.sql文件,但是我们要初始化数据的话,使用了data.sql。如果有多个表结构的话,要做初始化肯定不能再一张表里面,所以可以通过配置spring.datasource.data=classpath:data*.sql来配置,也可以设置其他路径。具体的扫描并执行文件的代码可以参考控制台日志中的类信息在查找相关的源码。
2.dao层没有加任何spring的注解(PersonDao),但是也能被spring扫描到,而且也可以正确的被注入到controller里面去。这是因为JpaRepository注解最上层继承自Repository注解,这是一个标记接口,所有实现该接口的类都会被IOC容器识别并且管理。
3.以上包括之前的几篇有关springboot的博客仅为入门案例,关于springboot其实并没有很多新知识,都是一些跟其他spring框架的结合使用,而且这种集成基本上是无需开发者担心的,因为自动配置能帮我们解决大多数的配置问题,像spring batch,spring security等一些常用的,springboot都提供了自动配置,后面不多赘述。更多文档请参考spring官网或者其他资料,这里附上我学习的参考书籍。
4:附件:javaEE的颠覆者-Spring Boot实战:百度云下载链接:http://pan.baidu.com/s/1hrDhFTE 密码:fi7h