深入理解h2和r2dbc-h2

{"type":"doc","content":[{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"簡介","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"本文將會介紹R2DBC的H2實現r2dbc-h2的使用方法和要注意的事項。一起來看看吧。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"H2數據庫簡介","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"什麼是H2數據庫呢?","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"H2是一個Java SQL database,它是一個開源的數據庫,運行起來非常快。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"H2流行的原因是它既可以當做一個獨立的服務器,也可以以一個嵌套的服務運行,並且支持純內存形式運行。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"H2的jar包非常小,只有2M大小,所以非常適合做嵌套式數據庫。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果作爲嵌入式數據庫,則需要將h2*.jar添加到classpath中。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"下面是一個簡單的建立H2連接的代碼:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"import java.sql.*;\npublic class Test {\n public static void main(String[] a)\n throws Exception {\n Connection conn = DriverManager.\n getConnection(\"jdbc:h2:~/test\", \"sa\", \"\");\n // add application code here\n conn.close();\n }\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果給定地址的數據庫並不存在,","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"同時H2還提供了一個簡單的管理界面,使用下面的命令就可以啓動H2管理界面:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"java -jar h2*.jar\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"默認情況下訪問http://localhost:8082就可以訪問到管理界面:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/50/50c7908a9a005a5759c99fa048d6d752.png","alt":"","title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/23/23b3c4611a0feb61582e5a2aa877f5bf.png","alt":"","title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"r2dbc-h2","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"r2dbc-h2是r2dbc spi的一種實現。同樣的使用r2dbc-h2也提供了兩種h2的模式,一種是文件系統,一種是內存。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"同時還提供了事務支持,prepared statements和batch statements等特性的支持。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"r2dbc-h2的Maven依賴","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"要想使用r2dbc-h2,我們需要添加如下依賴:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"\n io.r2dbc\n r2dbc-h2\n ${version}\n\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果你體驗snapshot版本,可以添加下面的依賴:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"\n io.r2dbc\n r2dbc-h2\n ${version}.BUILD-SNAPSHOT\n\n\n\n spring-libs-snapshot\n Spring Snapshot Repository\n https://repo.spring.io/libs-snapshot\n\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"建立連接","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"h2有兩種連接方式,file和內存,我們分別看一下都是怎麼建立連接的:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"ConnectionFactory connectionFactory = ConnectionFactories.get(\"r2dbc:h2:mem:///testdb\");\n\nPublisher extends Connection> connectionPublisher = connectionFactory.create();\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"ConnectionFactory connectionFactory = ConnectionFactories.get(\"r2dbc:h2:file//my/relative/path\");\n\nPublisher extends Connection> connectionPublisher = connectionFactory.create();\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們還可以通過ConnectionFactoryOptions來創建更加詳細的連接信息:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"ConnectionFactoryOptions options = builder()\n .option(DRIVER, \"h2\")\n .option(PROTOCOL, \"...\") // file, mem\n .option(HOST, \"…\")\n .option(USER, \"…\")\n .option(PASSWORD, \"…\")\n .option(DATABASE, \"…\")\n .build();\n\nConnectionFactory connectionFactory = ConnectionFactories.get(options);\n\nPublisher extends Connection> connectionPublisher = connectionFactory.create();\n\n// Alternative: Creating a Mono using Project Reactor\nMono connectionMono = Mono.from(connectionFactory.create());\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"上面的例子中,我們使用到了driver,protocol, host,username,password和database這幾個選項,除此之外H2ConnectionOption中定義了其他可以使用的Option:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"public enum H2ConnectionOption {\n\n /**\n * FILE|SOCKET|NO\n */\n FILE_LOCK,\n\n /**\n * TRUE|FALSE\n */\n IFEXISTS,\n\n /**\n * Seconds to stay open or {@literal -1} to to keep in-memory DB open as long as the virtual machine is alive.\n */\n DB_CLOSE_DELAY,\n\n /**\n * TRUE|FALSE\n */\n DB_CLOSE_ON_EXIT,\n\n /**\n * DML or DDL commands on startup, use \"\\\\;\" to chain multiple commands\n */\n INIT,\n\n /**\n * 0..3 (0=OFF, 1=ERROR, 2=INFO, 3=DEBUG)\n */\n TRACE_LEVEL_FILE,\n\n /**\n * Megabytes (to override the 16mb default, e.g. 64)\n */\n TRACE_MAX_FILE_SIZE,\n\n /**\n * 0..3 (0=OFF, 1=ERROR, 2=INFO, 3=DEBUG)\n */\n TRACE_LEVEL_SYSTEM_OUT,\n\n LOG,\n\n /**\n * TRUE|FALSE\n */\n IGNORE_UNKNOWN_SETTINGS,\n\n /**\n * r|rw|rws|rwd (r=read, rw=read/write)\n */\n ACCESS_MODE_DATA,\n\n /**\n * DB2|Derby|HSQLDB|MSSQLServer|MySQL|Oracle|PostgreSQL|Ignite\n */\n MODE,\n\n /**\n * TRUE|FALSE\n */\n AUTO_SERVER,\n\n /**\n * A port number\n */\n AUTO_SERVER_PORT,\n\n /**\n * Bytes (e.g. 512)\n */\n PAGE_SIZE,\n\n /**\n * Number of threads (e.g. 4)\n */\n MULTI_THREADED,\n\n /**\n * TQ|SOFT_LRU\n */\n CACHE_TYPE,\n\n /**\n * TRUE|FALSE\n */\n PASSWORD_HASH;\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當然還有最直接的database選項:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"r2dbc:h2:file//../relative/file/name\nr2dbc:h2:file///absolute/file/name\nr2dbc:h2:mem:///testdb\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們還可以通過H2特有的代碼H2ConnectionFactory來創建:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"H2ConnectionFactory connectionFactory = new H2ConnectionFactory(H2ConnectionConfiguration.builder()\n .inMemory(\"...\")\n .option(H2ConnectionOption.DB_CLOSE_DELAY, \"-1\")\n .build());\n\nMono connection = connectionFactory.create();\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"CloseableConnectionFactory connectionFactory = H2ConnectionFactory.inMemory(\"testdb\");\n\nMono connection = connectionFactory.create();\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"參數綁定","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在使用prepare statement的時候,我們需要進行參數綁定:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"connection\n .createStatement(\"INSERT INTO person (id, first_name, last_name) VALUES ($1, $2, $3)\")\n .bind(\"$1\", 1)\n .bind(\"$2\", \"Walter\")\n .bind(\"$3\", \"White\")\n .execute()\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"除了$符號綁定之外,還支持index綁定,如下所示:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"Statement statement = connection.createStatement(\"SELECT title FROM books WHERE author = $1 and publisher = $2\");\nstatement.bind(0, \"John Doe\");\nstatement.bind(1, \"Happy Books LLC\");\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"批處理","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們來看下r2dbc-h2是怎麼來進行批處理的:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"Batch batch = connection.createBatch();\nPublisher extends Result> publisher = batch.add(\"SELECT title, author FROM books\")\n .add(\"INSERT INTO books VALUES('John Doe', 'HappyBooks LLC')\")\n .execute();\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"事務和Savepoint","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"r2dbc還支持事務和savepoint,我們可以在事務中rollback到特定的savepoint。具體的代碼如下:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"Publisher begin = connection.beginTransaction();\n\nPublisher insert1 = connection.createStatement(\"INSERT INTO books VALUES ('John Doe')\").execute();\n\nPublisher savepoint = connection.createSavepoint(\"savepoint\");\n\nPublisher insert2 = connection.createStatement(\"INSERT INTO books VALUES ('Jane Doe')\").execute();\n\n\nPublisher partialRollback = connection.rollbackTransactionToSavepoint(\"savepoint\");\n\n\nPublisher commit = connection.commit();\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"italic","attrs":{}}],"text":"本文作者:flydean程序那些事","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"italic","attrs":{}}],"text":"本文鏈接:","attrs":{}},{"type":"link","attrs":{"href":"http://www.flydean.com/r2dbc-h2-in-depth/","title":null},"content":[{"type":"text","text":"http://www.flydean.com/r2dbc-h2-in-depth/","attrs":{}}],"marks":[{"type":"italic"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"italic","attrs":{}}],"text":"本文來源:flydean的博客","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"italic","attrs":{}}],"text":"歡迎關注我的公衆號:「程序那些事」最通俗的解讀,最深刻的乾貨,最簡潔的教程,衆多你不知道的小技巧等你來發現!","attrs":{}}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章