package de.huepattl.playground.berkeleydb;
import com.sleepycat.je.Environment;
import com.sleepycat.je.EnvironmentConfig;
import com.sleepycat.je.SequenceConfig;
import com.sleepycat.persist.EntityStore;
import com.sleepycat.persist.PrimaryIndex;
import com.sleepycat.persist.StoreConfig;
import de.huepattl.playground.berkeleydb.domain.model.Contacts;
import de.huepattl.playground.berkeleydb.domain.model.SimplePerson;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
/**
* Simple examples showing how to deal with the Berkeley DB (JE - Java Edition). We will only deal with entities
* (annotated JavaBeans/POJOs) and will not use BDB with the original simple API.
* <p>
* We use this JUnit test for demonstration purposes. Just execute one or all test methods in your IDE of choice or use
* Maven on the console: {@code mvn test -Dtest=SimplePersistenceTest}.
*
* @author Timo Boewing (bjblazko@gmail.com)
* @see AdvancedPersistenceTest
* @see SearchMethodsTest
* @since 2013-04-24
*/
public class SimplePersistenceTest {
Logger LOG = LogManager.getLogger(SimplePersistenceTest.class.getName());
/**
* Takes care of allocating a temporary folder and cleaning it up after test execution.
* If you need to have a look at the data in this location, you need to set a breakpoint
* and run as debug.
*/
@Rule
public TemporaryFolder dbLocation = new TemporaryFolder();
/**
* Our persistence store. This is a JE specific feature that not exists in the non-JE Berkeley DB.
*/
private EntityStore entityStore;
/**
* Executed before test: bootstrap our database.
*
* @see EnvironmentConfig
* @see Environment
* @see StoreConfig
*/
@Before
public void setupDatabase() {
/*
* Create default database environment. You might configure stuff like locking behaviour,
* caching, recovery etc.
*/
EnvironmentConfig environmentConfig = new EnvironmentConfig();
environmentConfig.setAllowCreate(true); // create if not exists
/*
* The database environment itself. You can, for example, use this instance to get
* statistics on current transactions etc.
*/
Environment environment = new Environment(dbLocation.getRoot(), environmentConfig);
LOG.info("Using DB location: " + dbLocation.getRoot().getAbsolutePath());
/*
* Configure and create the entity-related store. It is thread-safe and handles entity handling.
*/
StoreConfig storeConfig = new StoreConfig();
storeConfig.setAllowCreate(true);
this.entityStore = new EntityStore(environment, "testDatabase", storeConfig);
SequenceConfig sequenceConfig = new SequenceConfig();
sequenceConfig.setAllowCreate(true);
sequenceConfig.setInitialValue(1);
/*
* Define a named sequence: entities that define this sequence by named using the
* PrimaryKey annotation will receive auto-named values for their unique identity (ID).
*/
this.entityStore.setSequenceConfig("ID", sequenceConfig);
}
/**
* Perform the most simple persistence: create entity object, persist, clear, retrieve
* and compare for equality. Berkeley DB (JE) will auto-assign a new ID for the entity ({@link
* de.huepattl.playground.berkeleydb.domain.model.SimplePerson#getId()}).
* The object to persist ({@link de.huepattl.playground.berkeleydb.domain.model.SimplePerson}) requires to have the
* {@link com.sleepycat.persist.model.Entity}
* annotation
* marking it as a top-level object to be persisted having a unique identifier.
*
* @throws Exception Arrrr...
* @see #persistWithSubobjects()
* @see #setupDatabase()
*/
@Test
public void simplePersistence() throws Exception {
SimplePerson personToPersist;
SimplePerson personFromDatabase;
/*
* The index is our persistence interface. It is described by the primary key data type (long),
* which refers to the ID entity, and the entity type itself.
*/
PrimaryIndex<Long, SimplePerson> primaryIndex;
/*
* Create example entity. Please have a look at that class and pay attention to its annotations
* that are required for that entity in order to be persisted and retrieved.
* Note that we do NOT specify the identifier (ID).
*/
{
personToPersist = new SimplePerson();
personToPersist.setLastName("Doe");
personToPersist.setFirstName("John");
}
/*
* All entities are identified by their primary key (ID). Therefore we create a
* typed index and persis the object. By using put() instead of putNoReturn(),
* the passed entity will be updated accordingly.
* A bit strange: out() also returns the entity in case of UPDATE, but it will
* be NULL for INSERT. FIXME
*/
{
primaryIndex = entityStore.getPrimaryIndex(Long.class, SimplePerson.class);
LOG.info("Object BEFORE persisting: " + personToPersist.toString());
primaryIndex.put(personToPersist);
LOG.info("Object AFTER persisting: " + personToPersist.toString()
+ " (now with ID!");
}
/*
* Retrieve object from database and compare if it equals the original one.
* We use the ID from the original update (put() returned the updated entity
* with the ID that we can use here...).
*/
{
final long id = personToPersist.getId();
personFromDatabase = primaryIndex.get(id);
assertNotNull(personFromDatabase);
LOG.info("Object retrieved from store: " + personFromDatabase.toString());
assertEquals(personToPersist.getLastName(), personFromDatabase.getLastName());
assertEquals(personToPersist.getFirstName(), personFromDatabase.getFirstName());
}
}
/**
* This show case demonstrates how to persist an entity with custom sub-objects that are not entities on their own.
* In this case we store a {@link de.huepattl.playground.berkeleydb.domain.model.SimplePerson} entity with an
* inherited address ({@link Contacts}). {@link de.huepattl.playground.berkeleydb.domain.model.SimplePerson} is
* the owning entity and the {@link de.huepattl.playground.berkeleydb.domain.model.SimplePerson#getContacts()} is a
* 1:1
* object being persisted in the domain of its parent (dependent object).
*
* @throws Exception BAM!
*/
@Test
public void persistWithSubobjects() throws Exception {
PrimaryIndex<Long, SimplePerson> primaryIndex = entityStore.getPrimaryIndex(Long.class, SimplePerson.class);
SimplePerson personToPersist;
SimplePerson person;
/*
* Create person object with owned contacts object.
*/
{
Contacts contacts;
contacts = new Contacts();
contacts.setMobilePhone("+555-1234");
contacts.setPhone("+555-2345");
contacts.setEmail("johndoe@example.com");
contacts.setStreet("Middle-Of-Nowhere 231");
contacts.setCity("Shell Beach");
contacts.setZip("101");
personToPersist = new SimplePerson("Doe", "John", contacts);
}
/*
* Persist and log/show updated object.
*/
LOG.info("Object to persist: " + personToPersist + ", " + personToPersist.getContacts());
primaryIndex.put(personToPersist);
person = primaryIndex.get(personToPersist.getId());
LOG.info("Object retrieved from store: " + person + ", " + person.getContacts());
}
}