summaryrefslogtreecommitdiff
path: root/examples_java/src/persist
diff options
context:
space:
mode:
Diffstat (limited to 'examples_java/src/persist')
-rw-r--r--examples_java/src/persist/CustomKeyOrderExample.java126
-rw-r--r--examples_java/src/persist/DplDump.java148
-rw-r--r--examples_java/src/persist/EventExample.java424
-rw-r--r--examples_java/src/persist/EventExampleDPL.java273
-rw-r--r--examples_java/src/persist/PersonExample.java256
-rw-r--r--examples_java/src/persist/gettingStarted/SimpleDA.java51
-rw-r--r--examples_java/src/persist/gettingStarted/SimpleEntityClass.java42
-rw-r--r--examples_java/src/persist/gettingStarted/SimpleStoreGet.java112
-rw-r--r--examples_java/src/persist/gettingStarted/SimpleStorePut.java116
-rw-r--r--examples_java/src/persist/txn/PayloadDataEntity.java33
-rw-r--r--examples_java/src/persist/txn/StoreWriter.java176
-rw-r--r--examples_java/src/persist/txn/TxnGuideDPL.java162
12 files changed, 1919 insertions, 0 deletions
diff --git a/examples_java/src/persist/CustomKeyOrderExample.java b/examples_java/src/persist/CustomKeyOrderExample.java
new file mode 100644
index 0000000..aee8c8b
--- /dev/null
+++ b/examples_java/src/persist/CustomKeyOrderExample.java
@@ -0,0 +1,126 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2002-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+package persist;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+
+import com.sleepycat.db.DatabaseException;
+import com.sleepycat.db.Environment;
+import com.sleepycat.db.EnvironmentConfig;
+import com.sleepycat.persist.EntityCursor;
+import com.sleepycat.persist.EntityStore;
+import com.sleepycat.persist.PrimaryIndex;
+import com.sleepycat.persist.StoreConfig;
+import com.sleepycat.persist.model.Entity;
+import com.sleepycat.persist.model.KeyField;
+import com.sleepycat.persist.model.Persistent;
+import com.sleepycat.persist.model.PrimaryKey;
+
+public class CustomKeyOrderExample {
+
+ @Entity
+ static class Person {
+
+ @PrimaryKey
+ ReverseOrder name;
+
+ Person(String name) {
+ this.name = new ReverseOrder(name);
+ }
+
+ private Person() {} // For deserialization
+
+ @Override
+ public String toString() {
+ return name.value;
+ }
+ }
+
+ @Persistent
+ static class ReverseOrder implements Comparable<ReverseOrder> {
+
+ @KeyField(1)
+ String value;
+
+ ReverseOrder(String value) {
+ this.value = value;
+ }
+
+ private ReverseOrder() {} // For deserialization
+
+ public int compareTo(ReverseOrder o) {
+ return o.value.compareTo(value);
+ }
+ }
+
+ public static void main(String[] args)
+ throws DatabaseException, FileNotFoundException {
+
+ if (args.length != 2 || !"-h".equals(args[0])) {
+ System.err.println
+ ("Usage: java " + CustomKeyOrderExample.class.getName() +
+ " -h <envHome>");
+ System.exit(2);
+ }
+ CustomKeyOrderExample example =
+ new CustomKeyOrderExample(new File(args[1]));
+ example.run();
+ example.close();
+ }
+
+ private Environment env;
+ private EntityStore store;
+
+ private CustomKeyOrderExample(File envHome)
+ throws DatabaseException, FileNotFoundException {
+
+ /* Open a transactional Berkeley DB engine environment. */
+ EnvironmentConfig envConfig = new EnvironmentConfig();
+ envConfig.setAllowCreate(true);
+ envConfig.setTransactional(true);
+ envConfig.setInitializeCache(true);
+ envConfig.setInitializeLocking(true);
+ env = new Environment(envHome, envConfig);
+
+ /* Open a transactional entity store. */
+ StoreConfig storeConfig = new StoreConfig();
+ storeConfig.setAllowCreate(true);
+ storeConfig.setTransactional(true);
+ store = new EntityStore(env, "TestStore", storeConfig);
+ }
+
+ private void run()
+ throws DatabaseException {
+
+ PrimaryIndex<ReverseOrder,Person> index =
+ store.getPrimaryIndex(ReverseOrder.class, Person.class);
+
+ index.put(new Person("Andy"));
+ index.put(new Person("Lisa"));
+ index.put(new Person("Zola"));
+
+ /* Print the entities in key order. */
+ EntityCursor<Person> people = index.entities();
+ try {
+ for (Person person : people) {
+ System.out.println(person);
+ }
+ } finally {
+ people.close();
+ }
+ }
+
+ private void close()
+ throws DatabaseException {
+
+ store.close();
+ env.close();
+ }
+}
diff --git a/examples_java/src/persist/DplDump.java b/examples_java/src/persist/DplDump.java
new file mode 100644
index 0000000..f677bc6
--- /dev/null
+++ b/examples_java/src/persist/DplDump.java
@@ -0,0 +1,148 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2002-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+package persist;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+
+import com.sleepycat.db.DatabaseException;
+import com.sleepycat.db.Environment;
+import com.sleepycat.db.EnvironmentConfig;
+import com.sleepycat.persist.EntityCursor;
+import com.sleepycat.persist.EntityStore;
+import com.sleepycat.persist.PrimaryIndex;
+import com.sleepycat.persist.StoreConfig;
+import com.sleepycat.persist.model.EntityMetadata;
+import com.sleepycat.persist.model.EntityModel;
+import com.sleepycat.persist.raw.RawObject;
+import com.sleepycat.persist.raw.RawStore;
+import com.sleepycat.persist.raw.RawType;
+
+/**
+ * Dumps a store or all stores to standard output in raw XML format. This
+ * sample is intended to be modifed to dump in application specific ways.
+ * @see #usage
+ */
+public class DplDump {
+
+ private File envHome;
+ private String storeName;
+ private boolean dumpMetadata;
+ private Environment env;
+
+ public static void main(String[] args) {
+ try {
+ DplDump dump = new DplDump(args);
+ dump.open();
+ dump.dump();
+ dump.close();
+ } catch (Throwable e) {
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private DplDump(String[] args) {
+
+ for (int i = 0; i < args.length; i += 1) {
+ String name = args[i];
+ String val = null;
+ if (i < args.length - 1 && !args[i + 1].startsWith("-")) {
+ i += 1;
+ val = args[i];
+ }
+ if (name.equals("-h")) {
+ if (val == null) {
+ usage("No value after -h");
+ }
+ envHome = new File(val);
+ } else if (name.equals("-s")) {
+ if (val == null) {
+ usage("No value after -s");
+ }
+ storeName = val;
+ } else if (name.equals("-meta")) {
+ dumpMetadata = true;
+ } else {
+ usage("Unknown arg: " + name);
+ }
+ }
+
+ if (storeName == null) {
+ usage("-s not specified");
+ }
+ if (envHome == null) {
+ usage("-h not specified");
+ }
+ }
+
+ private void usage(String msg) {
+
+ if (msg != null) {
+ System.out.println(msg);
+ }
+
+ System.out.println
+ ("usage:" +
+ "\njava " + DplDump.class.getName() +
+ "\n -h <envHome>" +
+ "\n # Environment home directory" +
+ "\n [-meta]" +
+ "\n # Dump metadata; default: false" +
+ "\n -s <storeName>" +
+ "\n # Store to dump");
+
+ System.exit(2);
+ }
+
+ private void open()
+ throws DatabaseException, FileNotFoundException {
+
+ EnvironmentConfig envConfig = new EnvironmentConfig();
+ envConfig.setInitializeCache(true);
+ envConfig.setInitializeLocking(true);
+ env = new Environment(envHome, envConfig);
+ }
+
+ private void close()
+ throws DatabaseException {
+
+ env.close();
+ }
+
+ private void dump()
+ throws DatabaseException {
+
+ StoreConfig storeConfig = new StoreConfig();
+ storeConfig.setReadOnly(true);
+ RawStore store = new RawStore(env, storeName, storeConfig);
+
+ EntityModel model = store.getModel();
+ for (String clsName : model.getKnownClasses()) {
+ EntityMetadata meta = model.getEntityMetadata(clsName);
+ if (meta != null) {
+ if (dumpMetadata) {
+ for (RawType type : model.getAllRawTypeVersions(clsName)) {
+ System.out.println(type);
+ }
+ } else {
+ PrimaryIndex<Object,RawObject> index =
+ store.getPrimaryIndex(clsName);
+ EntityCursor<RawObject> entities = index.entities();
+ for (RawObject entity : entities) {
+ System.out.println(entity);
+ }
+ entities.close();
+ }
+ }
+ }
+
+ store.close();
+ }
+}
diff --git a/examples_java/src/persist/EventExample.java b/examples_java/src/persist/EventExample.java
new file mode 100644
index 0000000..5a3ee44
--- /dev/null
+++ b/examples_java/src/persist/EventExample.java
@@ -0,0 +1,424 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2004-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+package persist;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.Serializable;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Random;
+import java.util.Set;
+
+import com.sleepycat.bind.EntryBinding;
+import com.sleepycat.bind.serial.SerialBinding;
+import com.sleepycat.bind.serial.StoredClassCatalog;
+import com.sleepycat.bind.tuple.IntegerBinding;
+import com.sleepycat.bind.tuple.LongBinding;
+import com.sleepycat.db.Cursor;
+import com.sleepycat.db.Database;
+import com.sleepycat.db.DatabaseConfig;
+import com.sleepycat.db.DatabaseEntry;
+import com.sleepycat.db.DatabaseException;
+import com.sleepycat.db.DatabaseType;
+import com.sleepycat.db.Environment;
+import com.sleepycat.db.EnvironmentConfig;
+import com.sleepycat.db.OperationStatus;
+import com.sleepycat.db.SecondaryConfig;
+import com.sleepycat.db.SecondaryCursor;
+import com.sleepycat.db.SecondaryDatabase;
+import com.sleepycat.db.SecondaryKeyCreator;
+import com.sleepycat.db.Transaction;
+
+/**
+ * EventExample is a trivial example which stores Java objects that represent
+ * an event. Events are primarily indexed by a timestamp, but have other
+ * attributes, such as price, account reps, customer name and quantity.
+ * Some of those other attributes are indexed.
+ * <p>
+ * The example simply shows the creation of a BDB environment and database,
+ * inserting some events, and retrieving the events.
+ * <p>
+ * This example is meant to be paired with its twin, EventExampleDPL.java.
+ * EventExample.java and EventExampleDPL.java perform the same functionality,
+ * but use the Base API and the Direct Persistence Layer API, respectively.
+ * This may be a useful way to compare the two APIs.
+ * <p>
+ * To run the example:
+ * <pre>
+ * cd jehome/examples
+ * javac je/EventExample.java
+ * java je.EventExample -h <environmentDirectory>
+ * </pre>
+ */
+public class EventExample {
+
+ /*
+ * The Event class embodies our example event and is the application
+ * data. BDB data records are represented at key/data tuples. In this
+ * example, the key portion of the record is the event time, and the data
+ * portion is the Event instance.
+ */
+ static class Event implements Serializable {
+
+ /* This example will add secondary indices on price and accountReps. */
+ private int price;
+ private Set<String> accountReps;
+
+ private String customerName;
+ private int quantity;
+
+ Event(int price,
+ String customerName) {
+
+ this.price = price;
+ this.customerName = customerName;
+ this.accountReps = new HashSet<String>();
+ }
+
+ void addRep(String rep) {
+ accountReps.add(rep);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(" price=").append(price);
+ sb.append(" customerName=").append(customerName);
+ sb.append(" reps=");
+ if (accountReps.size() == 0) {
+ sb.append("none");
+ } else {
+ for (String rep: accountReps) {
+ sb.append(rep).append(" ");
+ }
+ }
+ return sb.toString();
+ }
+
+ int getPrice() {
+ return price;
+ }
+ }
+
+ /* A BDB environment is roughly equivalent to a relational database. */
+ private Environment env;
+
+ /*
+ * A BDB table is roughly equivalent to a relational table with a
+ * primary index.
+ */
+ private Database eventDb;
+
+ /* A secondary database indexes an additional field of the data record */
+ private SecondaryDatabase eventByPriceDb;
+
+ /*
+ * The catalogs and bindings are used to convert Java objects to the byte
+ * array format used by BDB key/data in the base API. The Direct
+ * Persistence Layer API supports Java objects as arguments directly.
+ */
+ private Database catalogDb;
+ private EntryBinding eventBinding;
+
+ /* Used for generating example data. */
+ private Calendar cal;
+
+
+ /*
+ * First manually make a directory to house the BDB environment.
+ * Usage: java EventExample -h <envHome>
+ * All BDB on-disk storage is held within envHome.
+ */
+ public static void main(String[] args)
+ throws DatabaseException, FileNotFoundException {
+
+ if (args.length != 2 || !"-h".equals(args[0])) {
+ System.err.println
+ ("Usage: java " + EventExample.class.getName() +
+ " -h <envHome>");
+ System.exit(2);
+ }
+ EventExample example = new EventExample(new File(args[1]));
+ example.run();
+ example.close();
+ }
+
+ private EventExample(File envHome)
+ throws DatabaseException, FileNotFoundException {
+
+ /* Open a transactional Berkeley DB engine environment. */
+ System.out.println("-> Creating a BDB environment");
+ EnvironmentConfig envConfig = new EnvironmentConfig();
+ envConfig.setAllowCreate(true);
+ envConfig.setTransactional(true);
+ envConfig.setInitializeCache(true);
+ envConfig.setInitializeLocking(true);
+ env = new Environment(envHome, envConfig);
+
+ init();
+ cal = Calendar.getInstance();
+ }
+
+ /**
+ * Create all primary and secondary indices.
+ */
+ private void init()
+ throws DatabaseException, FileNotFoundException {
+
+ System.out.println("-> Creating a BDB database");
+ DatabaseConfig dbConfig = new DatabaseConfig();
+ dbConfig.setTransactional(true);
+ dbConfig.setAllowCreate(true);
+ dbConfig.setType(DatabaseType.BTREE);
+ eventDb = env.openDatabase(null, // use auto-commit txn
+ "eventDb", // file name
+ null, // database name
+ dbConfig);
+
+
+ /*
+ * In our example, the database record is composed of a key portion
+ * which represents the event timestamp, and a data portion holds an
+ * instance of the Event class.
+ *
+ * BDB's base API accepts and returns key and data as byte arrays, so
+ * we need some support for marshaling between objects and byte arrays.
+ * We call this binding, and supply a package of helper classes to
+ * support this. It's entirely possible to do all binding on your own.
+ *
+ * A class catalog database is needed for storing class descriptions
+ * for the serial binding used below. This avoids storing class
+ * descriptions redundantly in each record.
+ */
+ DatabaseConfig catalogConfig = new DatabaseConfig();
+ catalogConfig.setTransactional(true);
+ catalogConfig.setAllowCreate(true);
+ catalogConfig.setType(DatabaseType.BTREE);
+ catalogDb = env.openDatabase(null, "catalogDb", null, catalogConfig);
+ StoredClassCatalog catalog = new StoredClassCatalog(catalogDb);
+
+ /*
+ * Create a serial binding for Event data objects. Serial
+ * bindings can be used to store any Serializable object.
+ * We can use some pre-defined binding classes to convert
+ * primitives like the long key value to the a byte array.
+ */
+ eventBinding = new SerialBinding(catalog, Event.class);
+
+ /*
+ * Open a secondary database to allow accessing the primary
+ * database a secondary key value. In this case, access events
+ * by price.
+ */
+ SecondaryConfig secConfig = new SecondaryConfig();
+ secConfig.setTransactional(true);
+ secConfig.setAllowCreate(true);
+ secConfig.setType(DatabaseType.BTREE);
+ secConfig.setSortedDuplicates(true);
+ secConfig.setKeyCreator(new PriceKeyCreator(eventBinding));
+ eventByPriceDb = env.openSecondaryDatabase(null,
+ "priceDb",
+ null,
+ eventDb,
+ secConfig);
+
+ }
+
+ private void run()
+ throws DatabaseException {
+
+ Random rand = new Random();
+
+ /* DatabaseEntry represents the key and data of each record */
+ DatabaseEntry key = new DatabaseEntry();
+ DatabaseEntry data = new DatabaseEntry();
+
+ /*
+ * Create a set of events. Each insertion is a separate, auto-commit
+ * transaction.
+ */
+ System.out.println("-> Inserting 4 events");
+ LongBinding.longToEntry(makeDate(1), key);
+ eventBinding.objectToEntry(new Event(100, "Company_A"),
+ data);
+ eventDb.put(null, key, data);
+
+ LongBinding.longToEntry(makeDate(2), key);
+ eventBinding.objectToEntry(new Event(2, "Company_B"),
+ data);
+ eventDb.put(null, key, data);
+
+ LongBinding.longToEntry(makeDate(3), key);
+ eventBinding.objectToEntry(new Event(20, "Company_C"),
+ data);
+ eventDb.put(null, key, data);
+
+ LongBinding.longToEntry(makeDate(4), key);
+ eventBinding.objectToEntry(new Event(40, "CompanyD"),
+ data);
+ eventDb.put(null, key, data);
+
+ /* Load a whole set of events transactionally. */
+ Transaction txn = env.beginTransaction(null, null);
+ int maxPrice = 50;
+ System.out.println("-> Inserting some randomly generated events");
+ for (int i = 0; i < 25; i++) {
+ long time = makeDate(rand.nextInt(365));
+ Event e = new Event(rand.nextInt(maxPrice),"Company_X");
+ if ((i%2) ==0) {
+ e.addRep("Jane");
+ e.addRep("Nikunj");
+ } else {
+ e.addRep("Yongmin");
+ }
+ LongBinding.longToEntry(time, key);
+ eventBinding.objectToEntry(e, data);
+ eventDb.put(txn, key, data);
+ }
+ txn.commitWriteNoSync();
+
+ /*
+ * Windows of events - display the events between June 1 and Aug 31
+ */
+ System.out.println("\n-> Display the events between June 1 and Aug 31");
+ long endDate = makeDate(Calendar.AUGUST, 31);
+
+ /* Position the cursor and print the first event. */
+ Cursor eventWindow = eventDb.openCursor(null, null);
+ LongBinding.longToEntry(makeDate(Calendar.JUNE, 1), key);
+
+ if ((eventWindow.getSearchKeyRange(key, data, null)) !=
+ OperationStatus.SUCCESS) {
+ System.out.println("No events found!");
+ eventWindow.close();
+ return;
+ }
+ try {
+ printEvents(key, data, eventWindow, endDate);
+ } finally {
+ eventWindow.close();
+ }
+
+ /*
+ * Display all events, ordered by a secondary index on price.
+ */
+ System.out.println("\n-> Display all events, ordered by price");
+ SecondaryCursor priceCursor =
+ eventByPriceDb.openSecondaryCursor(null, null);
+ try {
+ printEvents(priceCursor);
+ } finally {
+ priceCursor.close();
+ }
+ }
+
+ private void close()
+ throws DatabaseException {
+
+ eventByPriceDb.close();
+ eventDb.close();
+ catalogDb.close();
+ env.close();
+ }
+
+ /**
+ * Print all events covered by this cursor up to the end date. We know
+ * that the cursor operates on long keys and Event data items, but there's
+ * no type-safe way of expressing that within the BDB base API.
+ */
+ private void printEvents(DatabaseEntry firstKey,
+ DatabaseEntry firstData,
+ Cursor cursor,
+ long endDate)
+ throws DatabaseException {
+
+ System.out.println("time=" +
+ new Date(LongBinding.entryToLong(firstKey)) +
+ eventBinding.entryToObject(firstData));
+ DatabaseEntry key = new DatabaseEntry();
+ DatabaseEntry data = new DatabaseEntry();
+
+ while (cursor.getNext(key, data, null) ==
+ OperationStatus.SUCCESS) {
+ if (LongBinding.entryToLong(key) > endDate) {
+ break;
+ }
+ System.out.println("time=" +
+ new Date(LongBinding.entryToLong(key)) +
+ eventBinding.entryToObject(data));
+ }
+ }
+
+ private void printEvents(SecondaryCursor cursor)
+ throws DatabaseException {
+ DatabaseEntry timeKey = new DatabaseEntry();
+ DatabaseEntry priceKey = new DatabaseEntry();
+ DatabaseEntry eventData = new DatabaseEntry();
+
+ while (cursor.getNext(priceKey, timeKey, eventData, null) ==
+ OperationStatus.SUCCESS) {
+ System.out.println("time=" +
+ new Date(LongBinding.entryToLong(timeKey)) +
+ eventBinding.entryToObject(eventData));
+ }
+ }
+
+ /**
+ * Little utility for making up java.util.Dates for different days, just
+ * to generate test data.
+ */
+ private long makeDate(int day) {
+
+ cal.set((Calendar.DAY_OF_YEAR), day);
+ return cal.getTime().getTime();
+ }
+ /**
+ * Little utility for making up java.util.Dates for different days, just
+ * to make the test data easier to read.
+ */
+ private long makeDate(int month, int day) {
+
+ cal.set((Calendar.MONTH), month);
+ cal.set((Calendar.DAY_OF_MONTH), day);
+ return cal.getTime().getTime();
+ }
+
+ /**
+ * A key creator that knows how to extract the secondary key from the data
+ * entry of the primary database. To do so, it uses both the dataBinding
+ * of the primary database and the secKeyBinding.
+ */
+ private static class PriceKeyCreator implements SecondaryKeyCreator {
+
+ private EntryBinding dataBinding;
+
+ PriceKeyCreator(EntryBinding eventBinding) {
+ this.dataBinding = eventBinding;
+ }
+
+ public boolean createSecondaryKey(SecondaryDatabase secondaryDb,
+ DatabaseEntry keyEntry,
+ DatabaseEntry dataEntry,
+ DatabaseEntry resultEntry)
+ throws DatabaseException {
+
+ /*
+ * Convert the data entry to an Event object, extract the secondary
+ * key value from it, and then convert it to the resulting
+ * secondary key entry.
+ */
+ Event e = (Event) dataBinding.entryToObject(dataEntry);
+ int price = e.getPrice();
+ IntegerBinding.intToEntry(price, resultEntry);
+ return true;
+ }
+ }
+}
diff --git a/examples_java/src/persist/EventExampleDPL.java b/examples_java/src/persist/EventExampleDPL.java
new file mode 100644
index 0000000..283b121
--- /dev/null
+++ b/examples_java/src/persist/EventExampleDPL.java
@@ -0,0 +1,273 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2004-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+package persist;
+
+import static com.sleepycat.persist.model.Relationship.MANY_TO_ONE;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Random;
+import java.util.Set;
+
+import com.sleepycat.db.DatabaseException;
+import com.sleepycat.db.Environment;
+import com.sleepycat.db.EnvironmentConfig;
+import com.sleepycat.db.Transaction;
+import com.sleepycat.persist.EntityCursor;
+import com.sleepycat.persist.EntityStore;
+import com.sleepycat.persist.PrimaryIndex;
+import com.sleepycat.persist.SecondaryIndex;
+import com.sleepycat.persist.StoreConfig;
+import com.sleepycat.persist.model.Entity;
+import com.sleepycat.persist.model.PrimaryKey;
+import com.sleepycat.persist.model.SecondaryKey;
+
+/**
+ * EventExampleDPL is a trivial example which stores Java objects that
+ * represent an event. Events are primarily indexed by a timestamp, but have
+ * other attributes, such as price, account reps, customer name and
+ * quantity. Some of those other attributes are indexed.
+ * <p>
+ * The example simply shows the creation of a BDB environment and database,
+ * inserting some events, and retrieving the events using the Direct
+ * Persistence layer.
+ * <p>
+ * This example is meant to be paired with its twin, EventExample.java.
+ * EventExample.java and EventExampleDPL.java perform the same functionality,
+ * but use the Base API and the Direct Persistence Layer API, respectively.
+ * This may be a useful way to compare the two APIs.
+ * <p>
+ * To run the example:
+ * <pre>
+ * javac EventExampleDPL.java
+ * java EventExampleDPL -h <environmentDirectory>
+ * </pre>
+ */
+public class EventExampleDPL {
+
+ /*
+ * The Event class embodies our example event and is the application
+ * data. The @Entity annotation indicates that this class defines the
+ * objects stored in a BDB database.
+ */
+ @Entity
+ static class Event {
+
+ @PrimaryKey
+ private Date time;
+
+ @SecondaryKey(relate=MANY_TO_ONE)
+ private int price;
+
+ private Set<String> accountReps;
+
+ private String customerName;
+ private int quantity;
+
+ Event(Date time,
+ int price,
+ String customerName) {
+
+ this.time = time;
+ this.price = price;
+ this.customerName = customerName;
+ this.accountReps = new HashSet<String>();
+ }
+
+ private Event() {} // For deserialization
+
+ void addRep(String rep) {
+ accountReps.add(rep);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("time=").append(time);
+ sb.append(" price=").append(price);
+ sb.append(" customerName=").append(customerName);
+ sb.append(" reps=");
+ if (accountReps.size() == 0) {
+ sb.append("none");
+ } else {
+ for (String rep: accountReps) {
+ sb.append(rep).append(" ");
+ }
+ }
+ return sb.toString();
+ }
+ }
+
+ /* A BDB environment is roughly equivalent to a relational database. */
+ private Environment env;
+ private EntityStore store;
+
+ /*
+ * Event accessors let us access events by the primary index (time)
+ * as well as by the rep and price fields
+ */
+ PrimaryIndex<Date,Event> eventByTime;
+ SecondaryIndex<Integer,Date,Event> eventByPrice;
+
+ /* Used for generating example data. */
+ private Calendar cal;
+
+ /*
+ * First manually make a directory to house the BDB environment.
+ * Usage: java EventExampleDPL -h <envHome>
+ * All BDB on-disk storage is held within envHome.
+ */
+ public static void main(String[] args)
+ throws DatabaseException, FileNotFoundException {
+
+ if (args.length != 2 || !"-h".equals(args[0])) {
+ System.err.println
+ ("Usage: java " + EventExampleDPL.class.getName() +
+ " -h <envHome>");
+ System.exit(2);
+ }
+ EventExampleDPL example = new EventExampleDPL(new File(args[1]));
+ example.run();
+ example.close();
+ }
+
+ private EventExampleDPL(File envHome)
+ throws DatabaseException, FileNotFoundException {
+
+ /* Open a transactional Berkeley DB engine environment. */
+ System.out.println("-> Creating a BDB environment");
+ EnvironmentConfig envConfig = new EnvironmentConfig();
+ envConfig.setAllowCreate(true);
+ envConfig.setTransactional(true);
+ envConfig.setInitializeCache(true);
+ envConfig.setInitializeLocking(true);
+ env = new Environment(envHome, envConfig);
+
+ /* Initialize the data access object. */
+ init();
+ cal = Calendar.getInstance();
+ }
+
+ /**
+ * Create all primary and secondary indices.
+ */
+ private void init()
+ throws DatabaseException {
+
+ /* Open a transactional entity store. */
+ System.out.println("-> Creating a BDB database");
+ StoreConfig storeConfig = new StoreConfig();
+ storeConfig.setAllowCreate(true);
+ storeConfig.setTransactional(true);
+ store = new EntityStore(env, "ExampleStore", storeConfig);
+
+ eventByTime = store.getPrimaryIndex(Date.class, Event.class);
+ eventByPrice = store.getSecondaryIndex(eventByTime,
+ Integer.class,
+ "price");
+ }
+
+ private void run()
+ throws DatabaseException {
+
+ Random rand = new Random();
+
+ /*
+ * Create a set of events. Each insertion is a separate, auto-commit
+ * transaction.
+ */
+ System.out.println("-> Inserting 4 events");
+ eventByTime.put(new Event(makeDate(1), 100, "Company_A"));
+ eventByTime.put(new Event(makeDate(2), 2, "Company_B"));
+ eventByTime.put(new Event(makeDate(3), 20, "Company_C"));
+ eventByTime.put(new Event(makeDate(4), 40, "CompanyD"));
+
+ /* Load a whole set of events transactionally. */
+ Transaction txn = env.beginTransaction(null, null);
+ int maxPrice = 50;
+ System.out.println("-> Inserting some randomly generated events");
+ for (int i = 0; i < 25; i++) {
+ Event e = new Event(makeDate(rand.nextInt(365)),
+ rand.nextInt(maxPrice),
+ "Company_X");
+ if ((i%2) ==0) {
+ e.addRep("Bob");
+ e.addRep("Nikunj");
+ } else {
+ e.addRep("Yongmin");
+ }
+ eventByTime.put(e);
+ }
+ txn.commitWriteNoSync();
+
+ /*
+ * Windows of events - display the events between June 1 and Aug 31
+ */
+ System.out.println("\n-> Display the events between June 1 and Aug 31");
+ Date startDate = makeDate(Calendar.JUNE, 1);
+ Date endDate = makeDate(Calendar.AUGUST, 31);
+
+ EntityCursor<Event> eventWindow =
+ eventByTime.entities(startDate, true, endDate, true);
+ printEvents(eventWindow);
+
+ /*
+ * Display all events, ordered by a secondary index on price.
+ */
+ System.out.println("\n-> Display all events, ordered by price");
+ EntityCursor<Event> byPriceEvents = eventByPrice.entities();
+ printEvents(byPriceEvents);
+ }
+
+ private void close()
+ throws DatabaseException {
+
+ store.close();
+ env.close();
+ }
+
+ /**
+ * Print all events covered by this cursor.
+ */
+ private void printEvents(EntityCursor<Event> eCursor)
+ throws DatabaseException {
+ try {
+ for (Event e: eCursor) {
+ System.out.println(e);
+ }
+ } finally {
+ /* Be sure to close the cursor. */
+ eCursor.close();
+ }
+ }
+
+ /**
+ * Little utility for making up java.util.Dates for different days, just
+ * to generate test data.
+ */
+ private Date makeDate(int day) {
+
+ cal.set((Calendar.DAY_OF_YEAR), day);
+ return cal.getTime();
+ }
+
+ /**
+ * Little utility for making up java.util.Dates for different days, just
+ * to make the test data easier to read.
+ */
+ private Date makeDate(int month, int day) {
+
+ cal.set((Calendar.MONTH), month);
+ cal.set((Calendar.DAY_OF_MONTH), day);
+ return cal.getTime();
+ }
+}
diff --git a/examples_java/src/persist/PersonExample.java b/examples_java/src/persist/PersonExample.java
new file mode 100644
index 0000000..484f1e7
--- /dev/null
+++ b/examples_java/src/persist/PersonExample.java
@@ -0,0 +1,256 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2002-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+package persist;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.HashSet;
+import java.util.Set;
+
+import com.sleepycat.db.DatabaseException;
+import com.sleepycat.db.Environment;
+import com.sleepycat.db.EnvironmentConfig;
+import com.sleepycat.persist.EntityCursor;
+import com.sleepycat.persist.EntityIndex;
+import com.sleepycat.persist.EntityStore;
+import com.sleepycat.persist.PrimaryIndex;
+import com.sleepycat.persist.SecondaryIndex;
+import com.sleepycat.persist.StoreConfig;
+import com.sleepycat.persist.model.Entity;
+import com.sleepycat.persist.model.Persistent;
+import com.sleepycat.persist.model.PrimaryKey;
+import com.sleepycat.persist.model.SecondaryKey;
+import static com.sleepycat.persist.model.DeleteAction.NULLIFY;
+import static com.sleepycat.persist.model.Relationship.ONE_TO_ONE;
+import static com.sleepycat.persist.model.Relationship.ONE_TO_MANY;
+import static com.sleepycat.persist.model.Relationship.MANY_TO_ONE;
+import static com.sleepycat.persist.model.Relationship.MANY_TO_MANY;
+
+public class PersonExample {
+
+ /* An entity class. */
+ @Entity
+ static class Person {
+
+ @PrimaryKey
+ String ssn;
+
+ String name;
+ Address address;
+
+ @SecondaryKey(relate=MANY_TO_ONE, relatedEntity=Person.class)
+ String parentSsn;
+
+ @SecondaryKey(relate=ONE_TO_MANY)
+ Set<String> emailAddresses = new HashSet<String>();
+
+ @SecondaryKey(relate=MANY_TO_MANY,
+ relatedEntity=Employer.class,
+ onRelatedEntityDelete=NULLIFY)
+ Set<Long> employerIds = new HashSet<Long>();
+
+ Person(String name, String ssn, String parentSsn) {
+ this.name = name;
+ this.ssn = ssn;
+ this.parentSsn = parentSsn;
+ }
+
+ private Person() {} // For deserialization
+ }
+
+ /* Another entity class. */
+ @Entity
+ static class Employer {
+
+ @PrimaryKey(sequence="ID")
+ long id;
+
+ @SecondaryKey(relate=ONE_TO_ONE)
+ String name;
+
+ Address address;
+
+ Employer(String name) {
+ this.name = name;
+ }
+
+ private Employer() {} // For deserialization
+ }
+
+ /* A persistent class used in other classes. */
+ @Persistent
+ static class Address {
+ String street;
+ String city;
+ String state;
+ int zipCode;
+ private Address() {} // For deserialization
+ }
+
+ /* The data accessor class for the entity model. */
+ static class PersonAccessor {
+
+ /* Person accessors */
+ PrimaryIndex<String,Person> personBySsn;
+ SecondaryIndex<String,String,Person> personByParentSsn;
+ SecondaryIndex<String,String,Person> personByEmailAddresses;
+ SecondaryIndex<Long,String,Person> personByEmployerIds;
+
+ /* Employer accessors */
+ PrimaryIndex<Long,Employer> employerById;
+ SecondaryIndex<String,Long,Employer> employerByName;
+
+ /* Opens all primary and secondary indices. */
+ public PersonAccessor(EntityStore store)
+ throws DatabaseException {
+
+ personBySsn = store.getPrimaryIndex(
+ String.class, Person.class);
+
+ personByParentSsn = store.getSecondaryIndex(
+ personBySsn, String.class, "parentSsn");
+
+ personByEmailAddresses = store.getSecondaryIndex(
+ personBySsn, String.class, "emailAddresses");
+
+ personByEmployerIds = store.getSecondaryIndex(
+ personBySsn, Long.class, "employerIds");
+
+ employerById = store.getPrimaryIndex(
+ Long.class, Employer.class);
+
+ employerByName = store.getSecondaryIndex(
+ employerById, String.class, "name");
+ }
+ }
+
+ public static void main(String[] args)
+ throws DatabaseException, FileNotFoundException {
+
+ if (args.length != 2 || !"-h".equals(args[0])) {
+ System.err.println
+ ("Usage: java " + PersonExample.class.getName() +
+ " -h <envHome>");
+ System.exit(2);
+ }
+ PersonExample example = new PersonExample(new File(args[1]));
+ example.run();
+ example.close();
+ }
+
+ private Environment env;
+ private EntityStore store;
+ private PersonAccessor dao;
+
+ private PersonExample(File envHome)
+ throws DatabaseException, FileNotFoundException {
+
+ /* Open a transactional Berkeley DB engine environment. */
+ EnvironmentConfig envConfig = new EnvironmentConfig();
+ envConfig.setAllowCreate(true);
+ envConfig.setTransactional(true);
+ envConfig.setInitializeCache(true);
+ envConfig.setInitializeLocking(true);
+ env = new Environment(envHome, envConfig);
+
+ /* Open a transactional entity store. */
+ StoreConfig storeConfig = new StoreConfig();
+ storeConfig.setAllowCreate(true);
+ storeConfig.setTransactional(true);
+ store = new EntityStore(env, "PersonStore", storeConfig);
+
+ /* Initialize the data access object. */
+ dao = new PersonAccessor(store);
+ }
+
+ private void run()
+ throws DatabaseException {
+
+ /*
+ * Add a parent and two children using the Person primary index.
+ * Specifying a non-null parentSsn adds the child Person to the
+ * sub-index of children for that parent key.
+ */
+ dao.personBySsn.put
+ (new Person("Bob Smith", "111-11-1111", null));
+ dao.personBySsn.put
+ (new Person("Mary Smith", "333-33-3333", "111-11-1111"));
+ dao.personBySsn.put
+ (new Person("Jack Smith", "222-22-2222", "111-11-1111"));
+
+ /* Print the children of a parent using a sub-index and a cursor. */
+ EntityCursor<Person> children =
+ dao.personByParentSsn.subIndex("111-11-1111").entities();
+ try {
+ for (Person child : children) {
+ System.out.println(child.ssn + ' ' + child.name);
+ }
+ } finally {
+ children.close();
+ }
+
+ /* Get Bob by primary key using the primary index. */
+ Person bob = dao.personBySsn.get("111-11-1111");
+ assert bob != null;
+
+ /*
+ * Create two employers if they do not already exist. Their primary
+ * keys are assigned from a sequence.
+ */
+ Employer gizmoInc = dao.employerByName.get("Gizmo Inc");
+ if (gizmoInc == null) {
+ gizmoInc = new Employer("Gizmo Inc");
+ dao.employerById.put(gizmoInc);
+ }
+ Employer gadgetInc = dao.employerByName.get("Gadget Inc");
+ if (gadgetInc == null) {
+ gadgetInc = new Employer("Gadget Inc");
+ dao.employerById.put(gadgetInc);
+ }
+
+ /* Bob has two jobs and two email addresses. */
+ bob.employerIds.add(gizmoInc.id);
+ bob.employerIds.add(gadgetInc.id);
+ bob.emailAddresses.add("bob@bob.com");
+ bob.emailAddresses.add("bob@gmail.com");
+
+ /* Update Bob's record. */
+ dao.personBySsn.put(bob);
+
+ /* Bob can now be found by both email addresses. */
+ bob = dao.personByEmailAddresses.get("bob@bob.com");
+ assert bob != null;
+ bob = dao.personByEmailAddresses.get("bob@gmail.com");
+ assert bob != null;
+
+ /* Bob can also be found as an employee of both employers. */
+ EntityIndex<String,Person> employees;
+ employees = dao.personByEmployerIds.subIndex(gizmoInc.id);
+ assert employees.contains("111-11-1111");
+ employees = dao.personByEmployerIds.subIndex(gadgetInc.id);
+ assert employees.contains("111-11-1111");
+
+ /*
+ * When an employer is deleted, the onRelatedEntityDelete=NULLIFY for
+ * the employerIds key causes the deleted ID to be removed from Bob's
+ * employerIds.
+ */
+ dao.employerById.delete(gizmoInc.id);
+ bob = dao.personBySsn.get("111-11-1111");
+ assert bob != null;
+ assert !bob.employerIds.contains(gizmoInc.id);
+ }
+
+ private void close()
+ throws DatabaseException {
+
+ store.close();
+ env.close();
+ }
+}
diff --git a/examples_java/src/persist/gettingStarted/SimpleDA.java b/examples_java/src/persist/gettingStarted/SimpleDA.java
new file mode 100644
index 0000000..ab4c6e9
--- /dev/null
+++ b/examples_java/src/persist/gettingStarted/SimpleDA.java
@@ -0,0 +1,51 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2008-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+package persist.gettingStarted;
+
+import java.io.File;
+
+import com.sleepycat.db.DatabaseException;
+import com.sleepycat.persist.EntityStore;
+import com.sleepycat.persist.PrimaryIndex;
+import com.sleepycat.persist.SecondaryIndex;
+import com.sleepycat.persist.EntityCursor;
+
+public class SimpleDA {
+ // Open the indices
+ public SimpleDA(EntityStore store)
+ throws DatabaseException {
+
+ // Primary key for SimpleEntityClass classes
+ pIdx = store.getPrimaryIndex(
+ String.class, SimpleEntityClass.class);
+
+ // Secondary key for SimpleEntityClass classes
+ // Last field in the getSecondaryIndex() method must be
+ // the name of a class member; in this case, an
+ // SimpleEntityClass.class data member.
+ sIdx = store.getSecondaryIndex(
+ pIdx, String.class, "sKey");
+
+ sec_pcursor = pIdx.entities();
+ sec_scursor = sIdx.subIndex("skeyone").entities();
+ }
+
+ public void close()
+ throws DatabaseException {
+ sec_pcursor.close();
+ sec_scursor.close();
+ }
+
+ // Index Accessors
+ PrimaryIndex<String,SimpleEntityClass> pIdx;
+ SecondaryIndex<String,String,SimpleEntityClass> sIdx;
+
+ EntityCursor<SimpleEntityClass> sec_pcursor;
+ EntityCursor<SimpleEntityClass> sec_scursor;
+}
diff --git a/examples_java/src/persist/gettingStarted/SimpleEntityClass.java b/examples_java/src/persist/gettingStarted/SimpleEntityClass.java
new file mode 100644
index 0000000..c4c0d81
--- /dev/null
+++ b/examples_java/src/persist/gettingStarted/SimpleEntityClass.java
@@ -0,0 +1,42 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2008-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+package persist.gettingStarted;
+
+import com.sleepycat.persist.model.Entity;
+import com.sleepycat.persist.model.PrimaryKey;
+import static com.sleepycat.persist.model.Relationship.*;
+import com.sleepycat.persist.model.SecondaryKey;
+
+@Entity
+public class SimpleEntityClass {
+
+ // Primary key is pKey
+ @PrimaryKey
+ private String pKey;
+
+ // Secondary key is the sKey
+ @SecondaryKey(relate=MANY_TO_ONE)
+ private String sKey;
+
+ public void setpKey(String data) {
+ pKey = data;
+ }
+
+ public void setsKey(String data) {
+ sKey = data;
+ }
+
+ public String getpKey() {
+ return pKey;
+ }
+
+ public String getsKey() {
+ return sKey;
+ }
+}
diff --git a/examples_java/src/persist/gettingStarted/SimpleStoreGet.java b/examples_java/src/persist/gettingStarted/SimpleStoreGet.java
new file mode 100644
index 0000000..44ac2dc
--- /dev/null
+++ b/examples_java/src/persist/gettingStarted/SimpleStoreGet.java
@@ -0,0 +1,112 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2008-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+package persist.gettingStarted;
+
+import java.io.File;
+
+import com.sleepycat.db.DatabaseException;
+import com.sleepycat.db.Environment;
+import com.sleepycat.db.EnvironmentConfig;
+
+import com.sleepycat.persist.EntityStore;
+import com.sleepycat.persist.StoreConfig;
+
+import java.io.FileNotFoundException;
+
+public class SimpleStoreGet {
+
+ private static File envHome = new File("./JEDB");
+
+ private Environment envmnt;
+ private EntityStore store;
+ private SimpleDA sda;
+
+ // The setup() method opens the environment and store
+ // for us.
+ public void setup()
+ throws DatabaseException {
+
+ try {
+ EnvironmentConfig envConfig = new EnvironmentConfig();
+ StoreConfig storeConfig = new StoreConfig();
+
+ // Open the environment and entity store
+ envmnt = new Environment(envHome, envConfig);
+ store = new EntityStore(envmnt, "EntityStore", storeConfig);
+ } catch (FileNotFoundException fnfe) {
+ System.err.println("setup(): " + fnfe.toString());
+ System.exit(-1);
+ }
+ }
+
+ public void shutdown()
+ throws DatabaseException {
+
+ store.close();
+ envmnt.close();
+ }
+
+
+ private void run()
+ throws DatabaseException {
+
+ setup();
+
+ // Open the data accessor. This is used to store
+ // persistent objects.
+ sda = new SimpleDA(store);
+
+ // Instantiate and store some entity classes
+ SimpleEntityClass sec1 = sda.pIdx.get("keyone");
+ SimpleEntityClass sec2 = sda.pIdx.get("keytwo");
+
+ SimpleEntityClass sec4 = sda.sIdx.get("skeythree");
+
+ System.out.println("sec1: " + sec1.getpKey());
+ System.out.println("sec2: " + sec2.getpKey());
+ System.out.println("sec4: " + sec4.getpKey());
+
+ System.out.println("############ Doing pcursor ##########");
+ for (SimpleEntityClass seci : sda.sec_pcursor ) {
+ System.out.println("sec from pcursor : " + seci.getpKey() );
+ }
+
+ sda.pIdx.delete("keyone");
+ System.out.println("############ Doing pcursor ##########");
+ System.out.println("sec from pcursor : " + sda.sec_pcursor.first().getpKey());
+ for (SimpleEntityClass seci : sda.sec_pcursor ) {
+ System.out.println("sec from pcursor : " + seci.getpKey() );
+ }
+
+ System.out.println("############ Doing scursor ##########");
+ for (SimpleEntityClass seci : sda.sec_scursor ) {
+ System.out.println("sec from scursor : " + seci.getpKey() );
+ }
+
+
+
+ sda.close();
+ shutdown();
+ }
+
+ public static void main(String args[]) {
+ SimpleStoreGet ssg = new SimpleStoreGet();
+ try {
+ ssg.run();
+ } catch (DatabaseException dbe) {
+ System.err.println("SimpleStoreGet: " + dbe.toString());
+ dbe.printStackTrace();
+ } catch (Exception e) {
+ System.out.println("Exception: " + e.toString());
+ e.printStackTrace();
+ }
+ System.out.println("All done.");
+ }
+
+}
diff --git a/examples_java/src/persist/gettingStarted/SimpleStorePut.java b/examples_java/src/persist/gettingStarted/SimpleStorePut.java
new file mode 100644
index 0000000..0e48a5b
--- /dev/null
+++ b/examples_java/src/persist/gettingStarted/SimpleStorePut.java
@@ -0,0 +1,116 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2008-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+package persist.gettingStarted;
+
+import java.io.File;
+
+import com.sleepycat.db.DatabaseException;
+import com.sleepycat.db.Environment;
+import com.sleepycat.db.EnvironmentConfig;
+
+import com.sleepycat.persist.EntityStore;
+import com.sleepycat.persist.StoreConfig;
+
+import java.io.FileNotFoundException;
+
+public class SimpleStorePut {
+
+ private static File envHome = new File("./JEDB");
+
+ private Environment envmnt;
+ private EntityStore store;
+ private SimpleDA sda;
+
+ // The setup() method opens the environment and store
+ // for us.
+ public void setup()
+ throws DatabaseException {
+
+ EnvironmentConfig envConfig = new EnvironmentConfig();
+ StoreConfig storeConfig = new StoreConfig();
+
+ envConfig.setAllowCreate(true);
+ storeConfig.setAllowCreate(true);
+
+ try {
+ // Open the environment and entity store
+ envmnt = new Environment(envHome, envConfig);
+ store = new EntityStore(envmnt, "EntityStore", storeConfig);
+ } catch (FileNotFoundException fnfe) {
+ System.err.println("setup(): " + fnfe.toString());
+ System.exit(-1);
+ }
+ }
+
+ // Close our environment and store.
+ public void shutdown()
+ throws DatabaseException {
+
+ store.close();
+ envmnt.close();
+ }
+
+
+ private void run()
+ throws DatabaseException {
+
+ setup();
+
+ // Open the data accessor. This is used to store
+ // persistent objects.
+ sda = new SimpleDA(store);
+
+ // Instantiate and store some entity classes
+ SimpleEntityClass sec1 = new SimpleEntityClass();
+ SimpleEntityClass sec2 = new SimpleEntityClass();
+ SimpleEntityClass sec3 = new SimpleEntityClass();
+ SimpleEntityClass sec4 = new SimpleEntityClass();
+ SimpleEntityClass sec5 = new SimpleEntityClass();
+
+ sec1.setpKey("keyone");
+ sec1.setsKey("skeyone");
+
+ sec2.setpKey("keytwo");
+ sec2.setsKey("skeyone");
+
+ sec3.setpKey("keythree");
+ sec3.setsKey("skeytwo");
+
+ sec4.setpKey("keyfour");
+ sec4.setsKey("skeythree");
+
+ sec5.setpKey("keyfive");
+ sec5.setsKey("skeyfour");
+
+ sda.pIdx.put(sec1);
+ sda.pIdx.put(sec2);
+ sda.pIdx.put(sec3);
+ sda.pIdx.put(sec4);
+ sda.pIdx.put(sec5);
+
+ sda.close();
+
+ shutdown();
+ }
+
+ public static void main(String args[]) {
+ SimpleStorePut ssp = new SimpleStorePut();
+ try {
+ ssp.run();
+ } catch (DatabaseException dbe) {
+ System.err.println("SimpleStorePut: " + dbe.toString());
+ dbe.printStackTrace();
+ } catch (Exception e) {
+ System.out.println("Exception: " + e.toString());
+ e.printStackTrace();
+ }
+ System.out.println("All done.");
+ }
+
+}
diff --git a/examples_java/src/persist/txn/PayloadDataEntity.java b/examples_java/src/persist/txn/PayloadDataEntity.java
new file mode 100644
index 0000000..9d464ff
--- /dev/null
+++ b/examples_java/src/persist/txn/PayloadDataEntity.java
@@ -0,0 +1,33 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2008-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+package persist.txn;
+
+import com.sleepycat.persist.model.Entity;
+import com.sleepycat.persist.model.PrimaryKey;
+import static com.sleepycat.persist.model.Relationship.*;
+
+@Entity
+public class PayloadDataEntity {
+ @PrimaryKey
+ private int oID;
+
+ private String threadName;
+
+ private double doubleData;
+
+ PayloadDataEntity() {}
+
+ public double getDoubleData() { return doubleData; }
+ public int getID() { return oID; }
+ public String getThreadName() { return threadName; }
+
+ public void setDoubleData(double dd) { doubleData = dd; }
+ public void setID(int id) { oID = id; }
+ public void setThreadName(String tn) { threadName = tn; }
+}
diff --git a/examples_java/src/persist/txn/StoreWriter.java b/examples_java/src/persist/txn/StoreWriter.java
new file mode 100644
index 0000000..fb8b4e5
--- /dev/null
+++ b/examples_java/src/persist/txn/StoreWriter.java
@@ -0,0 +1,176 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2008-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+package persist.txn;
+
+import com.sleepycat.db.CursorConfig;
+import com.sleepycat.db.DatabaseException;
+import com.sleepycat.db.DeadlockException;
+import com.sleepycat.db.Environment;
+import com.sleepycat.db.Transaction;
+
+import com.sleepycat.persist.EntityCursor;
+import com.sleepycat.persist.EntityStore;
+import com.sleepycat.persist.PrimaryIndex;
+
+import java.util.Iterator;
+import java.util.Random;
+import java.io.UnsupportedEncodingException;
+
+public class StoreWriter extends Thread
+{
+ private EntityStore myStore = null;
+ private Environment myEnv = null;
+ private PrimaryIndex<Integer,PayloadDataEntity> pdKey;
+ private Random generator = new Random();
+ private boolean passTxn = false;
+
+
+ private static final int MAX_RETRY = 20;
+
+ // Constructor. Get our handles from here
+ StoreWriter(Environment env, EntityStore store)
+
+ throws DatabaseException {
+ myStore = store;
+ myEnv = env;
+
+ // Open the data accessor. This is used to store persistent
+ // objects.
+ pdKey = myStore.getPrimaryIndex(Integer.class,
+ PayloadDataEntity.class);
+ }
+
+ // Thread method that writes a series of objects
+ // to the store using transaction protection.
+ // Deadlock handling is demonstrated here.
+ public void run () {
+ Transaction txn = null;
+
+ // Perform 50 transactions
+ for (int i=0; i<50; i++) {
+
+ boolean retry = true;
+ int retry_count = 0;
+ // while loop is used for deadlock retries
+ while (retry) {
+ // try block used for deadlock detection and
+ // general exception handling
+ try {
+
+ // Get a transaction
+ txn = myEnv.beginTransaction(null, null);
+
+ // Write 10 PayloadDataEntity objects to the
+ // store for each transaction
+ for (int j = 0; j < 10; j++) {
+ // Instantiate an object
+ PayloadDataEntity pd = new PayloadDataEntity();
+
+ // Set the Object ID. This is used as the primary key.
+ pd.setID(i + j);
+
+ // The thread name is used as a secondary key, and
+ // it is retrieved by this class's getName() method.
+ pd.setThreadName(getName());
+
+ // The last bit of data that we use is a double
+ // that we generate randomly. This data is not
+ // indexed.
+ pd.setDoubleData(generator.nextDouble());
+
+ // Do the put
+ pdKey.put(txn, pd);
+ }
+
+ // commit
+ System.out.println(getName() + " : committing txn : " + i);
+ System.out.println(getName() + " : Found " +
+ countObjects(txn) + " objects in the store.");
+ try {
+ txn.commit();
+ txn = null;
+ } catch (DatabaseException e) {
+ System.err.println("Error on txn commit: " +
+ e.toString());
+ }
+ retry = false;
+
+ } catch (DeadlockException de) {
+ System.out.println("################# " + getName() +
+ " : caught deadlock");
+ // retry if necessary
+ if (retry_count < MAX_RETRY) {
+ System.err.println(getName() +
+ " : Retrying operation.");
+ retry = true;
+ retry_count++;
+ } else {
+ System.err.println(getName() +
+ " : out of retries. Giving up.");
+ retry = false;
+ }
+ } catch (DatabaseException e) {
+ // abort and don't retry
+ retry = false;
+ System.err.println(getName() +
+ " : caught exception: " + e.toString());
+ System.err.println(getName() +
+ " : errno: " + e.getErrno());
+ e.printStackTrace();
+ } finally {
+ if (txn != null) {
+ try {
+ txn.abort();
+ } catch (Exception e) {
+ System.err.println("Error aborting transaction: " +
+ e.toString());
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // This simply counts the number of objects contained in the
+ // store and returns the result. You can use this method
+ // in three ways:
+ //
+ // First call it with an active txn handle.
+ //
+ // Secondly, configure the cursor for dirty reads
+ //
+ // Third, call countObjects AFTER the writer has committed
+ // its transaction.
+ //
+ // If you do none of these things, the writer thread will
+ // self-deadlock.
+ private int countObjects(Transaction txn) throws DatabaseException {
+ int count = 0;
+
+ CursorConfig cc = new CursorConfig();
+ // This is ignored if the store is not opened with uncommitted read
+ // support.
+ cc.setReadUncommitted(true);
+ EntityCursor<PayloadDataEntity> cursor = pdKey.entities(txn, cc);
+
+ try {
+ for (PayloadDataEntity pdi : cursor) {
+ count++;
+ }
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
+ }
+
+ return count;
+
+ }
+}
diff --git a/examples_java/src/persist/txn/TxnGuideDPL.java b/examples_java/src/persist/txn/TxnGuideDPL.java
new file mode 100644
index 0000000..d429507
--- /dev/null
+++ b/examples_java/src/persist/txn/TxnGuideDPL.java
@@ -0,0 +1,162 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 2008-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+// File TxnGuideDPL.java
+
+package persist.txn;
+
+import com.sleepycat.db.DatabaseConfig;
+import com.sleepycat.db.DatabaseException;
+import com.sleepycat.db.DatabaseType;
+import com.sleepycat.db.LockDetectMode;
+
+import com.sleepycat.db.Environment;
+import com.sleepycat.db.EnvironmentConfig;
+
+import com.sleepycat.persist.EntityStore;
+import com.sleepycat.persist.StoreConfig;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+
+public class TxnGuideDPL {
+
+ private static String myEnvPath = "./";
+ private static String storeName = "exampleStore";
+
+ // Handles
+ private static EntityStore myStore = null;
+ private static Environment myEnv = null;
+
+ private static final int NUMTHREADS = 5;
+
+ private static void usage() {
+ System.out.println("TxnGuideDPL [-h <env directory>]");
+ System.exit(-1);
+ }
+
+ public static void main(String args[]) {
+ try {
+ // Parse the arguments list
+ parseArgs(args);
+ // Open the environment and store
+ openEnv();
+
+ // Start the threads
+ StoreWriter[] threadArray;
+ threadArray = new StoreWriter[NUMTHREADS];
+ for (int i = 0; i < NUMTHREADS; i++) {
+ threadArray[i] = new StoreWriter(myEnv, myStore);
+ threadArray[i].start();
+ }
+
+ for (int i = 0; i < NUMTHREADS; i++) {
+ threadArray[i].join();
+ }
+ } catch (Exception e) {
+ System.err.println("TxnGuideDPL: " + e.toString());
+ e.printStackTrace();
+ } finally {
+ closeEnv();
+ }
+ System.out.println("All done.");
+ }
+
+
+ private static void openEnv() throws DatabaseException {
+ System.out.println("opening env and store");
+
+ // Set up the environment.
+ EnvironmentConfig myEnvConfig = new EnvironmentConfig();
+ myEnvConfig.setAllowCreate(true);
+ myEnvConfig.setInitializeCache(true);
+ myEnvConfig.setInitializeLocking(true);
+ myEnvConfig.setInitializeLogging(true);
+ myEnvConfig.setRunRecovery(true);
+ myEnvConfig.setTransactional(true);
+ // EnvironmentConfig.setThreaded(true) is the default behavior
+ // in Java, so we do not have to do anything to cause the
+ // environment handle to be free-threaded.
+
+ // Indicate that we want db to internally perform deadlock
+ // detection. Also indicate that the transaction that has
+ // performed the least amount of write activity to
+ // receive the deadlock notification, if any.
+ myEnvConfig.setLockDetectMode(LockDetectMode.MINWRITE);
+
+ // Set up the entity store
+ StoreConfig myStoreConfig = new StoreConfig();
+ myStoreConfig.setAllowCreate(true);
+ myStoreConfig.setTransactional(true);
+
+ // Need a DatabaseConfig object so as to set uncommitted read
+ // support.
+ DatabaseConfig myDbConfig = new DatabaseConfig();
+ myDbConfig.setType(DatabaseType.BTREE);
+ myDbConfig.setAllowCreate(true);
+ myDbConfig.setTransactional(true);
+ myDbConfig.setReadUncommitted(true);
+
+ try {
+ // Open the environment
+ myEnv = new Environment(new File(myEnvPath), // Env home
+ myEnvConfig);
+
+ // Open the store
+ myStore = new EntityStore(myEnv, storeName, myStoreConfig);
+
+ // Set the DatabaseConfig object, so that the underlying
+ // database is configured for uncommitted reads.
+ myStore.setPrimaryConfig(PayloadDataEntity.class, myDbConfig);
+ } catch (FileNotFoundException fnfe) {
+ System.err.println("openEnv: " + fnfe.toString());
+ System.exit(-1);
+ }
+ }
+
+ private static void closeEnv() {
+ System.out.println("Closing env and store");
+ if (myStore != null ) {
+ try {
+ myStore.close();
+ } catch (DatabaseException e) {
+ System.err.println("closeEnv: myStore: " +
+ e.toString());
+ e.printStackTrace();
+ }
+ }
+
+ if (myEnv != null ) {
+ try {
+ myEnv.close();
+ } catch (DatabaseException e) {
+ System.err.println("closeEnv: " + e.toString());
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private TxnGuideDPL() {}
+
+ private static void parseArgs(String args[]) {
+ int nArgs = args.length;
+ for(int i = 0; i < args.length; ++i) {
+ if (args[i].startsWith("-")) {
+ switch(args[i].charAt(1)) {
+ case 'h':
+ if (i < nArgs - 1) {
+ myEnvPath = new String(args[++i]);
+ }
+ break;
+ default:
+ usage();
+ }
+ }
+ }
+ }
+}