Berkeley DB Java Edition初步

0.概述
Berkeley DB是历史悠久的嵌入式数据库系统,主要应用在UNIX/LINUX操作系统上,其设计思想是简单、小巧、可靠、高性能。

1. 下载
可去 官网下载,本文写作时的Java Edition(简称JE)最新版是Berkeley DB Java Edition 6.1.5。
另外,也可以用maven pom的方式来指定,这样就不用下载了(可参考上面这个地址上的链接)。
下载以后,解压后在lib目录下有个je-6.1.5.jar,加入到classpath就可以用了。Berkeley DB不需要像oracle,mysql那样先要启动数据库。因为他是嵌入式的,所以直接指定一个目录写文件就可以了。数据库文件的格式是00000000.jdb,00000001.jdb......

2. Base API
Berkeley DB读写数据库有2种API(Base API和DPL)。
先介绍第一种,Base API。
没啥好说的,看了代码就懂的。
public class BaseApiTest {

	public static void main(String[] args) throws Exception {
		EnvironmentConfig envConfig = new EnvironmentConfig();
		envConfig.setAllowCreate(true);
		Environment dbEnv = new Environment(new File("D:/bdbtest/"), envConfig);
		DatabaseConfig dbconf = new DatabaseConfig();
		dbconf.setAllowCreate(true);
		dbconf.setSortedDuplicates(false);//allow update
		Database db = dbEnv.openDatabase(null, "SampleDB", dbconf);
		DatabaseEntry searchEntry = new DatabaseEntry();
		DatabaseEntry dataValue = new DatabaseEntry("data content".getBytes("UTF-8")); 
		DatabaseEntry keyValue = new DatabaseEntry("key content".getBytes("UTF-8"));
		db.put(null, keyValue, dataValue);//inserting an entry	}
		db.get(null, keyValue, searchEntry, LockMode.DEFAULT);//retrieving record
		String foundData = new String(searchEntry.getData(), "UTF-8");
		System.out.println(foundData);
		dataValue = new DatabaseEntry("updated data content".getBytes("UTF-8"));
		db.put(null, keyValue, dataValue);//updating an entry
		db.delete(null, keyValue);//delete operation
		db.close();
		dbEnv.close();
	}
}

这段代码先是创建了一个Environment,也就是数据库,指定数据写入目录为D:/bdbtest/。
然后插入一条key/value数据,key="key content", value="data content"

3.DPL
DPL(Direct Persistence Layer ),则相对Base API提供了更多的高级功能。有点类似hibernate/JPA这种了,可以直接将java bean保存到数据库。

首先定义2个java bean,Employee 和Project
@Entity(version=1)
public class Employee {
	@PrimaryKey
	public String empID;
	public String lastname;
	@SecondaryKey(relate = Relationship.MANY_TO_ONE)
	public int age;
	@SecondaryKey(relate = Relationship.MANY_TO_ONE)
	public int sex;
	@SecondaryKey(relate = Relationship.MANY_TO_MANY, relatedEntity = Project.class, onRelatedEntityDelete = DeleteAction.NULLIFY)
	public Set<Long> projects;

	public Employee() {
	}

	public Employee(String empID, String lastname, int age, int sex, Set<Long> projects) {
		this.empID = empID;
		this.lastname = lastname;
		this.age = age;
		this.sex = sex;
		this.projects = projects;
	}
}


@Entity(version=1)
public class Project {
	public String projName;
	@PrimaryKey(sequence = "ID")
	public long projID;

	public Project() {
	}

	public Project(String projName) {
		this.projName = projName;
	}
}


首先,@Entity类似于JPA,表示这是一个实体,或者表。
然后@PrimaryKey表示这张表的主键
@SecondaryKey先不要管。
我们通过下面这个程序测试一下。
public class DplTest {

	public static void main(String[] args) throws Exception {
		EnvironmentConfig envConfig = new EnvironmentConfig();
		envConfig.setAllowCreate(true);
		Environment dbEnv = new Environment(new File("D:/bdbtest/"), envConfig);
		StoreConfig stConf = new StoreConfig();
		stConf.setAllowCreate(true);
		EntityStore store = new EntityStore(dbEnv, "DPLSample", stConf);
		PrimaryIndex<String, Employee> userIndex;
		userIndex = store.getPrimaryIndex(String.class, Employee.class);
		userIndex.putNoReturn(new Employee("u180", "Doe", 20, 1, null));// insert
		Employee user = userIndex.get("u180");// retrieve
		System.out.println("empID=" + user.empID + ",lastname="
				+ user.lastname);
		userIndex.putNoReturn(new Employee("u180", "Locke", 30, 2, null));// Update
		userIndex.delete("u180");// delete
		store.close();
		dbEnv.close();
	}
}

putNoReturn方法就是insert/update数据了,可以看到插入了一条u180的用户,很简单。

