Chinaunix首页 | 论坛 | 博客
  • 博客访问: 362009
  • 博文数量: 97
  • 博客积分: 2030
  • 博客等级: 大尉
  • 技术积分: 763
  • 用 户 组: 普通用户
  • 注册时间: 2006-08-12 09:11
文章分类

全部博文(97)

文章存档

2020年(1)

2019年(1)

2018年(4)

2017年(16)

2016年(61)

2015年(1)

2013年(3)

2006年(10)

我的朋友

分类: Java

2016-05-05 14:40:27

一个通用的事务保护,100%纯Java编写的嵌入式NoSQL数据库,采取开源(免费)和商用(付费)的双License的授权模式。Berkeley DB是历史悠久的嵌入式数据库系统,06年被 Oracle 收购,而Berkeley DB Java Edition是Berkeley DB产品中的一部分。 

引用
Berkeley DB Java Edition is a open source, transactional storage solution for Java applications. The Direct Persistence Layer (DPL) API is faster and easier to develop, deploy, and manage than serialized object files or ORM-based Java persistence solutions.  The Collections API enhances the standard java.util.collections classes allowing them to be persisted to a local file system and accessed concurrently while protected by ACID transactions. Data is stored by serializing objects and managing class and instance data separately so as not to waste space. Berkeley DB Java Edition is the reliable drop-in solution for complex, fast, and scalable storage.


http://www.oracle.com/technetwork/products/berkeleydb/downloads/index.html 

一、概述   

        Berkeley DB是历史悠久的嵌入式数据库系统,在06年被 Oracle 收购了。现在我们在 Oracle 网站上会看到: BerkeleyDB、BerkeleyDB XML 和 BerkeleyDB JAVA Edition 这个三个东东。简单的说最开始 BerkeleyDB 是只有 C 语言版本的,但是 JAVA 也可以使用,只不过需要通过 JNI 调用,效率可能有点影响。后来出了 JAVA Edition ,用纯 JAVA 实现了一遍,也就是我们看到的 BerkeleyDB JAVA Edition (简称 JE )。
       JE是一个通用的事务保护的,100%纯Java(JE不作任何JNI调用)编写的嵌入式数据库。因此,它为Java开发人员提供了安全高效的对任意数据的存储和管理。
       您可以通过一系列的Java API来使用JE,这些API能够读写数据,管理你的数据库,而且可以执行一些更高级的活动,如管理事务。
       和JE进行交互的Java API有两种基本形式。


  • 第一个是高层次的API,可让您的Java类的持久性。
  • 第二个是一个低级别的API,它提供了额外的灵活性与JE数据库。


二、特性

      • 大型数据库的支持:它支持从1到数百万级的数据量,数据库的大小限制基本上受限于你的硬件支持。
      • Database Environment:Database Environment提供了一个单元的封装和管理一个或多个数据库。Database Environment也是内部资源管理的一个单元,如内存中的缓存和后台线程。最后,使用它管理并发性和事务。请注意,所有应用程序使用JE都需要使用Database Environment。
      • 多线程,多进程支持:JE是专为控制多线程设计的。读写操作都可以是多线程。JE使用记录级锁定为线程应用程序提供高并发性。此外,JE使用死锁超时检测的机制来确保不会有两个线程无限期的死锁。JE允许多个进程访问同一个DB,但在这种情况下, Berkeley 只允许一个线程进行写操作,读操作随意。 
      • 事务:原子性,可恢复,隔离性。 
      • 内存Cache:为了减少IO操作提高性能,将数据暂存在内存里面。 
      • 索引。 
      • 日志文件:JE数据是存储在主目录下一个或多个数字命名的日志文件。日志文件一次写成并且非常便于跨平台的移植。
      • 后台线程:JE提供了几个线程为你管理内部资源。 checkpointer是负责数据库中的数据刷新到磁盘上的;compressor线程从数据库中删除由于删除活动产生的子树是空的数据;cleaner线程负责清理和删除不需要的日志文件,从而帮助您节省磁盘空间。 
      • 备份和恢复:JE的备份就是将log文件copy到一个安全的存储介质, 它的灾后重建的做法就是把备份的日志文件拿出来,放到原位置, 重启JE即可。

