Package de.huepattl.playground.berkeleydb

Source Code of de.huepattl.playground.berkeleydb.AdvancedPersistenceTest

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.Person;
import java.util.Date;
import java.time.LocalDate;
import java.time.Month;
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.*;

/**
* Some more advanced persistence showcases demonstrating related entities etc.
*
* @author Timo Boewing (bjblazko@gmail.com)
* @see SimplePersistenceTest
* @see SearchMethodsTest
* @since 2013-04-29
*/
public class AdvancedPersistenceTest {

    Logger LOG = LogManager.getLogger(AdvancedPersistenceTest.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 com.sleepycat.je.EnvironmentConfig
     * @see com.sleepycat.je.Environment
     * @see com.sleepycat.persist.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);
        this.entityStore.setSequenceConfig("ID", sequenceConfig);
    }

    /**
     * Just the verify it is working, this is code similar to
     * {@link de.huepattl.playground.berkeleydb.SimplePersistenceTest#simplePersistence()}.
     *
     * @throws Exception Arrrr...
     * @see #setupDatabase()
     */
    @Test
    public void simplePersistence() throws Exception {
        Person person;
        PrimaryIndex<Long, Person> primaryIndex = entityStore.getPrimaryIndex(Long.class, Person.class);

        person = new Person("Doe", "John");
        // Birthday: Dec 31st 1977
        person.setDateOfBirth(new Date(java.sql.Date.valueOf(LocalDate.of(1977, Month.DECEMBER, 9)).getTime()));
        primaryIndex.put(person);
        person = primaryIndex.get(person.getId());
        LOG.info(person);

        assertNotNull(person);
    }

    /**
     * Entity relations are always expressed through ID references, so not direct references. Probably, this demands
     * for a seperate design of domain model classes and persistence entities because you most likely want to express
     * such relations differently in your business code.<p>
     * In your entity models, relations are built by using the {@link com.sleepycat.persist.model.SecondaryKey}
     * annotation. Just have a look at the {@link Person} entity.
     */
    @Test
    public void relations() {
        final long id;
        Person person;
        Person friendA;
        Person friendB;
        Person friendC;

        PrimaryIndex<Long, Person> primaryIndex = entityStore.getPrimaryIndex(Long.class, Person.class);

        /*
        Set up test data: one guy (John Doe) and three friends: Alfred, Berta and Charles.
         */
        {
            person = new Person("Doe", "John");
            friendA = new Person("Friend", "Alfred");
            friendB = new Person("Friend", "Bertha");
            friendC = new Person("Friend", "Charles");
        }

        /*
        Persist everything. First, we store the dependencies (the friends), then we save the main
        persons referencing these friends.
         */
        {
            primaryIndex.put(friendA);
            primaryIndex.put(friendB);
            primaryIndex.put(friendC);
            LOG.info("Friends (not yet related): " + friendA + ", " + friendB + ", " + friendC);
            person.addFriend(friendA.getId());
            person.addFriend(friendB.getId());
            person.addFriend(friendC.getId());
            primaryIndex.put(person);
            id = person.getId();
        }

        /*
        Let us see if everything was stored...
         */
        {
            person = primaryIndex.get(id);
            LOG.info(person + ", has friends with IDs: " + person.getFriends());
            for (final long friendId : person.getFriends()) {
                final Person friend = primaryIndex.get(friendId);
                LOG.info("-> " + friend);
            }
        }
    }

    /**
     * Showcases the creation of some entities that are reference in other entities. When the entity is deleted, all
     * references should be removed as well. This can be achieved by using the {@link
     * com.sleepycat.persist.model.DeleteAction#CASCADE} option of the {@link com.sleepycat.persist.model.SecondaryKey}
     * annotation.
     */
    @Test
    public void deleteAndCascade() {
        final long friendToDeleteId;
        Person person;
        Person friendA;
        Person friendB;

        PrimaryIndex<Long, Person> primaryIndex = entityStore.getPrimaryIndex(Long.class, Person.class);

        /*
        Set up test data: one guy (John Doe) and two friends: Alfred and Berta.
         */
        {
            person = new Person("Doe", "John");
            friendA = new Person("Friend", "Alfred");
            friendB = new Person("Friend", "Bertha");
        }

        /*
        Persist.
         */
        {
            primaryIndex.put(friendA);
            friendToDeleteId = friendA.getId(); // remind ID (Alfred)
            primaryIndex.put(friendB);

            person.addFriend(friendA.getId());
            person.addFriend(friendB.getId());
            primaryIndex.put(person);
        }

        /*
        Now, let us delete a friend entity and see if it was also removed from the friend
        list (remember: we annotated the property so that deletions are cascaded through
        all usages - otherwise an exception would be thrown. Funnily, the correct annotation
        attribute is NULLIFY instead if CASCADE - seems that CASCADE would delete entities
        that just reference the deleted entity - quite strange...
         */
        {
            if (primaryIndex.delete(friendToDeleteId)) {
                LOG.info("Deleted entity with ID=" + friendToDeleteId);
                assertNull(primaryIndex.get(friendToDeleteId));
                /*
                   Ok, entity deleted - but what about the reference in friends list?
                   Reload person, iterate all friends and see that the ID of the deleted
                   one is not present any longer.
                 */
                person = primaryIndex.get(person.getId());
                for (final long friendId : person.getFriends()) {
                    assertNotEquals(friendToDeleteId, friendId);
                }
            } else {
                LOG.error("Failed to delete an entity...");
            }
        }
    }

}
TOP

Related Classes of de.huepattl.playground.berkeleydb.AdvancedPersistenceTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.