jEasyORM User Guide

Table of Contents

  1. Introduction
  2. Download
  3. Quickstart
  4. Mapping
  5. Set up database
  6. Comparison with other ORMs


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");
    // the id was automatically determined by auto-increment or a sequence:
    Long id = p.getId();

    // update an object

    // read from database
    p = em.load(Person.class, id);

    // delete

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", 
    // ... 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 =;

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.

    public class Helper {
      private f1;

    public class OtherPerson {

      private Long id;
      private String firstName;
      private String lastName;
      @Transient private String name;

      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 =;

Set up database

You create your database tables with normal create table scripts.

You have to ensure the following:

Comparison with other ORMs

jEasyORM Persist Ammentos SeQuaLite
ConfigurationlessYYN 1N 2
Use of any POJOYYY 1Y 3
Database independentYYY
Automatically use auto-increment or sequence for primary keys on insertYNYN 2
Database-independent pagingYNNY
Cascaded load/saveNNYY 3
Custom query language/APINNYY
Transaction managementNNYN
Automatic table creationNNNN
No external dependenciesYYYY
Small (less than 100kB)Y (40kB)Y (30kB)N (110kB)Y (75kB)
Tested with
SQL ServerNY


  1. POJOs need to be annotated
  2. XML configuration required
  3. Lazy loading only supported, when extending class SeQuaLiteModel