1前書き


Jinq

は、Javaでデータベースを照会するための直感的で便利なアプローチを提供します。このチュートリアルでは、Jinqを使用するようにSpringプロジェクトを設定する方法と、簡単な例で説明されているその機能のいくつかを探ります。


2 Mavenの依存関係


Jinq依存関係

を追加する必要があります。]

pom.xml

ファイル

<dependency>
    <groupId>org.jinq</groupId>
    <artifactId>jinq-jpa</artifactId>
    <version>1.8.22</version>
</dependency>

Springにはhttps://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22org.springframework%22%20AND%20a%3A%22spring-orm%22[the Springを追加します

pom.xml

ファイル内のORM依存関係]

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-orm</artifactId>
    <version>5.0.3.RELEASE</version>
</dependency>

最後に、テスト用にH2インメモリデータベースを使用しますので、https://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22com.h2database%22%20ANDも追加しましょう%20a%3A%22h2%22

pom.xml

ファイルへの[この依存関係]:

<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>1.4.196</version>
</dependency>


3 Jinqを理解する

Jinqは、内部的に


Java Stream API

モデル別に車を絞り込む例を見てみましょう。

jinqDataProvider.streamAll(entityManager, Car.class)
  .where(c -> c.getModel().equals(model))
  .toList();

  • Jinqは上記のコードスニペットを効率的な方法でSQLクエリに変換します。

select c.**  from car c where c.model=?

  • クエリの記述にプレーンテキストを使用せず、代わりにタイプセーフなAPIを使用するので、この方法ではエラーが発生しにくくなります。

さらに、Jinqは一般的で読みやすい式を使用することで開発のスピードアップを図っています。

それでも、次に説明するように、使用できる種類や操作の数には制限があります。


3.1. 制限事項

  • JinqはJPAの基本型とSQL関数の具体的なリストのみをサポートしています** すべてのオブジェクトとメソッドをJPAデータ型とSQL関数にマッピングすることにより、ラムダ操作をネイティブSQLクエリに変換します。

したがって、このツールがすべてのカスタム型または型のすべてのメソッドを変換することは期待できません。


3.2. サポートされているデータ型

サポートされているデータ型とサポートされているメソッドを見てみましょう。


  • String



    equals()



    compareTo()

    メソッドのみ

  • プリミティブデータ型 – 算術演算


  • Enums

    とカスタムクラス – ==と!=の操作のみをサポート


  • java.util.Collection –


    contains()


  • Date

    API –

    equals()



    before()



    after()

    メソッドのみ

  • 注:Javaオブジェクトからデータベースオブジェクトへの変換をカスタマイズしたい場合は、

    AttributeConverter

    の具体的な実装をJinqに登録する必要があります。


4 JinqとSpring

の統合

  • 永続コンテキストを取得するには、Jinqではhttps://docs.oracle.com/javaee/7/api/javax/persistence/EntityManager.html[

    EntityManager

    ]インスタンスが必要です。** このチュートリアルでは、次の簡単な方法を紹介します。 Jinqをhttp://hibernate.org/[休止状態]で提供される

    EntityManager

    と連携させるための春。


4.1. リポジトリインタフェース

  • Springはエンティティの管理にリポジトリの概念を使用しています** 特定のモデルの

    Car

    を取得するメソッドがある

    CarRepository

    インターフェースを見てみましょう。

public interface CarRepository {
    Optional<Car> findByModel(String model);
}


4.2. 抽象ベースリポジトリ

次に、すべてのJinq機能を提供するために、** ベースリポジトリが必要です。

public abstract class BaseJinqRepositoryImpl<T> {
    @Autowired
    private JinqJPAStreamProvider jinqDataProvider;

    @PersistenceContext
    private EntityManager entityManager;

    protected abstract Class<T> entityType();

    public JPAJinqStream<T> stream() {
        return streamOf(entityType());
    }

    protected <U> JPAJinqStream<U> streamOf(Class<U> clazz) {
        return jinqDataProvider.streamAll(entityManager, clazz);
    }
}


4.3. リポジトリの実装

  • 今、Jinqに必要なのは

    EntityManager

    インスタンスとエンティティタイプクラスだけです。

先ほど定義したJinqベースリポジトリを使用した

Car

リポジトリの実装を見てみましょう。

@Repository
public class CarRepositoryImpl
  extends BaseJinqRepositoryImpl<Car> implements CarRepository {

    @Override
    public Optional<Car> findByModel(String model) {
        return stream()
          .where(c -> c.getModel().equals(model))
          .findFirst();
    }

    @Override
    protected Class<Car> entityType() {
        return Car.class;
    }
}