三、maven 下载

 
  1. <dependency>
  2.             <groupId>com.sleepycat</groupId>
  3.             <artifactId>je</artifactId>
  4.             <version>6.4.25</version>
  5.         </dependency>

四、应用       

(1)打开Database环境 
Java代码  收藏代码
  1. EnvironmentConfig envCfg = new EnvironmentConfig();  
  2. //当数据库环境不存在的时候,创建一个数据库环境,默认为false.  
  3. envCfg.setAllowCreate(true);  
  4. //以只读方式打开,默认为false.  
  5. envCfg.setReadOnly(false);  
  6. //事务支持,默认为false.  
  7. envCfg.setTransactional(true);  
  8.   
  9. Environment mydbEnv = new Environment(new File(envHome), envCfg);  
  10.   
  11. System.out.println("Env Config: " + mydbEnv.getConfig());  


(2)打开Database 
Java代码  收藏代码
  1. DatabaseConfig dbCfg = new DatabaseConfig();  
  2. dbCfg.setAllowCreate(true);  
  3. dbCfg.setReadOnly(false);  
  4. dbCfg.setTransactional(true);  
  5.   
  6. Database mytestdb = mydbEnv.openDatabase(null"VendorDB", dbCfg);  
  7.       
  8. System.out.println("Database Name: " + mytestdb.getDatabaseName());  


(3)简单的CRUD 
Java代码  收藏代码
  1. //C  
  2. String key = "key-rensanning";  
  3. String value = "This is a test!(000)";  
  4.   
  5. DatabaseEntry keyEntry = new DatabaseEntry(key.getBytes("utf-8"));  
  6. DatabaseEntry valEntry = new DatabaseEntry(value.getBytes("utf-8"));  
  7. OperationStatus status = mytestdb.put(null, keyEntry, valEntry);  
  8. System.out.println("Put Status: " + status);  
  9.   
  10. //R  
  11. DatabaseEntry valGet = new DatabaseEntry();  
  12. status = mytestdb.get(null, keyEntry, valGet, LockMode.DEFAULT);  
  13. if (status == OperationStatus.SUCCESS) {  
  14.     value = new String(valGet.getData(), "utf-8");  
  15.     System.out.println("Read Value:" + value);  
  16. }  
  17.   
  18. //U  
  19. value = "This is a test!(111)";  
  20. status = mytestdb.put(null, keyEntry, new DatabaseEntry(value.getBytes("utf-8")));  
  21.   
  22. status = mytestdb.get(null, keyEntry, valGet, LockMode.DEFAULT);  
  23. if (status == OperationStatus.SUCCESS) {  
  24.     value = new String(valGet.getData(), "utf-8");  
  25.     System.out.println("Update Value:" + value);  
  26. }  
  27.   
  28. //D  
  29. status = mytestdb.delete(null, keyEntry);  
  30. System.out.println("Delete Status: " + status);  