4. DPL高级
接下来讲一下@SecondaryKey,表示第二主键。有些字段如果需要查询的,则需要加上@SecondaryKey。
例子中Employee有一个age和sex,relate = Relationship.MANY_TO_ONE表示多个Employee的age和sex允许重复。如果改用Relationship.ONE_TO_ONE的话每个人的年龄就不能重复了,显然是不行的。
下面这句表示Employee和Project表有关联了,是多对多关系。
@SecondaryKey(relate = Relationship.MANY_TO_MANY, relatedEntity = Project.class, onRelatedEntityDelete = DeleteAction.NULLIFY)
	public Set<Long> projects;


好了,测试吧。
public class DplTest2 {

	public static void main(String[] args) throws Exception {
		EnvironmentConfig envConfig = new EnvironmentConfig();
		envConfig.setAllowCreate(true);
		Environment dbEnv = new Environment(new File("D:/bdbtest/"), envConfig);
		StoreConfig stConf = new StoreConfig();
		stConf.setAllowCreate(true);
		EntityStore store = new EntityStore(dbEnv, "DPLSample", stConf);
		
		PrimaryIndex<String, Employee> empByID;
		PrimaryIndex<Long, Project> projByID;
		empByID = store.getPrimaryIndex(String.class, Employee.class); 
		projByID = store.getPrimaryIndex(Long.class, Project.class); 
		SecondaryIndex<Long, String, Employee> empsByProject; 
		empsByProject = store.getSecondaryIndex(empByID, Long.class, "projects"); 
		Set<Long> projects = new HashSet<Long>(); 
		Project proj = null; 
		proj = new Project("Project 1"); 
		projByID.putNoReturn(proj); 
		projects.add(proj.projID); 
		proj = new Project("Project 2"); 
		projByID.putNoReturn(proj); 
		projects.add(proj.projID);
		empByID.putNoReturn(new Employee("u150", "铃木五十郎", 20, 2, projects));//insert
		empByID.putNoReturn(new Employee("u144", "田中四郎", 20, 1, projects));//insert
		empByID.putNoReturn(new Employee("u146", "田中六郎", 30, 2, projects));//insert
		empByID.putNoReturn(new Employee("u147", "田中七郎", 20, 2, projects));//insert
		empByID.putNoReturn(new Employee("u148", "田中八郎", 30, 1, projects));//insert
		empByID.putNoReturn(new Employee("u149", "田中九郎", 20, 2, projects));//insert

		EntityIndex<String, Employee> projs = empsByProject.subIndex(proj.projID);
		EntityCursor<Employee> pcur = projs.entities();
		System.out.println("----Employees----");
		for (Employee user : pcur) {
			System.out.println("empID=" + user.empID + ",lastname="
					+ user.lastname);
		}
		pcur.close(); 
		EntityCursor<Employee> emplRange = empByID.entities("e143", true, "u146", true); 
		System.out.println("----Employees2----");
		for (Employee user : emplRange) {
			System.out.println("empID=" + user.empID + ",lastname="
					+ user.lastname);
		}
		emplRange.close();
		
		EntityJoin<String, Employee> join = new EntityJoin<String, Employee>(empByID);
		
	    // For SecondaryIndex, the params are
	    // 1st - type of the secondary index
	    // 2nd - type of the primary key
	    // 3rd - type of the stored object
		SecondaryIndex<Integer, String, Employee> employeeByAge = store.getSecondaryIndex(empByID, Integer.class, "age"); 
		SecondaryIndex<Integer, String, Employee> employeeBySex = store.getSecondaryIndex(empByID, Integer.class, "sex"); 
		//查找20岁,性别女的所有人
		join.addCondition(employeeByAge, 20);
		join.addCondition(employeeBySex, 2);
		
		System.out.println("----Employees3----");
		ForwardCursor<Employee> joinCursor = join.entities();
		for (Employee user : joinCursor) {
			System.out.println("empID=" + user.empID + ",lastname="
					+ user.lastname);
		}
		joinCursor.close();
		
		store.close(); 
		dbEnv.close();		
	}
}


我们的测试数据是u144~u150,年龄不是20就是30,然后性别不是1就是2(代表男女),每个人做的项目都是一样的,Project 1和Project 2。

测试结果
----Employees----
empID=u144,lastname=田中四郎
empID=u146,lastname=田中六郎
empID=u147,lastname=田中七郎
empID=u148,lastname=田中八郎
empID=u149,lastname=田中九郎
empID=u150,lastname=铃木五十郎
----Employees2----
empID=u144,lastname=田中四郎
empID=u146,lastname=田中六郎
----Employees3----
empID=u147,lastname=田中七郎
empID=u149,lastname=田中九郎
empID=u150,lastname=铃木五十郎

一共3个测试用例。
第一个,empsByProject.subIndex取得了做Project 1和Project 2的所有人,没问题。
第二个,empByID.entities("e143", true, "u146", true)表示取一个范围,id在e143到u146之间的,所以结果是2条记录(u144,u146)
第三个,通过EntityJoin.addCondition()这个方法查找20岁,性别女的所有人所以结果是3条记录(u147,u149,u150)

可以看到功能还是蛮丰富的,可以范围查找,还可以多条件过滤。
附件是本文提到的源代码。

猜你喜欢

转载自xpenxpen.iteye.com/blog/2124921