3

(I already saw this problem somewhere online but a search query that depends on "100" as search term apparently isn't a promising one - so forgive me if this question has already been asked)

I've just started playing with berkeley DB in Java using its DPL feature. I created a Class "Client" which has the following primary key and sequence:

public class Client {

    // primary key
    @PrimaryKey(sequence="Client_ID")
    private long id;
[...]
}

I'm adding a few sample Entities using the primary index:

clientById = store.getPrimaryIndex(Long.class, Client.class);
clientById.put(client);

The first time I'm starting the application, everything's ok. The sequence starts at 1 and increase by 1. The next time I start the application, it starts at 101 (stepping is still 1) instead of continnuing at 4 (I have 3 sample Entities). Is it possible to affect this behaviour somehow? I'd like to have an ongoing sequence.

Edit: This is my testcode:

public static void main(String[] args) {
        test();
        test();

    }

    public static void test() {
        // create some test clients
        Client c1 = new Client("Client 1", "Cli 1 street 1", null, "55411", "Bingen");
        Client c2 = new Client("Client 2", "Cli 1 street 2", null, "55411", "Bingen");
        Client c3 = new Client("Test Custoamer");

        // create database
        Store store = new Store();
        ClientAccessor ca = new ClientAccessor(store.getStore());

        ca.put(c1);
        ca.put(c2);
        ca.put(c3);

        List<Client> clients = ca.getAll();
        for (Client c : clients) {
            System.out.println(c);
            System.out.println("-------------------");
        }

        store.shutdown();
    }

Store looks like this:

public class Store {
    private File dbfile;
    private Environment env;
    private EntityStore store;

    public Store() {
        this(new File(System.getProperty("user.home"), "tmdb"));
    }

    public Store(File dbfile) {
        this.dbfile = dbfile;
        setup();
    }


    public void setup() {
        EnvironmentConfig envConfig = new EnvironmentConfig();
        envConfig.setAllowCreate(true);
        envConfig.setTransactional(true);
        env = new Environment(dbfile, envConfig);

        StoreConfig storeConfig = new StoreConfig();
        storeConfig.setAllowCreate(true);
        storeConfig.setTransactional(true);
        store = new EntityStore(env, "TimeManagement", storeConfig);

    }

    public void shutdown() {
        store.close();
        env.close();
    }


    public EntityStore getStore() {
        return store;
    }
}

ClientAccessor goes like this:

public class ClientAccessor {
    private EntityStore store;

    // primary index
    PrimaryIndex<Long, Client> clientById;


    public ClientAccessor(EntityStore store) {
        this.store = store;
        if (store == null)
            throw new IllegalArgumentException("EntityStore can't be null!");
        clientById = store.getPrimaryIndex(Long.class, Client.class);
    }

    public void put(Client c) {
        clientById.put(c);
    }

    public List<Client> getAll() {
        ArrayList<Client> clients = new ArrayList<Client>();
        EntityCursor<Client> cursor = clientById.entities();

        for (Client c : cursor) {
            clients.add(c);
        }

        cursor.close();

        return clients;
    }


}

And the client looks like this:

@Entity
public class Client {

    // primary key
    @PrimaryKey(sequence="Client_ID")
    private long id;

    // secondary keys
    @SecondaryKey(relate=Relationship.MANY_TO_ONE)
    private String name;
    @SecondaryKey(relate=Relationship.MANY_TO_ONE)
    private String address1;
    @SecondaryKey(relate=Relationship.MANY_TO_ONE)
    private String address2;
    @SecondaryKey(relate=Relationship.MANY_TO_ONE)
    private String plz;
    @SecondaryKey(relate=Relationship.MANY_TO_ONE)
    private String city;

    private Client(){}

    // address is optional
    public Client(String name) {
        this(name, null, null, null, null);
    }

    public Client(String name, String address1, String address2, String plz, String city) {
        this.setName(name);
        this.setAddress1(address1);
        this.setAddress2(address2);
        this.setPlz(plz);
        this.setCity(city);
    }

    @Override
    public String toString() {
        String str = "";
        str += id + "\n";
        str += name + "\n";
        str += (address1 != null && ! address1.isEmpty()) ? address1 + "\n" : "";
        str += (address2 != null && ! address2.isEmpty()) ? address2 + "\n" : "";
        str += (plz != null && ! plz.isEmpty()) ? plz + " " : "";
        str += (city != null &&! city.isEmpty()) ? city + "\n" : "";

        return str;
    }


    // getters and setters

    public long getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddress1() {
        return address1;
    }

    public void setAddress1(String address1) {
        this.address1 = address1;
    }

    public String getAddress2() {
        return address2;
    }

    public void setAddress2(String address2) {
        this.address2 = address2;
    }

    public String getPlz() {
        return plz;
    }

    public void setPlz(String plz) {
        this.plz = plz;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }
}
wullxz
  • 17,830
  • 8
  • 32
  • 51
  • Can you dump the contents of the BDB after the first time you run the application? Perhaps something in your application is reserving space for 100 records in the DB and then only filling 3 of them. – dg99 Jul 18 '14 at 23:08
  • Are you properly calling `close` on the `EntityStore`? It's likely ids are allocated to threads in blocks to reduce synchronization costs. `close` ought to record unused parts of the block. – Gene Jul 20 '14 at 04:04
  • I indeed forgot to close the EntityStore but fixed that now. Nevertheless that behaviour persists. I even moved my testcode into a dedicated test method and called that twice in the main() method with the same results as running the program twice. I'll add that code to my question... – wullxz Aug 15 '14 at 05:03

1 Answers1

3

By default, the sequence caches 100 entries. To change this, add this code to the end of your Store.setup() method:

    SequenceConfig sequenceConfig = store.getSequenceConfig("Client_ID");
    sequenceConfig.setCacheSize(1);
    store.setSequenceConfig("Client_ID", sequenceConfig);
Richard Neish
  • 8,414
  • 4
  • 39
  • 69
  • Just a note that this worked on the latest version, 6.1.5, but the setSequenceConfig() method was not available on an earlier version 5.0.73 – Richard Neish Aug 21 '14 at 21:36
  • thanks! that solved it! do you also have an idea how to set this for all sequences to come by default? – wullxz Aug 24 '14 at 01:27