Search code examples
javaormderbyebean

ebean .save() not returning identity column value


I've been stuck on the following for a while, and would appreciate any help/hints.

My application is using ebeans and a derby db. It has all been setup and working fine, however, i'm finding that when i use the Ebean.save(object) method, the object's id field (which is autogenerated by derby) is not being added to the object.

The following is my model class:

@Entity
@Table(name="GAME.Resource")
public class Resource {

@Id
private Long oid;

@Version
private Integer version;

private String name;

private String description;

@Column(name = "spaceRequired")
private Integer spaceRequired;

I have a simple test helper class at the moment creating a random resource and calling the save method:

public static Resource createResource() {
    Resource resource = new Resource();
    resource.setDescription(RandomStringUtils.randomAlphabetic(100));
    resource.setName(RandomStringUtils.randomAlphabetic(20));
    resource.setSpaceRequired(Integer.valueOf(RandomStringUtils.randomNumeric(3)));
    Ebean.save(resource);
    return resource;
}

my ebean.properties file is like so:

# specify jars to search for entity beans  
ebean.search.jars=engine-0.0.1-SNAPSHOT.jar

# -------------------------------------------------------------  
# Load (Dev/Test/Prod) properties external to your war/jar  
# -------------------------------------------------------------  
# You can use load.properties to load the properties from a  
# file external to your war/jar.   
#load.properties.override=${CATALINA_HOME}/conf/myapp.ebean.properties  


ebean.ddl.generate=false  
ebean.ddl.run=false  

ebean.debug.sql=true  
ebean.debug.lazyload=false  


# -------------------------------------------------------------  
# Transaction Logging  
# -------------------------------------------------------------  

# Use java util logging to log transaction details  
#ebean.loggingToJavaLogger=true  

# General logging level: (none, explicit, all)  
ebean.logging=all  

# Sharing log files: (none, explicit, all)  
ebean.logging.logfilesharing=all  

# location of transaction logs   
ebean.logging.directory=logs  
#ebean.logging.directory=${catalina.base}/logs/trans  

# Specific Log levels (none, summary, binding, sql)  
ebean.logging.iud=sql  
ebean.logging.query=sql  
ebean.logging.sqlquery=sql  

ebean.logging.txnCommit=none  

# -------------------------------------------------------------  
# DataSources (If using default Ebean DataSourceFactory)  
# -------------------------------------------------------------   
# You can specify many DataSources (one per EbeanServer)  and   
# one of them is defined as the default/primary DataSource  

# specify the default/primary DataSource  
datasource.default=derby  

datasource.derby.username=
datasource.derby.password=
datasource.derby.databaseUrl=jdbc:derby:/home/ali/dev/servers/derby-db/game/;  
datasource.derby.databaseDriver=org.apache.derby.jdbc.ClientDriver
datasource.derby.minConnections=1  
datasource.derby.maxConnections=25  
datasource.derby.heartbeatsql=select 1  
datasource.derby.isolationlevel=read_committed  

If I do a debug on the test helper, after the save() is called, the resource object that was just saved does not get it's oid value inserted into it. When I inspect the database, I can see that it has successfully inserted a record.

In my research, I believe I need to set the generatedkeys property, so that ebeans knows that my database can handle that and will retrieve the generated value, but I cannot find anywhere a listing of properties that I can set in the ebean.properties file in order to do this.

Any help, directions would be much appreciated.

UPDATE 1: I'm sure that I am getting closer, the following from apache derby talks about how it allows the autogenerated keys: http://db.apache.org/derby/docs/10.7/ref/crefjavstateautogen.html

and then this from ebeans API is how you set ebeans so that it knows your DB can handle the auto generated keys: http://www.avaje.org/static/javadoc/pub/com/avaje/ebean/config/dbplatform/DbIdentity.html#setSupportsGetGeneratedKeys%28boolean%29

But I still can't find how to set that API method using the .properties file!

Update 2: I found this on the avaje site, which talks about adding lines to your system.properties file in order to set them. I assumed that the system.properties file is my ebean.properties file? I added the following two lines, still with no luck...

ebean.derby.supportsGetGeneratedKeys=true
ebean.derby.identityGeneration=identity

Update 3: The following SQL is being used to generate the table:

CREATE TABLE GAME.Resource (
oid BIGINT NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1),
version INTEGER NOT NULL,
name VARCHAR(255) NOT NULL,
description VARCHAR(511) NOT NULL,
spaceRequired INTEGER NOT NULL,
PRIMARY KEY(oid)
);

Solution

  • So i've finally got it working.

    I needed to create a programmatic implementation instead of using the ebean.properties file (i've totally removed that file now).

    My implementation is a simple class which you just have the init() method called by.. whatever you need (e.g. setup in a unit test, or as a spring bean if using spring).

    public class DatasourceConfig {
    
    /**
     * Setup info came from: http://www.avaje.org/ebean/getstarted_programmatic.html
     */
    public void init() {
        ServerConfig serverConfig = new ServerConfig();
        serverConfig.setName("derby");
    
        //Define datasource parameters
        DataSourceConfig derbyDb = new DataSourceConfig();  
        derbyDb.setDriver("org.apache.derby.jdbc.ClientDriver");  
        derbyDb.setUsername("");  
        derbyDb.setPassword("");  
        derbyDb.setUrl("jdbc:derby:/home/the_ox/dev/servers/derby-db/game/;");  
        derbyDb.setHeartbeatSql("select 1");  
        serverConfig.setDataSourceConfig(derbyDb);  
    
        // set DDL options...  
        serverConfig.setDdlGenerate(false);  
        serverConfig.setDdlRun(false);  
    
        serverConfig.setDefaultServer(true);
    
        //Setup derby specific identity 'stuff'.
        DatabasePlatform dbPlatform = new DatabasePlatform();
        dbPlatform.getDbIdentity().setIdType(IdType.IDENTITY);
        dbPlatform.getDbIdentity().setSupportsGetGeneratedKeys(true);
        dbPlatform.getDbIdentity().setSupportsSequence(false);
        dbPlatform.getDbIdentity().setSupportsIdentity(true);
        serverConfig.setDatabasePlatform(dbPlatform);
    
        //Specify jar to search for entity beans
        serverConfig.addJar("engine-0.0.1-SNAPSHOT.jar");
    
        // create the EbeanServer instance  
        EbeanServer server = EbeanServerFactory.create(serverConfig);  
    }
    
    }