搭建SpringCloud微服务框架:六、数据库持久层-SpringDataJPA
搭建微服务框架(数据库持久层-SpringDataJPA)
用惯了Mybatis,这次来换换口味,在SQuid中集成SpringDataJPA。
Github地址:SQuid
介绍
以前都是听说过的是 HibernateJPA
,却从来没有使用过,一直在项目中使用的是 Mybatis
。
SpringDataJPA是基于Hibernate的底层封装的一套ORM框架,使用起来的第一感觉是代码量真的很少,相较传统的Mybatis来说,感觉最起码少了60%,当然大部分都是体现在xml文件上。
介绍真的没有太多词汇可以展示出来,下面来进行使用。👇
使用
在squid项目中,我们新建一个 squid-example-jpa
的项目(由于之前的example目录被删除,可以根据下面的层级目录来进行新建)
引入依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
生成Java实体
如果使用的是IDEA,完全可以参考这篇博客 IDEA下生成SpringDataJPA的Java实体
来生成实体信息。
因为使用了lombok,所以在生成的实体中并没有 getter setter
方法呈现,关于lombok可以了解一下 Lombok
DAO
生成了实体信息后,DAO文件就需要我们自己来手工生成了:
public interface EdocInvoiceRepository extends JpaRepository<EdocInvoice, Long> {
}
一般我们直接继承的是 JpaRepository
,这个是包含所有JPA处理的类,基本上拥有了所有持久层的交互方法。
JPARespository:
public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {
List<T> findAll();
List<T> findAll(Sort var1);
List<T> findAllById(Iterable<ID> var1);
<S extends T> List<S> saveAll(Iterable<S> var1);
void flush();
<S extends T> S saveAndFlush(S var1);
void deleteInBatch(Iterable<T> var1);
void deleteAllInBatch();
T getOne(ID var1);
<S extends T> List<S> findAll(Example<S> var1);
<S extends T> List<S> findAll(Example<S> var1, Sort var2);
}
如果你还有其他需求,比如需要根据某两个字段进行查询等等,SpringDataJPA完全支持:
Keyword | Sample | PQL snippet |
---|---|---|
And | findByLastnameAndFirstname | where x.lastname = ?1 and x.firstname = ?2 |
Or | findByLastnameOrFirstname | where x.lastname = ?1 or x.firstname = ?2 |
Is,Equals | findByFirstname,findByFirstnameIs,findByFirstnameEquals … | where x.firstname = ?1 |
Between | findByStartDateBetween … | where x.startDate between ?1 and ?2 |
LessThan | findByAgeLessThan … | where x.age < ?1 |
LessThanEqual | findByAgeLessThanEqual … | where x.age <= ?1 |
GreaterThan | findByAgeGreaterThan … | where x.age > ?1 |
GreaterThanEqual | findByAgeGreaterThanEqual … | where x.age >= ?1 |
After | findByStartDateAfter … | where x.startDate > ?1 |
Before | findByStartDateBefore … | where x.startDate < ?1 |
IsNull | findByAgeIsNull … | where x.age is null |
IsNotNull,NotNull | findByAge(Is)NotNull … | where x.age not null |
Like | findByFirstnameLike … | where x.firstname like ?1 |
NotLike | findByFirstnameNotLike ... findByFirstnameNotLike | |
StartingWith | findByFirstnameStartingWith … | where x.firstname like ?1 (parameter bound with appended %) |
EndingWith | findByFirstnameEndingWith … | where x.firstname like ?1 (parameter bound with prepended %) |
Containing | findByFirstnameContaining … | where x.firstname like ?1 (parameter bound wrapped in %) |
OrderBy | findByAgeOrderByLastnameDesc … | where x.age = ?1 order by x.lastname desc |
Not | findByLastnameNot … | where x.lastname <> ?1 |
In | findByAgeIn(Collection |
where x.age in ?1 |
NotIn | findByAgeNotIn(Collection |
where x.age not in ?1 |
True | findByActiveTrue() … | where x.active = true |
False | findByActiveFalse() … | where x.active = false |
IgnoreCase | findByFirstnameIgnoreCase … | where UPPER(x.firstame) = UPPER(?1) |
也可以访问SpringDataJPA的官方文档查看:SpringDataJPA
Service & Impl & Controller
service、service.impl,controller,按照常规项目中来编写就行,其中需要注意的是,service如果是要作为对外接口,可以注明 @FeignClient("squid-example-jpa")
,可以参考 sc-server
贴上项目中的例子:
public interface EdocInvoiceService {
List<EdocInvoice> findAll();
EdocInvoice save(EdocInvoice edocInvoice);
}
@Service
public class EdocInvoiceServiceImpl implements EdocInvoiceService {
@Autowired
private EdocInvoiceRepository edocInvoiceRepository;
@Override
public List<EdocInvoice> findAll() {
return edocInvoiceRepository.findAll();
}
@Override
public EdocInvoice save(EdocInvoice edocInvoice) {
return edocInvoiceRepository.save(edocInvoice);
}
}
@RestController
@RequestMapping(value = "/invoice")
public class EdocInvoiceController {
@Autowired
private EdocInvoiceService edocInvoiceService;
@PostMapping(value = "/findAll")
public List<EdocInvoice> findAll() {
return edocInvoiceService.findAll();
}
@PostMapping(value = "/save")
public EdocInvoice save(@RequestBody EdocInvoice edocInvoice) {
return edocInvoiceService.save(edocInvoice);
}
}
application.yaml
spring:
application:
name: squid-miniprogram
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://yanzhenyidai.com:3306/fapiaochi?useUnicode=true&characterEncoding=utf-8
username: root
password: ***
type: com.alibaba.druid.pool.DruidDataSource
jpa:
hibernate:
ddl-auto: update
show-sql: true
server:
port: 9090
jpa.hibernate.ddl-auto
:
key | value |
---|---|
create | 启动时删数据库中的表,然后创建,退出时不删除数据表 |
create-drop | 启动时删数据库中的表,然后创建,退出时删除数据表 如果表不存在报错 |
update | 如果启动时表格式不一致则更新表,原有数据保留 |
validate | 项目启动表结构进行校验 如果不一致则报错 |
一般的 ddl-auto
属性使用 update
就行。
多表查询
复杂业务出现时,可能会使用到多表查询,但是JPA不像Mybatis那么灵活,需要创建中间实体来进行接收,我一般的做法两张表分开查询,然后合并。
总结
SpringDataJPA使用起来的感受就是一个字 “快” ,相较于比较小型的项目,真的推荐使用SpringDataJPA,它能快速的搭建起一个持久层,也不用像Mybatis一样太多的关心底层的xml文件。
参考资料: