Created
September 5, 2012 09:46
-
-
Save hastebrot/3634242 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package sscce; | |
import java.util.ArrayList; | |
import java.util.List; | |
import javax.persistence.Entity; | |
import javax.persistence.Id; | |
import com.avaje.ebean.EbeanServer; | |
import com.avaje.ebean.EbeanServerFactory; | |
import com.avaje.ebean.Query; | |
import com.avaje.ebean.QueryIterator; | |
import com.avaje.ebean.config.AutofetchConfig; | |
import com.avaje.ebean.config.DataSourceConfig; | |
import com.avaje.ebean.config.ServerConfig; | |
import com.avaje.ebeaninternal.server.core.DefaultServer; | |
import com.avaje.ebeaninternal.server.ddl.DdlGenerator; | |
/** | |
* <h1>Simple Database Service with Ebean ORM</h1> | |
* | |
* <p>This Short, Self Contained, Correct Example (SSCCE) shows three pitfalls I | |
* stumpled upon. | |
* | |
* <p><b>Required Libraries:</b> ebean-2.7.4.jar, h2-1.3.164.jar, persistence-api-1.0.jar, | |
* servlet-api-2.5.jar. | |
* | |
* <h2>Pitfall #1: Used special characters in the name of ServerConfig</h2> | |
* | |
* <pre> | |
* WRONG: | |
* this.serverConfig.setName("h2:mem:ebean"); | |
* this.serverConfig.setName("h2.mem.ebean"); | |
* | |
* RIGHT: | |
* this.serverConfig.setName(this.sluggifyText("h2:mem:ebean")); | |
* </pre> | |
* | |
* <h2>Pitfall #2: Forgot to implement getters and setters in the entity bean</h2> | |
* | |
* <pre> | |
* WRONG: | |
* france.capitalName = "Paris"; | |
* System.out.println(france.capitalName); | |
* this.ebeanServer.insert(france); | |
* | |
* RIGHT: | |
* france.setCapitalName("Paris"); | |
* System.out.println(france.getCapitalName()); | |
* this.ebeanServer.insert(france); | |
* </pre> | |
* | |
* <h2>Pitfall #3. Connection in QueryIterator wasn't closed</h2> | |
* | |
* <pre> | |
* WRONG: | |
* QueryIterator<Country> queryIterator = query.findIterate(); | |
* | |
* RIGHT: | |
* QueryIterator<Country> queryIterator = query.findIterate(); | |
* queryIterator.close(); | |
* </pre> | |
*/ | |
public class SimpleEbeanService { | |
//----------------------------------------------------------------------------------- | |
// MAIN METHOD. | |
//----------------------------------------------------------------------------------- | |
public static void main(String[] args) { | |
SimpleEbeanService service = new SimpleEbeanService(); | |
System.out.println("Initializing database..."); | |
service.addEntityClass(Country.class); | |
service.initDataSourceConfig(); | |
service.initAutofetchConfig(); | |
service.initServerConfig(); | |
System.out.println("Connecting to database..."); | |
service.initEbeanServer(); | |
System.out.println("Running queries..."); | |
service.runCreateTableQueries(); | |
service.runInsertDatasetQuery(); | |
service.runSelectDatasetQueries(); | |
} | |
//----------------------------------------------------------------------------------- | |
// PUBLIC FIELDS. | |
//----------------------------------------------------------------------------------- | |
public int maxConnections = 5; | |
public int numberOfQueries = 20; | |
public List<Class<?>> entityClasses = new ArrayList<Class<?>>(); | |
public DataSourceConfig dataSourceConfig; | |
public AutofetchConfig autofetchConfig; | |
public ServerConfig serverConfig; | |
public EbeanServer ebeanServer; | |
//----------------------------------------------------------------------------------- | |
// PUBLIC METHODS. | |
//----------------------------------------------------------------------------------- | |
public void addEntityClass(Class<?> entityClass) { | |
this.entityClasses.add(entityClass); | |
} | |
public void initDataSourceConfig() { | |
this.dataSourceConfig = new DataSourceConfig(); | |
this.dataSourceConfig.setDriver("org.h2.Driver"); | |
this.dataSourceConfig.setUrl("jdbc:h2:mem:ebean"); | |
this.dataSourceConfig.setUsername("sa"); | |
this.dataSourceConfig.setPassword(""); | |
this.dataSourceConfig.setMaxConnections(this.maxConnections); | |
} | |
public void initAutofetchConfig() { | |
this.autofetchConfig = new AutofetchConfig(); | |
this.autofetchConfig.setUseFileLogging(false); | |
this.autofetchConfig.setLogDirectory("."); | |
} | |
public void initServerConfig() { | |
this.serverConfig = new ServerConfig(); | |
this.serverConfig.setLoggingToJavaLogger(true); | |
this.serverConfig.setLoggingDirectory("."); | |
this.serverConfig.setDataSourceConfig(this.dataSourceConfig); | |
this.serverConfig.setAutofetchConfig(this.autofetchConfig); | |
// PITFALL #1: | |
// javax.management.MalformedObjectNameException: Invalid character ':' in | |
// value part of property | |
//this.serverConfig.setName("h2:mem:ebean"); | |
// PITFALL #1: | |
// java.lang.ClassFormatError: Illegal class name "sscce/SimpleEbeanService | |
// $Country$$EntityBean$h2.mem.ebean" in class file sscce/SimpleEbeanService | |
// $Country$$EntityBean$h2/mem/ebean | |
//this.serverConfig.setName("h2.mem.ebean"); | |
this.serverConfig.setName(this.sluggifyText("h2:mem:ebean")); | |
this.serverConfig.setRegister(false); | |
this.serverConfig.setDefaultServer(false); | |
this.serverConfig.setClasses(this.entityClasses); | |
this.serverConfig.setDdlGenerate(false); | |
this.serverConfig.setDdlRun(false); | |
} | |
public void initEbeanServer() { | |
this.ebeanServer = EbeanServerFactory.create(this.serverConfig); | |
} | |
public void runCreateTableQueries() { | |
DdlGenerator generator = ((DefaultServer) this.ebeanServer).getDdlGenerator(); | |
generator.runScript(true, generator.generateDropDdl()); | |
generator.runScript(false, generator.generateCreateDdl()); | |
} | |
public void runInsertDatasetQuery() { | |
Country france = new Country(); | |
france.setName("France"); | |
france.setCapitalName("Paris"); | |
// PITFALL #2: | |
// Exception in thread "main" java.lang.RuntimeException: get id on [sscce. | |
// SimpleEbeanService$Country] type[sscce.SimpleEbeanService$Country] threw error. | |
this.ebeanServer.insert(france); | |
} | |
public void runSelectDatasetQueries() { | |
for (int index = 0; index < this.numberOfQueries; index += 1) { | |
Query<Country> query = this.ebeanServer.createQuery(Country.class) | |
.select("name, capitalName").where().eq("name", "France").query(); | |
QueryIterator<Country> queryIterator = query.findIterate(); | |
try { | |
while (queryIterator.hasNext()) { | |
Country country = queryIterator.next(); | |
System.out.println(country); | |
} | |
} | |
finally { | |
// PITFALL #3: | |
// Exception in thread "main" javax.persistence.PersistenceException: | |
// java.sql.SQLException: Unsuccessfully waited [1000] millis for a | |
// connection to be returned. No connections are free. You need to | |
// Increase the max connections of [5] or look for a connection pool | |
// leak using datasource.xxx.capturestacktrace=true | |
queryIterator.close(); | |
} | |
} | |
} | |
//----------------------------------------------------------------------------------- | |
// PRIVATE METHODS. | |
//----------------------------------------------------------------------------------- | |
private String sluggifyText(String text) { | |
text = text.toLowerCase(); | |
text = text.replaceAll("[^a-z0-9]+", "_"); | |
text = text.replaceAll("_$|^_", ""); | |
return text; | |
} | |
//----------------------------------------------------------------------------------- | |
// PUBLIC CLASSES. | |
//----------------------------------------------------------------------------------- | |
@Entity | |
public static class Country { | |
private @Id Integer id; | |
private String name; | |
private String capitalName; | |
public Integer getId() { return id; } | |
public void setId(Integer id) { this.id = id; } | |
public String getName() { return name; } | |
public void setName(String name) { this.name = name; } | |
public String getCapitalName() { return capitalName; } | |
public void setCapitalName(String capitalName) { this.capitalName = capitalName; } | |
public String toString() { | |
return "<Country name='" + this.name + "' " + | |
"capitalName='" + this.capitalName + "'>"; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment