深入理解h2和r2dbc-h2
简介
本文将会介绍R2DBC的H2实现r2dbc-h2的使用方法和要注意的事项。一起来看看吧。
H2数据库简介
什么是H2数据库呢?
H2是一个Java SQL database,它是一个开源的数据库,运行起来非常快。
H2流行的原因是它既可以当做一个独立的服务器,也可以以一个嵌套的服务运行,并且支持纯内存形式运行。
H2的jar包非常小,只有2M大小,所以非常适合做嵌套式数据库。
如果作为嵌入式数据库,则需要将h2*.jar添加到classpath中。
下面是一个简单的建立H2连接的代码:
import java.sql.*; public class Test { public static void main(String[] a) throws Exception { Connection conn = DriverManager. getConnection("jdbc:h2:~/test", "sa", ""); // add application code here conn.close(); } }
如果给定地址的数据库并不存在,
同时H2还提供了一个简单的管理界面,使用下面的命令就可以启动H2管理界面:
java -jar h2*.jar
默认情况下访问http://localhost:8082就可以访问到管理界面:
r2dbc-h2
r2dbc-h2是r2dbc spi的一种实现。同样的使用r2dbc-h2也提供了两种h2的模式,一种是文件系统,一种是内存。
同时还提供了事务支持,prepared statements和batch statements等特性的支持。
r2dbc-h2的Maven依赖
要想使用r2dbc-h2,我们需要添加如下依赖:
<dependency> <groupId>io.r2dbc</groupId> <artifactId>r2dbc-h2</artifactId> <version>${version}</version> </dependency>
如果你体验snapshot版本,可以添加下面的依赖:
<dependency> <groupId>io.r2dbc</groupId> <artifactId>r2dbc-h2</artifactId> <version>${version}.BUILD-SNAPSHOT</version> </dependency> <repository> <id>spring-libs-snapshot</id> <name>Spring Snapshot Repository</name> <url>https://repo.spring.io/libs-snapshot</url> </repository>
建立连接
h2有两种连接方式,file和内存,我们分别看一下都是怎么建立连接的:
ConnectionFactory connectionFactory = ConnectionFactories.get("r2dbc:h2:mem:///testdb"); Publisher<? extends Connection> connectionPublisher = connectionFactory.create();
ConnectionFactory connectionFactory = ConnectionFactories.get("r2dbc:h2:file//my/relative/path"); Publisher<? extends Connection> connectionPublisher = connectionFactory.create();
我们还可以通过ConnectionFactoryOptions来创建更加详细的连接信息:
ConnectionFactoryOptions options = builder() .option(DRIVER, "h2") .option(PROTOCOL, "...") // file, mem .option(HOST, "…") .option(USER, "…") .option(PASSWORD, "…") .option(DATABASE, "…") .build(); ConnectionFactory connectionFactory = ConnectionFactories.get(options); Publisher<? extends Connection> connectionPublisher = connectionFactory.create(); // Alternative: Creating a Mono using Project Reactor Mono<Connection> connectionMono = Mono.from(connectionFactory.create());
上面的例子中,我们使用到了driver,protocol, host,username,password和database这几个选项,除此之外H2ConnectionOption中定义了其他可以使用的Option:
public enum H2ConnectionOption { /** * FILE|SOCKET|NO */ FILE_LOCK, /** * TRUE|FALSE */ IFEXISTS, /** * Seconds to stay open or {@literal -1} to to keep in-memory DB open as long as the virtual machine is alive. */ DB_CLOSE_DELAY, /** * TRUE|FALSE */ DB_CLOSE_ON_EXIT, /** * DML or DDL commands on startup, use "\\;" to chain multiple commands */ INIT, /** * 0..3 (0=OFF, 1=ERROR, 2=INFO, 3=DEBUG) */ TRACE_LEVEL_FILE, /** * Megabytes (to override the 16mb default, e.g. 64) */ TRACE_MAX_FILE_SIZE, /** * 0..3 (0=OFF, 1=ERROR, 2=INFO, 3=DEBUG) */ TRACE_LEVEL_SYSTEM_OUT, LOG, /** * TRUE|FALSE */ IGNORE_UNKNOWN_SETTINGS, /** * r|rw|rws|rwd (r=read, rw=read/write) */ ACCESS_MODE_DATA, /** * DB2|Derby|HSQLDB|MSSQLServer|MySQL|Oracle|PostgreSQL|Ignite */ MODE, /** * TRUE|FALSE */ AUTO_SERVER, /** * A port number */ AUTO_SERVER_PORT, /** * Bytes (e.g. 512) */ PAGE_SIZE, /** * Number of threads (e.g. 4) */ MULTI_THREADED, /** * TQ|SOFT_LRU */ CACHE_TYPE, /** * TRUE|FALSE */ PASSWORD_HASH; }
当然还有最直接的database选项:
r2dbc:h2:file//../relative/file/name r2dbc:h2:file///absolute/file/name r2dbc:h2:mem:///testdb
我们还可以通过H2特有的代码H2ConnectionFactory来创建:
H2ConnectionFactory connectionFactory = new H2ConnectionFactory(H2ConnectionConfiguration.builder() .inMemory("...") .option(H2ConnectionOption.DB_CLOSE_DELAY, "-1") .build()); Mono<Connection> connection = connectionFactory.create();
CloseableConnectionFactory connectionFactory = H2ConnectionFactory.inMemory("testdb"); Mono<Connection> connection = connectionFactory.create();
参数绑定
在使用prepare statement的时候,我们需要进行参数绑定:
connection .createStatement("INSERT INTO person (id, first_name, last_name) VALUES ($1, $2, $3)") .bind("$1", 1) .bind("$2", "Walter") .bind("$3", "White") .execute()
除了$符号绑定之外,还支持index绑定,如下所示:
Statement statement = connection.createStatement("SELECT title FROM books WHERE author = $1 and publisher = $2"); statement.bind(0, "John Doe"); statement.bind(1, "Happy Books LLC");
批处理
我们来看下r2dbc-h2是怎么来进行批处理的:
Batch batch = connection.createBatch(); Publisher<? extends Result> publisher = batch.add("SELECT title, author FROM books") .add("INSERT INTO books VALUES('John Doe', 'HappyBooks LLC')") .execute();
事务和Savepoint
r2dbc还支持事务和savepoint,我们可以在事务中rollback到特定的savepoint。具体的代码如下:
Publisher<Void> begin = connection.beginTransaction(); Publisher<Void> insert1 = connection.createStatement("INSERT INTO books VALUES ('John Doe')").execute(); Publisher<Void> savepoint = connection.createSavepoint("savepoint"); Publisher<Void> insert2 = connection.createStatement("INSERT INTO books VALUES ('Jane Doe')").execute(); Publisher<Void> partialRollback = connection.rollbackTransactionToSavepoint("savepoint"); Publisher<Void> commit = connection.commit();
本文作者:flydean程序那些事
本文链接:http://www.flydean.com/r2dbc-h2-in-depth/
本文来源:flydean的博客
欢迎关注我的公众号:「程序那些事」最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!
- 深入理解r2dbc-mysql
- 深入理解计算机系统第二版习题解答CSAPP 2.17
- [布局概念] 关于CSS-BFC深入理解
- android Touch事件分发深入理解
- 深入理解Java虚拟机
- 深入理解hadoop网络
- 深入理解Java:注解(Annotation)自定义注解入门
- Java核心(二)深入理解线程池ThreadPool
- 四、OpenCV学习笔记——深入理解指针
- 深入理解javascript学习笔记(一) 编写高质量代码
- ElasticSearch-深入理解系列1-ES简介
- Java线程中断的本质深入理解
- Android 深入理解Android中的自定义属性
- (转)深入理解Objective-C的Runtime机制
- 好书推荐——关于学习Linux的经典书籍 (深入理解Linux内核、Linux设备驱动程序等)
- WebRTC学习之ICE深入理解
- 深入理解asp.net里的HttpModule机制
- js面向对象中的prototype深入理解
- 深入理解拉格朗日乘子法(Lagrange Multiplier) 和KKT条件
- 深入理解C++枚举类型enum