Spring Data JPA 和 H2数据库
Introduction
H2是一个轻量级数据库,有以下特点:
- 纯Java编写
- 没有任何依赖,只有一个jar包且不到2M
- 提供了一个web控制台
- 支持内存模式、内嵌模式、服务器模式和集群
- 支持事务
- 支持主键和索引
麻雀虽小,五脏俱全,在本地开发中如果不想费劲去安装一个MySQL,或在小型应用中需要一个内存数据库,H2都是不错的选择。
官网:http://www.h2database.com/html/main.html
下面就结合H2写一个Spring JPA的入门教程,如果要换成MySQL或其他数据库,差别也不大。
Get Started
引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>配置H2数据库
# 开启H2控制台
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
# 配置数据源,使用H2数据源
spring.datasource.name=your-datasource-name
spring.datasource.driver-class-name=org.h2.Driver
# H2数据库默认的账号密码
spring.datasource.username=sa
spring.datasource.password=
# url
spring.datasource.url=jdbc:h2:~/Documents/db/demo
# 开启ddl自动更新,应用启动时框架会根据实体类自动更新表结构
# 建议生产环境关闭此项配置,使用手动方式维护ddl
spring.jpa.hibernate.ddl-auto=update
# 开启sql日志,方便调试
spring.jpa.show-sql=trueH2数据库支持多种运行模式,由spring.datasource.url参数决定。
创建实体类
@Entity
@Table(name = "t_example")
@Data
public class ExampleEntity {
@Id
@GeneratedValue
private Long id;
private String message;
/**
* 字段在Java中是小驼峰方式命名,但是在建表时会自动转为使用下划线"_"分隔
*/
private LocalDateTime createTime;
}创建Repository
@Repository
public interface ExampleRepository extends JpaRepository<ExampleEntity, Long> {
}- 加
@Repository注解是为了在IDEA里面使用@Autowired装配repository bean时不报错 - 必须实现JpaRepository<Entity,ID>接口
测试
编写一个Unit Test:
@SpringBootTest
public class ExampleTest {
@Autowired
private ExampleRepository exampleRepository;
@Test
public void addExample() {
ExampleEntity entity = new ExampleEntity();
entity.setMessage("test add an example");
entity.setCreateTime(LocalDateTime.now());
exampleRepository.save(entity);
}
}执行后通过控制台查看结果:
Spring Data JPA的查询语法
你会发现在上述demo中没有写任何sql语句或使用自动化工具生成dao代码,这就是Spring Data JPA的神奇之处。
其实是父接口JpaRepository<T,ID>已经实现了默认的CRUD和分页查询功能,例如save()、getOne(ID id)、findAll()、count()等一系列见名知意的方法,这些都是开箱即用的!
那么如果想要根据其他条件查询信息呢?
根据条件定义查询方法
还是上述例子,要实现根据message字段来查询t_example表,只需要在Repository中增加一个方法:
@Repository
public interface ExampleRepository extends JpaRepository<ExampleEntity, Long> {
List<ExampleEntity> findByMessage(String message);
}Spring Data会自动根据方法签名来推测查询语句,例如上面的代码就会被翻译成:select * from t_example where message='<message>';
方法的命名遵循以下模式:readSomeThingByColumnNameEqualsOrderByColumnName。其中:
- read是动词,表示查询,也可以使用get、find、count等
- read后面紧跟的是主题,也就是EntityName,通常可以省略
- By后面跟着的是条件,还可以指定比较操作符,默认是Equals,还可以是In/NotIn/Like/Between等
- OrderBy即排序
因为篇幅原因,这里还有一些其他情况没有列举出来(例如distinct),好在我们并不需要逐个记忆,首先是这种语法比较贴近自然语言,并且IDEA有完整的自动化提示!
那么如果要创建时间查询t_example并排序可以这样写:
@Repository
public interface ExampleRepository extends JpaRepository<ExampleEntity, Long> {
List<ExampleEntity> findByCreateTimeBetweenOrderByCreateTime(LocalDateTime from, LocalDateTime to);
}自定义查询
上述方法确实很方便,但是在面对复杂场景时可能就不适用了,即便能用也可能导致方法名非常长!
这时候可以使用@Query注解来实现自定义查询,例如还是根据创建时间来查询并排序,可以写为:
@Repository
public interface ExampleRepository extends JpaRepository<ExampleEntity, Long> {
@Query("select t from ExampleEntity t where t.createTime between :from and :to order by create_time desc")
List<ExampleEntity> findByTime(@Param("from") LocalDateTime from, @Param("to") LocalDateTime to);
}需要注意:
- 不能使用select *,表名和字段名必须与Java中定义的一致,而不是数据库中的真实名称
- sql可以使用命名参数
:param,参数要和方法参数中的@Param一一对应
提示
如果要使用原生的sql语句,需要在@Query标签中加上参数nativeQuery = true
H2数据库的运行模式
内存模式
spring.datasource.url=jdbc:h2:mem:[<db_name>]
内存模式下数据直接保存在内存中。
- 如果
db_name为空,则表示数据库是私有库,每个数据库连接将单独创建一个数据库。 - 如果
db_name不为空则所有连接共享一个数据库。 - 当最后一个连接关闭时,数据库也会被关闭,内容丢失。如果希望数据库一直保留直到进程结束,需要设置url:
jdbc:h2:mem:test;DB_CLOSE_DELAY=-1 - 通常内存模式下,应用启动时数据库是空的,可以通过url的INIT参数来设置初始化脚本:
jdbc:h2:mem:test;INIT=runscript from '~/init.sql'
内嵌模式
spring.datasource.url=jdbc:h2:[file:][<path>]<db_name>
内嵌模式下数据库与应用同时启停,H2控制台与应用共用同一个域名和端口,数据文件单独存放在文件系统中以db_name.mv.db命名。
默认使用 localhost:8080/h2-console 访问控制台。
本例即使用这种方式,使用方便且数据可以持久化。
警告
如果开启了Spring Security,会默认设置HTTP Header X-Frame-Options: DENY不允许页面在Frame中加载,因此H2控制台无法打开。
只需在Spring Security中加入.and().headers().frameOptions().sameOrigin()即可。
提示
关于 Spring Security 可以查看Spring Security系列文章
独立运行模式
spring.datasource.url=jdbc:h2:tcp://<server>[:<port>]/[<path>]<db_name>
独立运行模式需要到官网下载运行程序,过程也是非常简单,这里不详述。