Berkely DB Java Edition学习笔记
Berkely DB对于高并发、要求速度快的应用来说是个不错的选择,mysql就是用BDB实现的(mysql的后台) ,mysql快,BDB比mysql还要快N倍。BDB是一种嵌入式的、非关系数据库,它与其他的关系数据库RMDBS不同,它没有提供SQL,而是提供 了自己的访问接口。作为一种嵌入式的数据库,它是进程内模式的,也就是说它和应用程序在同一内存空间运行,所以速度要高很多,与嵌入式的数据库如 Derby、HSQLDB(都是RMDBS的)相比,它效率更高,使用方法也有很大的不同。现在BDB以被Oracle收购。Berkely DB提供的文档Getting Started with Berkeley DB Java Edition可以说是短小精悍(113页),入门相当不错。下面Get Start吧:
Environment:
首先要接触的就是Environment了,使用它来open database以及做一管理方面的事情.
创建Environment,还需要Environment的一些配置信息EnvironmentConfig。
下面是创建的过程:
- EnvironmentConfig envConfig = new EnvironmentConfig();
- envConfig.setAllowCreate(true);
- myDbEnvironment = new Environment(new File("/export/dbEnv"),
- envConfig);
其中EnvironmentConfig提供了许多配置参数,常用的有:
envConfig.setAllowCreate()//如果不存在的env的话,是否要创建一个新的
envConfig.setReadOnly()//是否为只读的
envConfig.setTransactional()//是否使用事务
参数都是boolean类型的
除了EnvironmentConfig外,还有EnvironmentMutableConfig,他实际是EnvironmentConfig的父类,使用他来配置在创建完Environment之后可以改变
的属性:
setCachePercent()//设置cache的大小占JVM memory的百分比
setCacheSize()//设置cache的大小
setTxnNoSync()//事务提交是否将改变的记录写入磁盘
setTxnWriteNoSync()//事务提交是否将log写入磁盘
下面看一下使用EnvironmentMutableConfig的方法:
- Environment myEnv = new Environment(new File("/export/dbEnv"), null);
- EnvironmentMutableConfig envMutableConfig =
- new EnvironmentMutableConfig();
- envMutableConfig.setTxnNoSync(true);
- myEnv.setMutableConfig(envMutableConfig);
Environment通过close来关闭,释放资源
下面看看Environment在管理方面的一些方法:
可以通过Environment获得EnvironmentStats,他提供了Environment一些状态信息,
例如使用
- long cacheMisses = myEnv.getStats(null).getNCacheMiss();
我们可以获得cache未命中的次数,据此来调整cache的大小
可以同过Environment.getDatabaseNames()来获得Environment的数据库的名字:
- List myDbNames = myDbEnv.getDatabaseNames();
- for(int i=0; i < myDbNames.size(); i++) {
- System.out.println("Database Name: " + (String)myDbNames.get(i));
- }
可以通过Environment.removeDatabase()来删除一个数据库:
- String dbName = myDB.getDatabaseName();
- myDB.close();
- myDBEnv.removeDatabase(null,dbName);
可以使用Environment.renameDatabase()来重新命名一个数据库:
- String dbName = myDB.getDatabaseName();
- String dbNewName = new String(dbName + ".new", "UTF-8");
- myDB.close();
- myDBEnv.renameDatabase(null,dbName,dbNewName);
可以使用Environment.truncateDatabase()来删除数据库中的所有记录:
- myEnv.truncate(null, // txn handle
- myDatabase.getDatabaseName(), // database name
- true//whether to return the count of deleted records
- );
第三个参数是否返回删除的记录数,性能有很大不同。false的话会很快
Database:
最重要的一些操作大多都在Database里了,和Environment一样,它也有许多
配置的选项DatabaseConfig,我们先看看选项:
DatabaseConfig.setAllowCreate()//不能存在的话是open操作否创建新的
DatabaseConfig.setBtreeComparator()//设置Btree的比较器
DatabaseConfig.setDuplicateComparator()//设置判断重复的比较器
DatabaseConfig.setSortedDuplicates()//是否允许重复的记录
DatabaseConfig.setExclusiveCreate()//设为true,如果当前数据库已存在,则open失败,也就是说open操作会导致一个新的数据库被创建,默认为false
DatabaseConfig.setReadOnly()//是否是只读的
DatabaseConfig.setTransactional()//是否使用事务
下面我们看看Database的使用流程:
- EnvironmentConfig envConfig = new EnvironmentConfig();
- envConfig.setAllowCreate(true);
- myDbEnvironment = new Environment(new File("/export/dbEnv"), envConfig);
- DatabaseConfig dbConfig = new DatabaseConfig();
- dbConfig.setAllowCreate(true);
- myDatabase = myDbEnvironment.openDatabase(null,
- "sampleDatabase",
- dbConfig);
我们通过Environment的openDatabase来创建Database对象。使用完了Database使用
close方法来关闭数据库释放资源。
Database Records
Database Record是保存在数据库的内容,包含Key和value两部分,他们都被封装成
DatabaseEntry,DatabaseEntry只能存放字节数组,所以只要能把Key和Value是什么
类型的,只要能转化成字节数组就可以被DatabaseEntry封装。基本类型JE都有对应的Binding,复杂的类型可以使用序列化和自定义binding来实现。
下那面我们看看一个使用方法:
- String aKey = "key";
- String aData = "data";
- try {
- DatabaseEntry theKey = new DatabaseEntry(aKey.getBytes("UTF-8"));
- DatabaseEntry theData = new DatabaseEntry(aData.getBytes("UTF-8"));
- } catch (Exception e) {
- }
我们不应该依赖机器默认的编码,通常要指定特定的编码方法getBytes("UTF-8");
我们先看看怎么从数据库中读写记录:
通过Database.put()和Database.get()我们可以从数据库中读写记录
put:
- String aKey = "myFirstKey";
- String aData = "myFirstData";
- try {
- DatabaseEntry theKey = new DatabaseEntry(aKey.getBytes("UTF-8"));
- DatabaseEntry theData = new DatabaseEntry(aData.getBytes("UTF-8"));
- myDatabase.put(null, theKey, theData);
- } catch (Exception e) {
- }
get:
- String aKey = "myFirstKey";
- try {
- DatabaseEntry theKey = new DatabaseEntry(aKey.getBytes("UTF-8"));
- DatabaseEntry theData = new DatabaseEntry();
- if (myDatabase.get(null, theKey, theData, LockMode.DEFAULT) ==
- OperationStatus.SUCCESS) {
- byte[] retData = theData.getData();
- String foundData = new String(retData, "UTF-8");
- System.out.println("For key: '" + aKey + "' found data: '" +
- foundData + "'.");
- } else {
- System.out.println("No record found for key '" + aKey + "'.");
- }
- } catch (Exception e) {
- }
删除操作:
- String aKey = "myFirstKey";
- DatabaseEntry theKey = new DatabaseEntry(aKey.getBytes("UTF-8"));
- myDatabase.delete(null, theKey);
使用BIND APIs来操作基本类型:
我们可以使用JE提供的Bind Apis来操作数字类型和字符串类型:
以Long为例:
存储数据使用Bind Apis一般步骤如下:
1、通过EntryBinding binding =TupleBinding.getPrimitiveBinding(Long.class);
2、通过EntryBinding 把数据放到DatabaseEntry中:
myBinding.objectToEntry(data, dataEntry);
获取数据使用Bind Apis一般步骤如下:
1、通过EntryBinding binding =TupleBinding.getPrimitiveBinding(Long.class);
2、通过EntryBinding将Entry转换成Object Long theLong = (Long) myBinding.entryToObject(theData);
下面代码以测试的形式演示了整个过程:
- package edu.jlu.fuliang;
- import java.io.File;
- import com.sleepycat.bind.EntryBinding;
- import com.sleepycat.bind.tuple.TupleBinding;
- import com.sleepycat.je.Database;
- import com.sleepycat.je.DatabaseConfig;
- import com.sleepycat.je.DatabaseEntry;
- import com.sleepycat.je.Environment;
- import com.sleepycat.je.EnvironmentConfig;
- import com.sleepycat.je.LockMode;
- import junit.framework.TestCase;
- public class PrimitiveBindingTest extends TestCase{
- private Environment env;
- private Database db;
- private String key = "akey";
- private Long data = 1234556633L;
- public void setUp()throws Exception{
- EnvironmentConfig envConfig = new EnvironmentConfig();
- envConfig.setAllowCreate(true);
- env = new Environment(new File("etc/dbEnv"),envConfig);
- DatabaseConfig dbConfig = new DatabaseConfig();
- dbConfig.setAllowCreate(true);
- db = env.openDatabase(null, "myDB", dbConfig);
- DatabaseEntry keyEntry = new DatabaseEntry(key.getBytes("UTF-8"));
- DatabaseEntry dataEntry = new DatabaseEntry();
- EntryBinding myBinding = TupleBinding.getPrimitiveBinding(Long.class);
- myBinding.objectToEntry(data, dataEntry);
- db.put(null, keyEntry, dataEntry);
- }
- public void testGet()throws Exception{
- DatabaseEntry keyEntry = new DatabaseEntry(key.getBytes("UTF-8"));
- DatabaseEntry dataEntry = new DatabaseEntry();
- EntryBinding binding = TupleBinding.getPrimitiveBinding(Long.class);
- db.get(null, keyEntry, dataEntry, LockMode.DEFAULT);
- Long l = (Long)binding.entryToObject(dataEntry);
- assertEquals(l,data);
- }
- public void tearDown()throws Exception{
- db.close();
- env.truncateDatabase(null, "myDB",false);
- env.close();
- }
- }
序列化复杂的类型
步骤如下:
1、要存储的对象的类需要实现java.io.Serializable
2、打开两个数据库,一个存放数据,另一个存放类的信息
3、实例化com.sleepycat.bind.serial.StoredClassCatalog对象
4、创建uses com.sleepycat.bind.serial.SerialBinding对象
5、使用SerialBinding把对象放到DatabaseEntry中
下面是使用一个能够完整描述这个过程的例子来说明这个过程:
- package edu.jlu.fuliang;
- import java.io.File;
- import com.sleepycat.bind.EntryBinding;
- import com.sleepycat.bind.serial.SerialBinding;
- import com.sleepycat.bind.serial.StoredClassCatalog;
- import com.sleepycat.je.Database;
- import com.sleepycat.je.DatabaseConfig;
- import com.sleepycat.je.DatabaseEntry;
- import com.sleepycat.je.DatabaseException;
- import com.sleepycat.je.Environment;
- import com.sleepycat.je.EnvironmentConfig;
- import com.sleepycat.je.LockMode;
- import junit.framework.TestCase;
- public class SerializableTypeTest extends TestCase{
- private Person person;
- private Environment env;
- private Database db,classDB;
- private StoredClassCatalog classCatalog;
- public void setUp()throws Exception{
- person = new Person();
- person.setAge(12);
- person.setName("zhansan");
- person.setSex('m');
- EnvironmentConfig envConfig = new EnvironmentConfig();
- envConfig.setAllowCreate(true);
- env = new Environment(new File("etc/dbEnv"),envConfig);
- DatabaseConfig dbConfig = new DatabaseConfig();
- dbConfig.setAllowCreate(true);
- db = env.openDatabase(null, "myDB", dbConfig);
- classDB = env.openDatabase(null, "classDB", dbConfig);
- classCatalog = new StoredClassCatalog(classDB);
- EntryBinding dataBinding = new SerialBinding(classCatalog,Person.class);
- DatabaseEntry keyEntry = new DatabaseEntry(person.getName().getBytes("UTF-8"));
- DatabaseEntry dataEntry = new DatabaseEntry();
- dataBinding.objectToEntry(person, dataEntry);
- db.put(null, keyEntry, dataEntry);
- }
- public void testGet()throws Exception{
- EntryBinding dataBinding = new SerialBinding(classCatalog,Person.class);
- DatabaseEntry keyEntry = new DatabaseEntry(person.getName().getBytes("UTF-8"));
- DatabaseEntry dataEntry = new DatabaseEntry();
- db.get(null, keyEntry, dataEntry, LockMode.DEFAULT);
- Person p = (Person)dataBinding.entryToObject(dataEntry);
- assertEquals(p.getName(),person.getName());
- assertEquals(p.getAge(),person.getAge());
- assertEquals(p.getSex(), person.getSex());
- }
- public void tearDown()throws Exception{
- db.close();
- classDB.close();
- env.truncateDatabase(null, "myDB", false);
- env.truncateDatabase(null, "classDB", false);
- env.close();
- }
- }
要存储的对象对应的类
- package edu.jlu.fuliang;
- import java.io.Serializable;
- public class Person implements Serializable{
- private String name;
- private int age;
- private char sex;
- public int getAge() {
- return age;
- }
- public void setAge(int age) {
- this.age = age;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public char getSex() {
- return sex;
- }
- public void setSex(char sex) {
- this.sex = sex;
- }
- }
自定义元组绑定:
存储复杂对象自定义元组绑定的步骤:
1、创建要存储的对象,这个对象的类没有必要实现Serializable接口:
2、扩展com.sleepycat.bind.tuple.TupleBinding来实现自定义的Binging
3、创建2步欻关键的自定义binding对象
4、将创建的对象是用自定义个binding放到DatabaseEntry中
5、使用put方法存入数据库
下面的例子说明了这个过程:
自定义Binging:
- package edu.jlu.fuliang;
- import com.sleepycat.bind.tuple.TupleBinding;
- import com.sleepycat.bind.tuple.TupleInput;
- import com.sleepycat.bind.tuple.TupleOutput;
- public class PersonTupleBinding extends TupleBinding{
- @Override
- public Object entryToObject(TupleInput ti) {
- Person person = new Person();
- person.setName(ti.readString());
- person.setAge(ti.readInt());
- person.setSex(ti.readChar());
- return person;
- }
- @Override
- public void objectToEntry(Object obj, TupleOutput output) {
- Person person = (Person)obj;
- output.writeString(person.getName());
- output.writeInt(person.getAge());
- output.writeChar(person.getSex());
- }
- }
put/get的使用过程:
- package edu.jlu.fuliang;
- import java.io.File;
- import com.sleepycat.je.Database;
- import com.sleepycat.je.DatabaseConfig;
- import com.sleepycat.je.DatabaseEntry;
- import com.sleepycat.je.DatabaseException;
- import com.sleepycat.je.Environment;
- import com.sleepycat.je.EnvironmentConfig;
- import com.sleepycat.je.LockMode;
- import junit.framework.TestCase;
- public class CustomTupleBindingTest extends TestCase{
- private Person person;
- private Environment env;
- private Database db;
- public void setUp()throws Exception{
- person = new Person();
- person.setAge(12);
- person.setName("zhansan");
- person.setSex('m');
- EnvironmentConfig envConfig = new EnvironmentConfig();
- envConfig.setAllowCreate(true);
- env = new Environment(new File("etc/dbEnv"),envConfig);
- DatabaseConfig dbConfig = new DatabaseConfig();
- dbConfig.setAllowCreate(true);
- db = env.openDatabase(null, "myDB", dbConfig);
- PersonTupleBinding binding = new PersonTupleBinding();
- DatabaseEntry keyEntry = new DatabaseEntry(person.getName().getBytes("UTF-8"));
- DatabaseEntry dataEntry = new DatabaseEntry();
- binding.objectToEntry(person, dataEntry);
- db.put(null, keyEntry, dataEntry);
- }
- public void testGet()throws Exception{
- PersonTupleBinding binding = new PersonTupleBinding();
- DatabaseEntry keyEntry = new DatabaseEntry(person.getName().getBytes("UTF-8"));
- DatabaseEntry dataEntry = new DatabaseEntry();
- db.get(null, keyEntry, dataEntry, LockMode.DEFAULT);
- Person p = (Person)binding.entryToObject(dataEntry);
- assertEquals(p.getName(),person.getName());
- assertEquals(p.getAge(),person.getAge());
- assertEquals(p.getSex(), person.getSex());
- }
- public void tearDown()throws Exception{
- db.close();
- env.truncateDatabase(null, "myDB", false);
- env.close();
- }
- }
Berkely DB Java Edition学习笔记的更多相关文章
- 尚学堂JAVA基础学习笔记
目录 尚学堂JAVA基础学习笔记 写在前面 第1章 JAVA入门 第2章 数据类型和运算符 第3章 控制语句 第4章 Java面向对象基础 1. 面向对象基础 2. 面向对象的内存分析 3. 构造方法 ...
- 20145213《Java程序设计学习笔记》第六周学习总结
20145213<Java程序设计学习笔记>第六周学习总结 说在前面的话 上篇博客中娄老师指出我因为数据结构基础薄弱,才导致对第九章内容浅尝遏止地认知.在这里我还要自我批评一下,其实我事后 ...
- [原创]java WEB学习笔记95:Hibernate 目录
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- java JDK8 学习笔记——助教学习博客汇总
java JDK8 学习笔记——助教学习博客汇总 1-6章 (by肖昱) Java学习笔记第一章——Java平台概论 Java学习笔记第二章——从JDK到IDEJava学习笔记第三章——基础语法Jav ...
- java JDK8 学习笔记——第16章 整合数据库
第十六章 整合数据库 16.1 JDBC入门 16.1.1 JDBC简介 1.JDBC是java联机数据库的标准规范.它定义了一组标准类与接口,标准API中的接口会有数据库厂商操作,称为JDBC驱动程 ...
- [原创]java WEB学习笔记75:Struts2 学习之路-- 总结 和 目录
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- [原创]java WEB学习笔记66:Struts2 学习之路--Struts的CRUD操作( 查看 / 删除/ 添加) 使用 paramsPrepareParamsStack 重构代码 ,PrepareInterceptor拦截器,paramsPrepareParamsStack 拦截器栈
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- Android(java)学习笔记267:Android线程池形态
1. 线程池简介 多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力. 假设一个服务器完成一项任务所需时间为:T1 创建线程时间, ...
- java多线程学习笔记——详细
一.线程类 1.新建状态(New):新创建了一个线程对象. 2.就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法.该状态的线程位于可运行线程池中, ...
随机推荐
- Java Web 基础(一) 基于TCP的Socket网络编程
一.Socket简单介绍 Socket通信作为Java网络通讯的基础内容,集中了异常.I/O流模式等众多知识点.学习Socket通信,既能够了解真正的网络通讯原理,也能够增强对I/O流模式的理解. 1 ...
- centos7.3网络配置
一.关闭NetworkManager 默认状态下最小化安装使用NetworkManager这个服务来控制联网的,但是这个配置在配置生产环境服务器时一般不会使用,而是使用系统自带的network服务,更 ...
- Linux系统属性文件详解
1)inode概述 中文意思就是索引节点(index node)第一部分是inode 第二部分是block inode主要用来存放文件属性信息的(也就是ls - l 的结果)包含的属性信息包括文件的大 ...
- CentOS下的Redis启动脚本
这是一个Shell脚本,用于管理Redis进程(启动,停止,重启),如果你在使用Redis,这个脚本可供参考. #!/bin/sh # # redis - this script starts and ...
- 如何将int转换为datetime?
$timestamp = 1210003200; $datetime = date('Y-m-d H:i:s', $timestamp); echo "该时间戳代表的时间:", $ ...
- Robotium测试报告的生成方法(上)
7.1 使用junit-report生成报告 这个是参考网上的:http://www.xuebuyuan.com/2148574.html,经我个人验证是可行的方法,网上写的挺详细的,不过有些不太清楚 ...
- PAT——乙级1018
题目是 1018 锤子剪刀布 (20 point(s)) 大家应该都会玩“锤子剪刀布”的游戏:两人同时给出手势,胜负规则如图所示: 现给出两人的交锋记录,请统计双方的胜.平.负次数,并且给出双方分别出 ...
- 关于C++ STL标准库中map 的多元素应用
map的特性是,所有的元素会根据键值自动排序.map的所有元素都是pair,同时拥有实值(value)和键值(key).pair的第一个元素被视为键值,第二个被视为实质piar 的定义 templat ...
- 单元测试如何保证了易用的API
一般而言TDD的好处是以输出为导向及早发现问题,以及方便重构(单元测试保证).我理解,还有一个比较重要的意义是: 客观上强制了程序员写出更加友好的接口 方便测试和联调. 问题 这里我以c++举例,需求 ...
- 在同一个sql语句中如何写不同条件的count数量 (转)
end) end)"描述名称2" from 表名 t