ORMLiteの紹介

1概要

ORMLite は、Javaアプリケーション用の軽量ORMライブラリです。他のORMフレームワークの複雑さやオーバーヘッドを追加することなく、最も一般的なユースケースに合わせてORMツールの標準機能を提供します。

主な機能は次のとおりです。

  • Javaアノテーションを使用してエンティティクラスを定義する

  • 拡張可能な DAO クラス

  • 複雑なクエリを作成するための QueryBuilder クラス

  • データベーステーブルを作成および削除するための生成クラス

  • 取引のサポート

  • エンティティ関係のサポート

次のセクションでは、ライブラリの設定方法、エンティティクラスの定義方法、およびライブラリを使用したデータベースに対する操作の実行方法について説明します。

2 Mavenの依存関係

ORMLiteを使い始めるには、 ormlite-jdbc 依存関係を pom.xml に追加する必要があります。 :

<dependency>
    <groupId>com.j256.ormlite</groupId>
    <artifactId>ormlite-jdbc</artifactId>
    <version>5.0</version>
</dependency>

デフォルトでは、これはhttps://search.maven.org/classic/#search%7Cga%7C1%7Ca%3A%22h2%22%20AND%20g%3A%22com.h2database%22[ h2 ]依存関係も持ち込みます。 。この例では、 H2 インメモリデータベースを使用するので、別のJDBCドライバは必要ありません。

別のデータベースを使用したい場合は、対応する依存関係も必要になります。

3エンティティクラスの定義

ORMLiteを使用して永続化のためにモデルクラスを設定するために使用できる2つの主なアノテーションがあります。

エンティティクラスの** @ DatabaseTable

プロパティの** @ DatabaseField

まず、 name フィールドと、主キーでもある libraryId フィールドを使用して Library エンティティを定義することから始めましょう。

@DatabaseTable(tableName = "libraries")
public class Library {

    @DatabaseField(generatedId = true)
    private long libraryId;

    @DatabaseField(canBeNull = false)
    private String name;

    public Library() {
    }

   //standard getters, setters
}

@ DatabaseTable アノテーションには、デフォルトのクラス名に依存したくない場合にテーブルの名前を指定するオプションの tableName 属性があります。

  • データベーステーブルの列として永続化したいフィールドごとに、 @ DatabaseField アノテーションを追加する必要があります。

テーブルの主キーとして機能するプロパティは、 id generatedId 、または generatedSequence 属性のいずれかでマークできます。この例では、主キーが自動的にインクリメントされるように generatedId = true 属性を選択します。

また、クラスには少なくとも package-scope の可視性を持つ引数のないコンストラクタが必要です。

私たちがフィールドを設定するために使用できる他のいくつかのよく知られた属性は columnName dataType defaultValue canBeNull unique です。

3.1. JPA アノテーションを使う

ORMLite固有のアノテーションに加えて、** JPAスタイルのアノテーションを使ってエンティティを定義することもできます。

JPA 標準アノテーションを使用する前に定義した Library エンティティの同等物は次のようになります。

@Entity
public class LibraryJPA {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long libraryId;

    @Column
    private String name;

   //standard getters, setters
}

ORMLiteはこれらのアノテーションを認識しますが、 javax.persistence-api を追加する必要がありますそれらを使用するための依存関係。

サポートされている JPA アノテーションの完全なリストは@ Entity @ Id、 @ Column、 @ GeneratedValue、 @ OneToOne @ ManyToOne、 @ JoinColumn 、@ Version です。

4 ConnectionSource

定義されたオブジェクトを操作するには、 ConnectionSource ** を設定する必要があります。

これには、単一の接続を作成する JdbcConnectionSource クラス、または単純なプール接続ソースを表す JdbcPooledConnectionSource を使用できます。

JdbcPooledConnectionSource connectionSource
  = new JdbcPooledConnectionSource("jdbc:h2:mem:myDb");
//work with the connectionSource

connectionSource.close();

パフォーマンスの良い他の外部データソースも、それらを DataSourceConnectionSource オブジェクトにラップすることで使用できます。

5 TableUtils クラス

ConnectionSource に基づいて TableUtils クラスの静的メソッドを使用してデータベーススキーマで操作を実行できます

  • createTable() - エンティティクラスの定義に基づいてテーブルを作成します。