4.4.

JinqJPAStreamProvider


を配線する


JinqJPAStreamProvider

インスタンスを配線するために、Jinqプロバイダ設定を追加します。

@Configuration
public class JinqProviderConfiguration {

    @Bean
    @Autowired
    JinqJPAStreamProvider jinqProvider(EntityManagerFactory emf) {
        return new JinqJPAStreamProvider(emf);
    }
}


4.5. Springアプリケーションの設定

最後のステップは、HibernateとJinq設定を使用してSpringアプリケーションを設定することです。

spring.datasource.url=jdbc:h2:~/jinq
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.hibernate.ddl-auto=create-drop


5問い合わせガイド

  • Jinqは、

    selectを使って最終的なSQLクエリをカスタマイズするための直感的なオプションを数多く提供します。ここで、

    __joinsなど。これらは、上で紹介したのと同じ制限があります。


5.1. どこで


where

句を使用すると、データコレクションに複数のフィルタを適用できます。

次の例では、モデルと説明で自動車を絞り込みます。

stream()
  .where(c -> c.getModel().equals(model)
    && c.getDescription().contains(desc))
  .toList();

そしてこれがJinqが翻訳するSQLです:

select c.model, c.description from car c where c.model=? and locate(?, c.description)>0


5.2. 選択

データベースからいくつかの列/フィールドのみを取得したい場合は、

select

句を使用する必要があります。

複数の値をマップするために、Jinqは最大8つの値を持ついくつかの

Tuple

クラスを提供します。

stream()
  .select(c -> new Tuple3<>(c.getModel(), c.getYear(), c.getEngine()))
  .toList()

そして翻訳されたSQL:

select c.model, c.year, c.engine from car c


5.3. 参加する

  • エンティティが正しくリンクされていれば、Jinqは1対1および多対1の関係を解決することができます。

たとえば、

Car

に製造元エンティティを追加したとします。

@Entity(name = "CAR")
public class Car {
   //...
    @OneToOne
    @JoinColumn(name = "name")
    public Manufacturer getManufacturer() {
        return manufacturer;
    }
}


__Car


sのリストを持つ

Manufacturer__エンティティ

@Entity(name = "MANUFACTURER")
public class Manufacturer {
   //...
    @OneToMany(mappedBy = "model")
    public List<Car> getCars() {
        return cars;
    }
}

与えられたモデルの

製造元

を取得できるようになりました。

Optional<Manufacturer> manufacturer = stream()
  .where(c -> c.getModel().equals(model))
  .select(c -> c.getManufacturer())
  .findFirst();

予想通り、このシナリオでは

Jinqは内部結合SQL句

を使用します。

select m.name, m.city from car c inner join manufacturer m on c.name=m.name where c.model=?

  • 多対多の関係のように、エンティティに対してより複雑な関係を実装するために

    join

    句をもっと制御する必要がある場合は、

    join

    メソッドを使用できます。

List<Pair<Manufacturer, Car>> list = streamOf(Manufacturer.class)
  .join(m -> JinqStream.from(m.getCars()))
  .toList()

最後に、

join

メソッドの代わりに

leftOuterJoin

メソッドを使用して、左外部結合SQL句を使用できます。


5.4. 集計

これまでに紹介した例はすべて、Jinqでクエリの最終結果を返すために

toList

メソッドまたは

findFirst

メソッドのいずれかを使用しています。

これらの方法以外にも、結果を集計するための他の方法にもアクセスできます。

たとえば、

count

メソッドを使用して、具体的なモデルの自動車の総数をデータベースで取得します。

long total = stream()
  .where(c -> c.getModel().equals(model))
  .count()

そして最後のSQLは期待通りに

count

SQLメソッドを使っています:

select count(c.model) from car c where c.model=?

Jinqは、

sum



average



min



max、

などの集約方法と、異なる集約を組み合わせる** 可能性も提供します。


5.5. ページ付け

データをバッチで読みたい場合は、

limit



skip

メソッドを使用できます。

最初の10台の車をスキップして20個の商品だけを取得する例を見てみましょう。

stream()
  .skip(10)
  .limit(20)
  .toList()

そして生成されたSQLは次のとおりです。

select c.**  from car c limit ? offset ?


6. 結論

そこに行きます。この記事では、Hibernateを使用してJinqでSpringアプリケーションを設定するためのアプローチについて説明しました(最小限)。

また、Jinqの利点とその主な機能についても簡単に説明しました。

いつものように、ソースはhttps://github.com/eugenp/tutorials/tree/master/spring-jinq[over on GitHub]にあります。