(4)不同的数据写入方式 
Java代码  收藏代码
  1. String key = "key-rensanning";  
  2. DatabaseEntry keyEntry = new DatabaseEntry(key.getBytes("utf-8"));  
  3. DatabaseEntry valGet = new DatabaseEntry();  
  4.   
  5. String value = "This is a test!(by 'put' method)";  
  6. //Database.put(): 向数据库写入数据,如果不支持重复记录,则会覆盖更新key对应的已有记录  
  7. OperationStatus status = mytestdb.put(null, keyEntry, new DatabaseEntry(value.getBytes("utf-8")));  
  8.   
  9. status = mytestdb.get(null, keyEntry, valGet, LockMode.DEFAULT);  
  10. if (status == OperationStatus.SUCCESS) {  
  11.     value = new String(valGet.getData(), "utf-8");  
  12.     System.out.println("Put Value:" + value);  
  13. }  
  14.   
  15. //Database.putNoOverwrite():向数据库写入数据,但是如果key已经存在,不会覆盖已有数据(即使数据库支持重复key)  
  16. value = "This is a test!(by 'putNoOverwrite' method)";  
  17. status = mytestdb.putNoOverwrite(null, keyEntry, new DatabaseEntry(value.getBytes("utf-8")));  
  18.   
  19. status = mytestdb.get(null, keyEntry, valGet, LockMode.DEFAULT);  
  20. if (status == OperationStatus.SUCCESS) {  
  21.     value = new String(valGet.getData(), "utf-8");  
  22.     System.out.println("PutNoOverwrite Value:" + value);  
  23. }  
  24.   
  25. //*****设置一个key是否允许存储多个值*****  
  26. DatabaseConfig dbCfg = new DatabaseConfig();  
  27. dbCfg.setAllowCreate(true);  
  28. dbCfg.setReadOnly(false);  
  29. dbCfg.setTransactional(true);  
  30. dbCfg.setSortedDuplicates(true);  
  31.   
  32. Database mytestdb2 = mytestdb.getEnvironment().openDatabase(null"DuplicatesDB", dbCfg);  
  33.   
  34. //Database.putNoDupData():向数据库写入数据(该方法仅用于支持重复key的数据库),如果key和value对应的记录已经存在,那么操作结果是:OperationStatus.KEYEXIST  
  35. value = "This is a test!(by 'putNoDupData' method)";  
  36. status = mytestdb2.putNoDupData(null, keyEntry, new DatabaseEntry(value.getBytes("utf-8")));  
  37. if (status == OperationStatus.SUCCESS) {  
  38.     value = new String(valGet.getData(), "utf-8");  
  39.     System.out.println("PutNoOverwrite Value:" + value);  
  40. else if (status == OperationStatus.KEYEXIST) {  
  41.     System.out.println("putNoDupData KEYEXIST:" + key);  
  42. }  
  43.   
  44. status = mytestdb2.get(null, keyEntry, valGet, LockMode.DEFAULT);  
  45. if (status == OperationStatus.SUCCESS) {  
  46.     value = new String(valGet.getData(), "utf-8");  
  47.     System.out.println("putNoDupData Value:" + value);  
  48. }  
  49.   
  50. if (null != mytestdb2) {  
  51.     mytestdb2.close();  
  52.     mytestdb2 = null;  
  53. }  


(5)不同的数据读取方式 
Java代码  收藏代码
  1. String key = "key-rensanning";  
  2. String value = "This is a test!(000)";  
  3. DatabaseEntry keyEntry = new DatabaseEntry(key.getBytes("utf-8"));  
  4. DatabaseEntry valEntry = new DatabaseEntry(value.getBytes("utf-8"));  
  5. OperationStatus status = mytestdb.put(null, keyEntry, valEntry);  
  6. System.out.println("Put Status: " + status);  
  7.   
  8. DatabaseEntry valGet = new DatabaseEntry();  
  9.   
  10. //Database.get() :检索key对应的记录  
  11. status = mytestdb.get(null, keyEntry, valGet, LockMode.DEFAULT);  
  12. if (status == OperationStatus.SUCCESS) {  
  13.     value = new String(valGet.getData(), "utf-8");  
  14.     System.out.println("Read Value(get):" + value);  
  15. }  
  16.   
  17. //Database.getSearchBoth() :根据key和value 检索数据库记录  
  18. status = mytestdb.getSearchBoth(null, keyEntry, valGet, LockMode.DEFAULT);  
  19. if (status == OperationStatus.SUCCESS) {  
  20.     value = new String(valGet.getData(), "utf-8");  
  21.     System.out.println("Read Value(getSearchBoth):" + value);  
  22. }  


(6)对象的读写 
Java代码  收藏代码
  1. //C  
  2. String key = "key-rensanning-Object";  
  3. Person value = new Person(9527"rensanning"true);  
  4.   
  5. DatabaseEntry keyEntry = new DatabaseEntry(key.getBytes("utf-8"));  
  6. DatabaseEntry valEntry = new DatabaseEntry();  
  7. PersonTupleBinding personBinding = new PersonTupleBinding();  
  8. personBinding.objectToEntry(value, valEntry);  
  9.   
  10. OperationStatus status = mytestdb.put(null, keyEntry, valEntry);  
  11. System.out.println("Put Person Status: " + status);  
  12.   
  13. //R  
  14. DatabaseEntry valGet = new DatabaseEntry();  
  15. status = mytestdb.get(null, keyEntry, valGet, LockMode.DEFAULT);  
  16. if (status == OperationStatus.SUCCESS) {  
  17.     value = personBinding.entryToObject(valGet);  
  18.     System.out.println("Read Person Value:" + value.getId() + "\t" + value.getName() + "\t" + value.isSex());  
  19. }  

Java代码  收藏代码
  1. class Person {  
  2.     int id;  
  3.     String name;  
  4.     boolean sex;  
  5.   
  6.     public Person() {  
  7.     }  
  8.       
  9.     public Person(int id, String name, boolean sex) {  
  10.         this.id = id;  
  11.         this.name = name;  
  12.         this.sex = sex;  
  13.     }  
  14.       
  15.     public int getId() {  
  16.         return id;  
  17.     }  
  18.     public void setId(int id) {  
  19.         this.id = id;  
  20.     }  
  21.     public String getName() {  
  22.         return name;  
  23.     }  
  24.     public void setName(String name) {  
  25.         this.name = name;  
  26.     }  
  27.     public boolean isSex() {  
  28.         return sex;  
  29.     }  
  30.     public void setSex(boolean sex) {  
  31.         this.sex = sex;  
  32.     }  
  33. }  

Java代码  收藏代码
  1. class PersonTupleBinding extends TupleBinding {  
  2.   
  3.     @Override  
  4.     public Person entryToObject(TupleInput input) {  
  5.         Person p = new Person();  
  6.         p.setId(input.readInt());  
  7.         p.setName(input.readString());  
  8.         p.setSex(input.readBoolean());  
  9.         return p;  
  10.     }  
  11.   
  12.     @Override  
  13.     public void objectToEntry(Person p, TupleOutput output) {         
  14.         output.writeInt(p.getId());  
  15.         output.writeString(p.getName());  
  16.         output.writeBoolean(p.isSex());  
  17.     }  
  18. }  


(7)直接持久层应用(DPL:Direct Persistence Layer) 
Java代码  收藏代码
  1. Environment env = mytestdb.getEnvironment();  
  2.   
  3. StoreConfig storeConfig = new StoreConfig();  
  4. storeConfig.setAllowCreate(true);  
  5. storeConfig.setTransactional(true);  
  6.   
  7. EntityStore store = new EntityStore(env, "StoreDB", storeConfig);  
  8.   
  9. PrimaryIndex pIndex = store.getPrimaryIndex(String.class, UserInfo.class);  
  10.   
  11. //C  
  12. pIndex.put(new UserInfo("001""user001"));  
  13. pIndex.put(new UserInfo("002""user002"));  
  14. pIndex.put(new UserInfo("003""user003"));  
  15. pIndex.put(new UserInfo("004""user004"));  
  16. pIndex.put(new UserInfo("005""user005"));  
  17.   
  18. //R  
  19. String myKey = "001";  
  20. UserInfo getData = pIndex.get(myKey);  
  21. System.out.println("Read User 001:" + getData);  
  22.   
  23. //U  
  24. pIndex.put(new UserInfo("002""user002222"));  
  25.   
  26. //Read ALL  
  27. EntityCursor cursor = pIndex.entities();  
  28. try {  
  29.     Iterator i = cursor.iterator();  
  30.     while (i.hasNext()) {  
  31.         System.out.println("Cursor data:" + i.next());  
  32.     }  
  33. finally {  
  34.     cursor.close();  
  35. }  
  36.   
  37. //D  
  38. String pkey = "003";  
  39. boolean flag = pIndex.delete(pkey);  
  40. System.out.println("delete object :" + pkey + " result:" + flag);  
  41.   
  42. //关闭store  
  43. if (store != null) {  
  44.     store.close();  
  45.     store = null;  
  46. }  

Java代码  收藏代码
  1. @Entity  
  2. @SuppressWarnings("serial")  
  3. class UserInfo implements Serializable {  
  4.       
  5.     @PrimaryKey  
  6.     private String userId;  
  7.     private String userName;  
  8.   
  9.     public UserInfo() {  
  10.     }  
  11.   
  12.     public UserInfo(String userId, String userName) {  
  13.         this.userId = userId;  
  14.         this.userName = userName;  
  15.     }  
  16.   
  17.     public String getUserId() {  
  18.         return userId;  
  19.     }  
  20.     public void setUserId(String userId) {  
  21.         this.userId = userId;  
  22.     }  
  23.     public String getUserName() {  
  24.         return userName;  
  25.     }  
  26.     public void setUserName(String userName) {  
  27.         this.userName = userName;  
  28.     }  
  29.   
  30.     @Override  
  31.     public String toString() {  
  32.         return "UserInfo [userId=" + userId + ", userName=" + userName + "]";  
  33.     }  
  34. }  


(8)事务处理 
Java代码  收藏代码
  1. Transaction txn = mytestdb.getEnvironment().beginTransaction(nullnull);  
  2. try {  
  3.     for(int i = 0; i < 5; i++) {  
  4.         mytestdb.put(txn, new DatabaseEntry(("TXN-KEY"+(i+1)).getBytes("utf-8")), new DatabaseEntry(("TXN-VALUE"+(i+1)).getBytes("utf-8")));  
  5.     }  
  6. catch (DatabaseException e) {  
  7.     if (txn != null) {  
  8.         txn.abort();  
  9.         txn = null;  
  10.     }  
  11.     throw e;  
  12. finally {  
  13.     if (txn != null) {  
  14.         txn.commit();  
  15.     }  
  16. }  


(9)游标操作 
Java代码  收藏代码
  1. //C  
  2. for(int i = 0; i < 5; i++) {  
  3.     mytestdb.put(nullnew DatabaseEntry(("KEY"+(i+1)).getBytes("utf-8")), new DatabaseEntry(("VALUE"+(i+1)).getBytes("utf-8")));  
  4. }  
  5.   
  6. DatabaseEntry key = new DatabaseEntry();  
  7. DatabaseEntry value = new DatabaseEntry();  
  8.   
  9. //D (by Cursor)  
  10. Transaction txn = mytestdb.getEnvironment().beginTransaction(nullnull);  
  11. Cursor cursor1 = mytestdb.openCursor(txn, null);  
  12. OperationStatus result1 = cursor1.getFirst(key, value, null);  
  13. while (result1 == OperationStatus.SUCCESS) {  
  14.     if ("VALUE3".equals(new String(value.getData(), "utf-8"))) {  
  15.         cursor1.delete();  
  16.     }         
  17.     result1 = cursor1.getNext(key, value, null);  
  18. }  
  19.   
  20. if (cursor1 != null) {  
  21.     cursor1.close();  
  22. }  
  23. if (txn != null) {  
  24.     txn.commit();  
  25. }  
  26.   
  27. //R (by Cursor)  
  28. Cursor cursor2 = mytestdb.openCursor(nullnull);  
  29. OperationStatus result2 = cursor2.getFirst(key, value, null);  
  30.   
  31. while (result2 == OperationStatus.SUCCESS) {  
  32.     System.out.println("Cursor Read Value:" + new String(value.getData(), "utf-8"));              
  33.     result2 = cursor2.getNext(key, value, null);  
  34. }  
  35.   
  36. if (cursor2 != null) {  
  37.     cursor2.close();  
  38. }  


(10)关闭database 
Java代码  收藏代码
  1. //关闭database  
  2. if (mytestdb != null) {  
  3.     mytestdb.close();  
  4.     mytestdb = null;  
  5. }  


(11)关闭database环境 
Java代码  收藏代码
  1. //关闭database环境  
  2. if (mydbEnv != null) {  
  3.     mydbEnv.sync();//把数据同步到磁盘中去  
  4.     mydbEnv.cleanLog();//清理日志  
  5.     mydbEnv.close();  
  6.     mydbEnv = null;  
  7. }  

阅读(958) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~