または DatabaseTableConfig オブジェクト ** createTableIfNotExists() - それ以外は前のメソッドと同じ

テーブルが存在しない場合にのみテーブルを作成します。これだけで動作します それをサポートするデータベース ** dropTable() - テーブルを削除する

  • clearTable () - テーブルからデータを削除する

TableUtils を使用して Library クラスのテーブルを作成する方法を見てみましょう。

TableUtils.createTableIfNotExists(connectionSource, Library.class);

6. DAO オブジェクト

ORMLiteには、CRUD機能を使用して DAO オブジェクトを作成できる DaoManager クラスが含まれています** :

Dao<Library, Long> libraryDao
  = DaoManager.createDao(connectionSource, Library.class);

DaoManager は、その後の__createDao()の呼び出しごとにクラスを再生成するわけではありませんが、代わりにパフォーマンスを向上させるために再利用します。

次に、 Library オブジェクトに対してCRUD操作を実行できます。

Library library = new Library();
library.setName("My Library");
libraryDao.create(library);

Library result = libraryDao.queryForId(1L);

library.setName("My Other Library");
libraryDao.update(library);

libraryDao.delete(library);

DAO は、すべてのレコードをループ処理できる反復子です。

libraryDao.forEach(lib -> {
    System.out.println(lib.getName());
});

ただし、ループが最後まで続く場合、ORMLiteは基礎となるSQL文を閉じるだけです。例外またはreturnステートメントは、コード内でリソースリークを引き起こす可能性があります。

そのため、ORMLiteのドキュメントでは、反復子を直接使用することをお勧めしています。

try (CloseableWrappedIterable<Library> wrappedIterable
  = libraryDao.getWrappedIterable()) {
    wrappedIterable.forEach(lib -> {
        System.out.println(lib.getName());
    });
 }

このようにして、 try-with-resources または finally ブロックを使用してイテレータを閉じることができ、リソースリークを回避できます。

6.1. カスタムDAOクラス

提供されている DAO オブジェクトの動作を拡張したい場合は、 Dao タイプを拡張する新しいインターフェースを作成できます。

public interface LibraryDao extends Dao<Library, Long> {
    public List<Library> findByName(String name) throws SQLException;
}

それでは、このインターフェースを実装し、 BaseDaoImpl クラスを拡張するクラスを追加しましょう。

public class LibraryDaoImpl extends BaseDaoImpl<Library, Long>
  implements LibraryDao {
    public LibraryDaoImpl(ConnectionSource connectionSource) throws SQLException {
        super(connectionSource, Library.class);
    }

    @Override
    public List<Library> findByName(String name) throws SQLException {
        return super.queryForEq("name", name);
    }
}
  • この形式のコンストラクタが必要です。

最後に、カスタムの DAOを使用するには、 Library__クラス定義にクラス名を追加する必要があります。

@DatabaseTable(tableName = "libraries", daoClass = LibraryDaoImpl.class)
public class Library {
   //...
}

これにより、 DaoManager を使用してカスタムクラスのインスタンスを作成できます。

LibraryDao customLibraryDao
  = DaoManager.createDao(connectionSource, Library.class);

それから、標準の DAO クラスのすべてのメソッドとカスタムメソッドを使用できます。

Library library = new Library();
library.setName("My Library");

customLibraryDao.create(library);
assertEquals(
  1, customLibraryDao.findByName("My Library").size());

7. エンティティの関係の定義

ORMLiteは永続化のためにエンティティ間の関係を定義するために「外部」オブジェクトまたはコレクションの概念を使用します。

それぞれの種類のフィールドを定義する方法を見てみましょう。

7.1. 異物フィールド

@ DatabaseField のアノテーションを付けたフィールドで foreign = true 属性を使用することで、2つのエンティティクラス間に単方向の1対1の関係を作成できます。このフィールドは、データベースにも保持されているタイプである必要があります。

まず、 Address という新しいエンティティクラスを定義しましょう。

@DatabaseTable(tableName="addresses")
public class Address {
    @DatabaseField(generatedId = true)
    private long addressId;

    @DatabaseField(canBeNull = false)
    private String addressLine;

   //standard getters, setters
}

次に、 Address 型のフィールドを Library クラスに追加します。

@DatabaseTable(tableName = "libraries")
public class Library {
   //...

