JPA
Spring Data Jpa 介绍
Spring Data JPA是Spring基于Hibernate开发的一个JPA框架。如果用过Hibernate或者MyBatis的话,就会知道对象关系映射(ORM)框架有多么方便。但是Spring Data JPA框架功能更进一步,为我们做了 一个数据持久层框架几乎能做的任何事情。并且提供了基础的增删查方法,具体api请看官网https://docs.spring.io/spring-data/data-jpa/docs/current/reference/html/。
简而言之:它提供了默认的简单的单表增删查方法,直接可以使用不用具体关心怎么去写sql语句的问题,但是这里修改的功能是默认没有提供的,需要自己手写实现。
实践
pom
<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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
</dependencies>
注意:mysql新驱动类名路径和旧版本的区别
建库建表
由于我们使用的spring data jpa 而jpa的底层实现是hibernate,用过hibernate的同学知道 hibernate可以通过实体类逆向创建表,只需要配置一下ddl-auto 就可以
所以我们需要在application.yml配置一下
server:
port: 8989
pring:
datasource:
username: root
password: root
url: jdbc:mysql://127.0.0.1:3306/device?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
hibernate:
ddl-auto: update
show-sql: true
#日志文件地址
logging:
path: /opt/log/
file: springbootdemo.log
level:
root: INFO
在上面的配置文件中 我们配置了一个数据源跟tomcat端口还有jpa的配置。其中 show-sql: true 代表会在日志中打印我们操作的sql、
而另外 ddl-auto有四个值可选,分别是
- create 启动时删数据库中的表,然后创建,退出时不删除数据表
- create-drop 启动时删数据库中的表,然后创建,退出时删除数据表 如果表不存在报错
- update 最常用的属性,第一次加载hibernate时根据model类会自动建立起表的结构(前提是先建立好数据库),以后加载hibernate时根据 model类自动更新表结构,即使表结构改变了但表中的行仍然存在不会删除以前的行。要注意的是当部署到服务器后,表结构是不会被马上建立起来的,是要等 应用第一次运行起来后才会。
- validate 项目启动表结构进行校验 如果不一致则报错
但是数据库还是需要我们创建的,这里的test数据库需要你自行创建
类、映射、DAO
类和表映射
/**
* 设备实体类和表的映射
*/
@JsonIgnoreProperties(value={"hibernateLazyInitializer","handler","fieldHandler"})
@Entity
public class Device implements Serializable {
private static final long serialVersionUID = -1L;
@Id
@GeneratedValue
private Long id;
@Column(name = "request", nullable = true, length = 12)
private String request;//register
@Column(name = "uuid", nullable = true, length = 32)
private String uuid;//cd33-977e-c809-e03a
@Column(name = "brand", nullable = true, length = 15)
private String brand;//jsrz
@Column(name = "app", nullable = true, length = 12)
private String app;//icast
@Column(name = "model", nullable = true, length = 12)
private String model;//t9wan
@Column(name = "version", nullable = true, length = 12)
private String version;//5.1.1
// setting和getting省略
}
dao操作
DAO操作才是使用过程的核心,这也是它和mybatis不同的地方最大的区别,这里简单的操作基本JpaRepository已经实现了,只有一些特殊的操作需要我们手动创建。
/**
* @program: springboot-demo
* @description: dao操作
* @author: Bamboo zjcjava@163.com
* @create: 2019-09-07 13:33
**/
public interface DeviceRepository extends JpaRepository<Device, Long> {
/**
* 根据uuid,它会自动根据find后面的属性名称作为表中对应的字段进行查询
* 因它的方法名命名规则就是find属性名,当然还有一些默认的是它已经实现的:findAll,findOne等
* @param uuid
* @return
*/
Device findByUuid(String uuid);
/**
*复杂JPA操作 使用@Query()自定义sql语句 根据业务id UId去更新整个实体
* 删除和更新操作,需要@Modifying和@Transactional注解的支持
* 更新操作中 如果某个字段为null则不更新,否则更新【注意符号和空格位置】
*
*修改设备信息拼接sql如果不为空则修改原有数据
* @param model 传入实体,分别取实体字段进行set
* @return 更新操作返回sql作用条数
*/
@Modifying
@Transactional
@Query("update Device ex set " +
"ex.app = CASE WHEN :#{#model.app} IS NULL THEN ex.app ELSE :#{#model.app} END ," +
"ex.brand = CASE WHEN :#{#model.brand} IS NULL THEN ex.brand ELSE :#{#model.brand} END ," +
"ex.model = CASE WHEN :#{#model.model} IS NULL THEN ex.model ELSE :#{#model.model} END ," +
"ex.request = CASE WHEN :#{#model.request} IS NULL THEN ex.request ELSE :#{#model.request} END ," +
"ex.version = CASE WHEN :#{#model.version} IS NULL THEN ex.version ELSE :#{#model.version} END " +
"where ex.uuid = :#{#model.uuid}")
int updateByuuid(@Param("model") Device model);
}
updateByuuid:方法名命名规则必须操作+扩展
传入的值需要占位符#{#model.request} 形参model和属性组成
业务逻辑层
业务逻辑层的使用和mybatis使用是相同的,直接注入使用相关dao方法即可
service
/**
* 客户端接口
*/
public interface BambooDubboService {
/**
* 客户端接口
* @param uuid
*/
Device sayBamboo(String uuid);
void saveDevice(Device device);
}
ServiceImpl
@Service
public class BambooDubboServiceImpl implements BambooDubboService {
@Autowired
private DeviceRepository deviceRepository;
@Override
public Device sayBamboo(String uuid) {
return deviceRepository.findByUuid(uuid);
}
// 如果不存在该uuid的数据则插入新值
@Override
public void saveDevice(Device device) {
Device deviceTmp = deviceRepository.findByUuid(device.getUuid());
if(Objects.nonNull(deviceTmp)){
deviceRepository.updateByuuid(device);
}else {
deviceRepository.save(device);
}
}
}
controller
MVC
import java.util.Objects;
/**
* demo url
* http://localhost:8080
*
* @author bamboo
* @time 2019-6-27
*/
@RestController
@RequestMapping("/devmgr")
public class BambooController {
private Log logger = LogFactory.getLog(BambooController.class);
@Autowired
BambooDubboService bambooDubboService;
/**
* 查询操作
*/
@GetMapping("/uuid")
public Object find(Model model, String uuid) {
if(Objects.isNull(uuid)){
return "error:null param";
}
return bambooDubboService.sayBamboo(uuid);
}
/**
* 新增和修改操作
*/
@GetMapping("")
public Object get(Model model, Device device) {
if(Objects.isNull(device)){
return "error:null param";
}
bambooDubboService.saveDevice(device);
return "success";
}
}
启动服务即可发现,数据库中它会自动创建两个表。
devic:业务表
hibernate_sequence:自增ID的序列表
通过下面接口我们可以看到已经有数据插入进去了
http://localhost:8080/devmgr?request=register\&uuid=cd33-977e-c809-e03d\&brand=APP\&app=icast\&model=t9wan\&version=5.1.5
源码
请访问我的github
https://github.com/BambooZhang/springboot-study