Skip to content
Naoki Takezoe edited this page Nov 8, 2013 · 8 revisions

What's Mirage?

Mirage is an easy and powerful SQL centric database access library. It provides two main features below:

  • 2WaySQL

    The main feature of Mirage is 2WaySQL. This makes plain old SQL template, and it is executable using any SQL client tools because parameters and conditions are written as SQL comment.

  • SQL less Update

    Generally, update processing are simpler than search processing. However, especially, large INSERT SQL brings us the considerable pain. In the Mirage, you can insert / update / delete records using entity class (without SQL).

Quick Start

At first, see the Configuration to setup Mirage.

First example of Mirage

The basic example of searching using the SQL file. SqlManager is a main interface of Mirage. You can get it from Session and you can control transaction using Session also.

Session session = SessionFactory.getSession();
SqlManager sqlManager = session.getSqlManager();
session.begin();

try {
  BookParam param = new BookParam();

  List<Book> result = sqlManager.getResultList(
      Book.class, "/META-INF/selectBooks.sql", param);

  // ...

  session.commit();

} catch(Exception ex) {
  session.rollback();

} finally {
  session.release();
}

Book is a POJO to mapping ResultSet:

public class Book {
  public Long bookId;
  public String bookName;
  public String author;
  public Integer price;
}

BookParam is a parameter class:

public class BookParam {
  public String author;
  public Integer minPrice;
  public Integer maxPrice;
}

/META-INF/selectProducts.sql:

SELECT * FROM BOOK
/*BEGIN*/
  WHERE
  /*IF author != null */
        AUTHOR = /*author*/'Naoki Takezoe'
  /*END*/
  /*IF minPrice != null */
    AND PRICE >= /*minPrice*/20
  /*END*/
  /*IF maxPrice != null */
    AND PRICE <= /*maxPrice*/100
  /*END*/
/*END*/
ORDER BY BOOK_ID ASC

2WaySQL

Mirage supports 2WaySQL. This is based on Japanese O/R mapping framework S2JDBC. 2WaySQL is the plain old SQL template. You can specify parameters and conditions using SQL comment. So these SQLs are executable using SQL client tools.

For exmaple, the following SQL has a SQL comment(/*author*/), however it is executable as SQL.

SELECT * FROM BOOK
WHERE AUTHOR = /*author*/'Naoki Takezoe'
ORDER BY BOOK_ID ASC

Mirage replaces /*author*/ to a place holder and removes a word ('Naoki Takezoe') after replaced SQL comment. Actually, Mirage would execute the following SQL.

SELECT * FROM BOOK
WHERE AUTHOR = ?
ORDER BY BOOK_ID ASC

See 2WaySQL to know details about 2WaySQL.

SQL less Update

Mirage can insert / update / delete using entity object (without SQL file).

Entity Class must have a primary key field with @PrimaryKey annotation:

public class Book {
  @PrimaryKey(generationType=GenerationType.IDENTITY)
  public Long bookId;
  public String bookName;
  public String author;
  public Integer price;
}

You should specify the generation type of primary keys. Mirage supports following generation types:

  • GenerationType.APPLICATION

    Primary keys have to be set by the application before invocation of SqlManager#insertEntity().

@PrimaryKey(generationType=GenerationType.APPLICATION)
public Long id;
  • GenerationType.IDENTITY

    Primary keys are set by database automatically. Database have to support PreparedStatement.RETURN_GENERATED_KEYS to acquire generated keys. Oracle does not support this feature.

@PrimaryKey(generationType=GenerationType.IDENTITY)
public Long id;
  • GenerationType.SEQUENCE

    Primary keys are set by Mirage using sequence. In this strategy, you have to specify the sequence name at generator attribute of @PrimaryKey annotation.

@PrimaryKey(generationType=GenerationType.SEQUENCE, generator="USER_ID_SEQ")
public Long id;

Example to insert an entity using SqlManager#insertEntity():

Book book = new Book();
book.bookName = "Mirage in Action";
book.author = "Naoki Takezoe";
book.price = 20;

sqlManager.insertEntity(entity);

You can also select entity using SqlManager#findEntity().

Book book = sqlManager.findEntity(Book.class, bookId);

Please note that Mirage does not support relationship between entities because it may bring complexity into Mirage.

Iteration Search

SqlManager#getResultList() creates all entity instances and returns a list which contains them. If SQL returns a large result, it causes OutOfMemory.

In these case, you should use SqlManager#iterate() instead of SqlManager#getResultList().

Integer result = sqlManager.iterate(
    Book.class,
    new IterationCallback<Book, Integer>() {

      private int result;

      @Override public Integer iterate(Book entity) {
        result = result + entity.price;
        return result;
      }

    },
    SQL_PREFIX + "SqlManagerImplTest_selectBooks.sql");

SqlManager#iterate() accepts IterationCallback and invoke it per record. The return value of SqlManager#iterate() is a last returned value from IterationCallback.

If you want to break iteration search on the way, throw BreakIterationException from IterationCallback. By this exception, iteration search is stopped and SqlManager#iterate() returns the previous returned value from IterationCallback. If BreakIterationException is thrown at first IterationCallback#iterate() invocation, SqlManager#iterate() returns null.

Stored Procedure / Function

Mirage can call stored procedures / functions by database independed way.

  • SqlManager#call()

    Calls the procedure or the function which returns the single result.

  • SqlManager#callForList()

    Calls the function which returns the result list.

// Parameter class
public class GetCountParam {
  @In
  public long deptId;
}

// Creates parameter object which give to stored function
GetCountParam param = new GetCountParam();
param.deptId = 1;

// Calls a stored function and get a result value.
Long count = sqlManager.call(Long.class, "get_emp_count", param);

Fields of the parameter class has annotation such as @In, @Out, @InOut and @ResultSet. These annotations mean the parameter type.

  • The field has no annotation or it has @In annotation, it means the IN parameter.
  • The field has @Out annotation, it means the OUT parameter.
  • The field has @InOut annotation, it means the INOUT parameter.
  • The field has @ResultSet annotation, it's mapped to the result set which is not returned as a parameter. In the database which can return a result set as a parameter only such as Oracle or PostgreSQL, @ResultSet field means the OUT parameter.
Clone this wiki locally