ORMLiteの紹介

ORMLiteの概要

1. 概要

ORMLiteは、Javaアプリケーション用の軽量ORMライブラリです。 最も一般的なユースケースであるwithout the added complexity and overhead of other ORM frameworks.用のORMツールの標準機能を提供します

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

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

  • 拡張可能なDAOクラス

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

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

  • トランザクションのサポート

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

次のセクションでは、ライブラリを設定し、エンティティクラスを定義し、ライブラリを使用してデータベースで操作を実行する方法を見ていきます。

2. Mavenの依存関係

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


    com.j256.ormlite
    ormlite-jdbc
    5.0

デフォルトでは、これは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アノテーションを追加する必要があります。

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

また、クラスには、少なくともpackage-scopeの可視性を持つ引数のないコンストラクターが必要であることに注意してください。

フィールドの構成に使用できるその他のよく知られた属性は、columnNamedataTypedefaultValuecanBeNulluniqueです。

3.1. JPAアノテーションの使用

ORMLite固有の注釈に加えて、we can also use JPA-style annotations to define our entities

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です。 )s、@Version

4. ConnectionSource

定義されたオブジェクトを操作するには、we need to set up a ConnectionSource

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

JdbcPooledConnectionSource connectionSource
  = new JdbcPooledConnectionSource("jdbc:h2:mem:myDb");

// work with the connectionSource

connectionSource.close();

パフォーマンスが向上した他の外部データソースも、DataSourceConnectionSourceオブジェクトでラップすることで使用できます。

5. TableUtilsクラス

ConnectionSourcewe can use static methods from the TableUtils class to perform operations on the database schemaに基づく:

  • createTable() –エンティティクラス定義またはDatabaseTableConfigオブジェクトに基づいてテーブルを作成します

  • createTableIfNotExists() –前の方法と同様ですが、テーブルが存在しない場合にのみテーブルを作成する点が異なります。これは、それをサポートするデータベースでのみ機能します

  • dropTable() –テーブルを削除します

  • clearTable()–テーブルからデータを削除します

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

TableUtils.createTableIfNotExists(connectionSource, Library.class);

6. DAOオブジェクト

ORMLiteにはa DaoManager class that can create DAO objects for us with CRUD functionalityが含まれています:

Dao 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 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 {
    public List findByName(String name) throws SQLException;
}

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

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

    @Override
    public List 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
}

次に、foreignとしてマークされているLibraryクラスにタイプAddressのフィールドを追加できます。

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

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

    // standard getters, setters
}

@DatabaseFieldアノテーションにさらに2つの属性foreignAutoCreateforeignAutoRefreshを追加したことに注意してください。どちらもtrue.に設定されています

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

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

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

Addressフィールドを持つ新しいLibraryオブジェクトを追加し、libraryDaoを呼び出して両方を永続化しましょう。

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

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

次に、addressDaoを呼び出して、Addressも保存されていることを確認できます。

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

7.2. 外国のコレクション

関係のmany側では、タイプForeignCollection<T>またはCollection<T>@ForeignCollectionFieldアノテーションとともに使用できます。

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

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

    @ForeignCollectionField(eager=false)
    private ForeignCollection books;

    // standard getters, setters
}

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

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

    // standard getters, setters
}

タイプBook:のレコードを操作するThe ForeignCollection has add() and remove() methods

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

libraryDao.refresh(library);

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

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

ブックフィールドを使用できるようになる前のNote that since our collection is marked as lazily loaded (eager=false), we need to call the refresh() method

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オブジェクトを取得し、それを利用してより強力なクエリを構築できます。

このクラスには、次のようなSQLクエリで使用される一般的な操作に対応するメソッドが含まれています。selectColumns(), where(), groupBy(),having(), countOf(), distinct(), orderBy(), join().

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

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

9. 結論

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

例の完全なソースコードはover on GitHubにあります。