    @DatabaseField(foreign=true, foreignAutoCreate = true,
      foreignAutoRefresh = true)
    private Address address;

   //standard getters, setters
}

@ DatabaseField アノテーションにさらに2つの属性、 foreignAutoCreate foreignAutoRefresh を追加しました。どちらも true. に設定されています。

foreignAutoCreate = true 属性は、 address フィールドを使用して Library オブジェクトを保存するときに、その id がnullではなく、 generatedId = true 属性を持っていれば、外部オブジェクトも保存されることを意味します。

foreignAutoCreate をデフォルト値の false に設定した場合は、それを参照する Library オブジェクトを保存する前に、外部オブジェクトを明示的に永続化する必要があります。

同様に、 __ foreignAutoRefresh = true__属性は、ライブラリオブジェクトを取得するときに、関連する外部オブジェクトも取得するように指定します。それ以外の場合は、手動で更新する必要があります。

Address フィールドを持つ新しい Library オブジェクトを追加し、両方を保持するために libraryDao を呼び出します。

Library library = new Library();
library.setName("My Library");
library.setAddress(new Address("Main Street nr 20"));

Dao<Library, Long> libraryDao
  = DaoManager.createDao(connectionSource, Library.class);
libraryDao.create(library);

次に、 address が呼び出され、 Address も保存されたことを確認します。

Dao<Address, Long> addressDao
  = DaoManager.createDao(connectionSource, Address.class);
assertEquals(1,
  addressDao.queryForEq("addressLine", "Main Street nr 20")
  .size());

7.2. 外国のコレクション

リレーションシップの には、 @ ForeignCollectionField アノテーションを付けて ForeignCollection <T> または Collection <T> 型を使用できます。

上記のような新しい Book エンティティを作成してから、 Library クラスに一対多の関係を追加しましょう。

@DatabaseTable(tableName = "libraries")
public class Library {
   //...

    @ForeignCollectionField(eager=false)
    private ForeignCollection<Book> books;

   //standard getters, setters
}

これに加えて、 Book クラスに Library 型のフィールドを追加する必要があります。

@DatabaseTable
public class Book {
   //...
    @DatabaseField(foreign = true, foreignAutoRefresh = true)
    private Library library;

   //standard getters, setters
}
  • ForeignCollection には、 Book: 型のレコードを操作する add() メソッドと remove() メソッドがあります。

Library library = new Library();
library.setName("My Library");
libraryDao.create(library);

libraryDao.refresh(library);

library.getBooks().add(new Book("1984"));

ここでは、 library オブジェクトを作成し、次に books フィールドに新しい Book オブジェクトを追加しました。これもデータベースに永続化されます。

  • コレクションは遅延ロードされているとマークされているので(eager = false)、bookフィールドを使用する前に__refresh()メソッドを呼び出す必要があります。

Book クラスの library フィールドを設定して関係を作成することもできます。

Book book = new Book("It");
book.setLibrary(library);
bookDao.create(book);

両方の Book オブジェクトが library に追加されたことを確認するために、 queryForEq() メソッドを使用して、指定された library idを持つすべての Book レコードを検索できます。

assertEquals(2, bookDao.queryForEq("library__id", library).size());

ここで、 library id は外部キー列のデフォルト名であり、主キーは library__オブジェクトから推測されます。

8 QueryBuilder

それぞれの DAO を使用して QueryBuilder オブジェクトを取得し、それを使用してより強力なクエリを構築することができます。

このクラスには、 selectColumns()、where()、groupBy()、 having()、countOf()、distinct()、orderBy()、join()など、SQLクエリで使用される共通の操作に対応するメソッドが含まれています。

複数の Book が関連付けられているすべての Library レコードを見つける方法の例を見てみましょう。

List<Library> libraries = libraryDao.queryBuilder()
  .where()
  .in("libraryId", bookDao.queryBuilder()
    .selectColumns("library__id")
    .groupBy("library__id")
    .having("count(** ) > 1"))
  .query();

9結論

この記事では、ORMLiteを使用してエンティティを定義する方法と、オブジェクトとそれに関連するリレーショナルデータベースを操作するために使用できるライブラリの主な機能について説明しました。

例の完全なソースコードはhttps://github.com/eugenp/tutorials/tree/master/libraries-data[over on GitHub]にあります。