jEasyORM is a Java-based ORM/DAO tool with the following features:
Full functionality is currently supported for the following databases:
jEasyORM works using a java.sql.Connection object. This means that it does not care about custom query languages (it uses plain SQL with placeholders, as PreparedStatement), connection pool handling, transaction handling, and so on. This also means it is very flexible, and can be integrated with any code that depends on JDBC (including code that already uses another ORM/DAO tool).
jEasyORM does not require explicit mappings from POJOs to database tables. As long as there is some sort of naming convention that relates database names to POJO names, jEasyORM will require no mappings. It can, however, be instructed to map Java classes and fields to specific database tables and columns using annotations.
jEasyORM requires no singletons, no ThreadLocal's, no global objects and no configuration files. It has no external dependencies. It has a very small, robust and straightforward codebase, which can be easily debugged in case you face an unforeseen problem.
You can download jEasyORM from Sourceforge.
A jEasyORM entity manager only requires a java.sql.Connection to be created:
EntityManager em = EntityManager.getInstance(conn);
jEasyORM can be used with any POJOs that can be mapped to a database table:
// insert a new object Person p = new Person("Joe", "Williams"); em.insert(p); // the id was automatically determined by auto-increment or a sequence: Long id = p.getId(); // update an object p.setFirstName("John"); em.update(p); // read from database p = em.load(Person.class, id); // delete em.delete(p);
To find objects in the database, use any of the finder methods:
// find a unique object, throw exception, when multiple results are returned Person p = em.findUnique(Person.class, "select * from person where first_name = ? and last_name = ?", "John", "Williams"); // find multiple objects: List<Person> people = em.find(Person.class, "select * from person where last_name = ? order by first_name", "Bush"); // ... or shorter: people = em.find(Person.class, "from person where last_name = ? order by first_name", "Bush"); // ... or even shorter: people = em.find(Person.class, "where last_name = ? order by first_name", "Bush"); // only get a few objects of a possible large number of objects (paging): int pageNumber = 27; int pageSize = 10; // the following will return records 270 to 279 in a list, // which additionally provides a totalSize Page<Person> page = em.find(Person.class, pageNumber, pageSize, "order by last_name, first_name"); int totalNumberOfPeople = page.totalSize();
If you are working with a large number of objects, you can also use an iterator:
Iterator<Person> it = em.iterator(Person.class, "order by last_name"); while (it.hasNext()) { Person p = it.next(); ... }
You can also return native objects:
// find the number of objects: int count2 = em.findUnique(int.class, "select count(*) from person"); // ... or shorter int count = em.count("from person"); // get multiple native objects: List<String> first_names = em.find(String.class, "select distinct first_name from person where last_name = ?", "Doe");
Finally you can just execute other statements:
int numAffected = em.execute("delete from person where first_name = ?", "Meier");
Mapping POJOs to tables and mapping fields to columns is done with a name guesser.
E.g. the following POJO
public class NicePerson { private Long id; private String firstName; private String lastName; private String notes; private byte[] picture; ... }
will by default map to a table named NICEPERSON, NICE_PERSON, TNICEPERSON or TNICE_PERSON.
The field firstName will by default map to a column named FIRSTNAME or FIRST_NAME.
Of course it is easy to change the algorithm by providing a custom name guesser:
EntityManager em = EntityManager.getInstance(conn); em.setNameGuesser(new NameGuesser() { public String[] guessTableName(Class<?> entityClass) { return new String[] { "TABLE_" + entityClass.getSimpleName().toUpperCase() }; } public String[] guessColumnName(Class<?> entityClass, String field) { return new String[] { "COL_" + field.toUpperCase(); }; } });
You can also annotate POJOs and fields to specify database table and column names:
@Table(schema="TEST", name="PERSON") public class AnnotatedPerson { @Column(name="NAME") private String lastName; ... }
POJOs are mapped the first time they are used in an EntityManager method. POJOs annotated with @Transient are not mapped to tables, but can only be used as result of finders. Fields annotated with @Transient are also not mapped.
@Transient public class Helper { private f1; ... } public class OtherPerson { private Long id; private String firstName; private String lastName; @Transient private String name; @Transient public String getFullName() { if (name == null) name = firstName + " " + lastName; return name; } ... }
If more than one connection is used, you have to specify a name, when getting a EntityManager instance to account for possibly different mappings:
Connection mysqlConn = ... Connection oracleConn = ... EntityManager mysqlEm = EntityManager.getInstance("mysql", mysqlConn); EntityManager oracleEm = EntityManager.getInstance("oracle", oracleConn); // copying persons from MySQL to Oracle: Iterator<Person> it = mysqlEm.iterator(Person.class, "order by last_name"); while (it.hasNext()) { Person p = it.next(); oracleEm.insert(p); }
You create your database tables with normal create table scripts.
You have to ensure the following:
jEasyORM | Persist | Ammentos | SeQuaLite | |
---|---|---|---|---|
Configurationless | Y | Y | N 1 | N 2 |
Use of any POJO | Y | Y | Y 1 | Y 3 |
Database independent | Y | Y | Y | |
Automatically use auto-increment or sequence for primary keys on insert | Y | N | Y | N 2 |
Database-independent paging | Y | N | N | Y |
Cascaded load/save | N | N | Y | Y 3 |
Custom query language/API | N | N | Y | Y |
Transaction management | N | N | Y | N |
Automatic table creation | N | N | N | N |
No external dependencies | Y | Y | Y | Y |
Small (less than 100kB) | Y (40kB) | Y (30kB) | N (110kB) | Y (75kB) |
Tested with | ||||
DB2 | N | Y | ||
Derby | Y | Y | ||
H2 | Y | Y | ||
HSQLDB | Y | Y | ||
MySQL | Y | Y | ||
Oracle | Y | Y | ||
PostgreSQL | Y | Y | ||
SQL Server | N | Y |
Remarks: