Hibernateのより高速な代替手段としてのMyBatis

Javaコミュニティでは、Hibernateフレームワークは事実上、データベースを使用した便利な作業の標準と見なされています。 開発者が別のフレームワークを選択するのは困難です。代替フレームワークの存在を知らない場合があるためです。 この記事では、若い戦闘機にMyBatisフレームワークを使用する方法を教えます。 フレームワーク全体を完全にカバーすることはできませんが、このフレームワークの長所と短所を確認し、MyBatisでの作業を開始するのに十分な情報があります。



MyBatisはJPA仕様を実装していませんが、JPAに代わるものです。 MyBatisとHibernateの主な違いは、オブジェクトのマッピング方法です。 Hibernateはデータベーステーブルをエンティティにマッピングし、データへのアクセスを提供します。 データを受信するために、HibernateはSQLクエリを生成します。生成されたクエリは当面は有効であり、多くの時間を消費し、扱いにくく管理不能になります。 MyBatisはテーブルにマッピングしませんが、SQLクエリには、開発者がクエリを生成する責任があり、それだけがアプリケーションの動作速度に依存します。



前文は終了しました。MyBatisを使用して小さなプロジェクトを直接作成して、より詳しく知ることができます。 私は独創的ではありません。MyBatisを使用していくつかのデータベースクエリを作成します。 この例では、MySQL DBMSを使用しますが、他の任意のDBMSを使用できます。



mybatisデータベースを作成します。



CREATE DATABASE `mybatis`;
      
      





テーブルのサブスクライバー、関税、支払いを作成します。



加入者:



 CREATE TABLE `mybatis`.`subscriber` ( `id` INT( 10 ) NOT NULL , `name` VARCHAR( 255 ) NOT NULL , `ref_tariff` VARCHAR( 10 ) NOT NULL , PRIMARY KEY ( `id` ) ) ENGINE = MYISAM
      
      





関税:



 CREATE TABLE `mybatis`.`tariff` ( `id` INT( 10 ) NOT NULL , `descr` VARCHAR( 255 ) NOT NULL , PRIMARY KEY ( `id` ) ) ENGINE = MYISAM
      
      





支払い:



 CREATE TABLE `mybatis`.`payments` ( `id` INT( 10 ) NOT NULL , `ref_subscriber` INT( 10 ) NOT NULL , `summa` INT( 10 ) NOT NULL , PRIMARY KEY ( `id` ) ) ENGINE = MYISAM
      
      





最も退屈なことは私たちの後ろにあります-私たちはそこからデータを受け取るデータベースを持っており、今ではMyBatisと直接やり取りを始めます。 まず、MyBatisライブラリが必要です。 ライブラリを取得するには、mavenを使用します。プロジェクト設定(pom.xml)に依存関係を追加する必要があります。



 <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.2.8</version> </dependency>
      
      





執筆時点で、MyBatis 3.2.8の最新バージョン



ライブラリが正常にロードされたら、データベースへの接続を構成する必要があります。 設定は、構成ファイルmybatis-config.xmlで行われます。



以下は、構成ファイルのリストです。



 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <properties resource="config.properties"> <!--    (  , ,   .)--> </properties> <settings><!--      .    http://mybatis.github.io/mybatis-3/configuration.html#settings--> <setting name="logImpl" value="LOG4J"/> </settings> <environments default="development"><!--      --> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${db.driver}"/> <property name="url" value="${db.url}"/> <property name="username" value="${db.username}"/> <property name="password" value="${db.password}"/> </dataSource> </environment> </environments> <mappers><!--     ,    --> <mapper class="kz.jazzsoft.mapper.SubscriberMapper"/> <mapper class="kz.jazzsoft.mapper.TariffMapper"/> <mapper class="kz.jazzsoft.mapper.PaymentMapper"/> </mappers> </configuration>
      
      





上記のリストでは、3つのマッパーを示しました。データベースとのすべてのやり取りはマッパーを介して実行され、マッパーの操作方法とクエリの作成方法を理解すればするほど、アプリケーションの生産性が向上します。



MyBatisを正しく動作させるには、使用するメソッドが事前に定義されているマッパーインターフェイス、SQLクエリが記述されるxml設定ファイル、オブジェクトへのマッピングのルールなどを作成する必要があります。



kz.jazzsoft.mapper.SubscriberMapperインターフェースを作成します。



 package kz.jazzsoft.mapper; import kz.jazzsoft.dal.Subscriber; public interface SubscriberMapper { Subscriber getSubscriberById(Integer id); List getSubscriber(); }
      
      





このインターフェイスでは、2つのメソッドを定義しています。



1. getSubscriberById-IDで1人のユーザーを返します。



2. getSubscriber-ユーザーのリストを返します。



ただし、これらのメソッドを機能させるには、SQLクエリを使用してXMLマッパーを作成する必要があります。



 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="kz.jazzsoft.mapper.SubscriberMapper"> <select id="getSubscriberById" <!-- --> parameterType="java.lang.Integer" <!--  ,    ,   Map   EntityBean.--> > select * from subscriber where id = #{id} <!--      ,    .   Map —  {}    .     EntityBean  {} —     bean.--> </select> <select id="getSubscriber"> select * from subscriber </select> </mapper>
      
      





実行する必要がある別のポイントを見逃したのは、beanEntityクラスを作成することです。このクラスで、クエリ実行の結果をマップします。



加入者:



 package kz.jazzsoft.dal; import java.util.List; public class Subscriber { private Long id; private String name; private Tariff tariff; private List<Payment> payments public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Tariff getTariff() { return tariff; } public void setTariff(Tariff tariff) { this.tariff = tariff; } public List<Payment> getPayments() { return paymentList; } public void setPayments(List<Payment> payments) { this.payments = payments; } public List<Connection> getConnections() { return connections; } }
      
      





関税:



 package kz.jazzsoft.dal; public class Tariff { private Long id; private String descr; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getDescr() { return descr; } public void setDescr(String descr) { this.descr = descr; } }
      
      





支払い管理



 package kz.jazzsoft.dal; public class Payment { private Long id; private Integer summa; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public Integer getSumma() { return discount; } public void getSumma(Integer summa) { this.summa = summa; } }
      
      





コードがどのように機能するかをすぐに確認できます。そのためには、データベースに接続し、目的のマッパーを初期化する必要がありますが、現時点では1つ(SubscriberMapper)があります。 作業するクラスを作成しましょう:



仕事:



 package kz.jazzsoft; import kz.jazzsoft.mapper.SubscriberMapper; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.IOException; import java.io.Reader; public class Work { public static void main(String[] args) { SqlSessionFactory sqlSessionFactory; SubscriberMapper subscriberMapper; Reader reader = null; try { reader = Resources .getResourceAsReader("mybatis-config.xml"); //       MyBatis sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); subscriberMapper = sqlSessionFactory.openSession().getMapper(SubscriberMapper.class); // ,       getSubscriberById  getSubscribers List<Subscriber> subscribers = subscriberMapper.getSubscribers(); Subscriber subscriber = subscriberMapper.getSubscriberById(101); } catch (IOException e) { e.printStackTrace(); } } }
      
      





リクエストは満たされ、作業できるオブジェクトがあります。 オブジェクトにはIDがあり、他のフィールドはすべてではありませんが、入力されていることがわかります。 ここで1つの注意点があります。データベース内の列が変数と同じ名前を持つ場合、自動的にその列にマップされます。 マッピングの機能を拡張し、MyBatisの兵器庫に複雑な構造を作成するために、任意のマッピングを構成できるResultMapタグがあります。 1対1および1対多の接続を作成します。



ResultMapは、EntityBeanフィールドをテーブルの列とリンクするためのルールの説明です。 サブスクライバーの例:



 <resultMap id="subscriber" type="kz.jazzsoft.dal.Subscriber"> <id property="id" column="id"/> <result property="name" column="name"/> <!--   name  Subscriber   ,    property--> </resultMap>
      
      





その結果、サブスクライバーのマッパーは次のようになります。



 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="kz.jazzsoft.mapper.SubscriberMapper"> <resultMap id="subscriber" type="kz.jazzsoft.dal.Subscriber"> <id property="id" column="id"/> <result property="name" column="name"/> </resultMap> <select id="getSubscriberById" parameterType="java.lang.Integer" resultMap="subscriber"> <!--   ResultMap      --> select * from subscriber where id = #{id} </select> <select id="getSubscribers" resultMap="tariff"> select * from subscriber </select> </mapper>
      
      





1対1の通信は、上記の例ほど複雑ではありません。 しかし、最初に次のマッパー関税について説明する必要があります。 これにより、サブスクライバーの関連フィールドのデータを受け取ります。



Tariffエンティティを作成します。



 package kz.jazzsoft.dal; public class Tariff { private Long id; private String descr; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getDescr() { return descr; } public void setDescr(String descr) { this.descr = descr; } }
      
      





TariffMapperマッパーインターフェイスを作成します。必要なメソッドは1つだけです。



 package kz.jazzsoft.mapper; import kz.jazzsoft.dal.Tariff; public interface TariffMapper { Tariff getTariffById(Integer id); }
      
      





マッパーを作成します。



 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="kz.jazzsoft.mapper.TariffMapper"> <resultMap id="tariff" type="kz.jazzsoft.dal.Tariff"> <id property="id" column="id"/> <result property="descr" column="descr"/> </resultMap> <select id="getTariffById" resultMap="tariff" parameterType="java.lang.Integer"> select * from tariff where id = #{id} </select> </mapper>
      
      





これで、Subscriber with TariffをSubscriberMaperに追加できます。resultMapで、通信ルールを追加する必要があります。



 <resultMap id="subscriber" type="kz.jazzsoft.dal.Subscriber"> <id property="id" column="id"/> <result property="name" column="name"/> <association property="tariff" <!--  Subscriber --> column="ref_tariff" <!--    Subscriber,          --> javaType="kz.jazzsoft.dal.Tariff" <!-- ,     --> select="kz.jazzsoft .mapper.TariffMapper.getTariffById" <!--       ,   sql      .--> fetchType="eager" <!--  --> /> </resultMap>
      
      





このresultMapを置き換える必要があり、どの関税(関税)プランで購読者(購読者)がいるかを調べることができます。



Subscriber.gettariff()。GetDescr();



購読者に支払いのリスト(1対多)を追加します。



まず、EntityBean支払いを作成する必要があります。



 package kz.jazzsoft.dal; public class Payment { private Long id; private Integer summa; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public Integer getSumma() { return discount; } public void getSumma(Integer summa) { this.summa = summa; } }
      
      





次に、PaymentMapperインターフェースを作成する必要があります。これは簡単です。 ユーザーIDによって支払いのリストを取得する1つの方法のみ。



 package kz.jazzsoft.mapper; import kz.jazzsoft.dal.Payment; import java.util.List; public interface PaymentMapper { List<Payment> getPaymentsByIdSub(Integer id); }
      
      





XMLマッパーを作成する必要があります。



 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="kz.jazzsoft.mapper.PaymentMapper"> <resultMap id="payment" type="kz.jazzsoft.dal.Payment"> <id property="id" column="id"/> <result property="summa" column="date"/> </resultMap> <select id="getPaymentsByIdSub" resultMap="payment" parameterType="java.lang.Integer"> select * from payment where ref_subscriber = #{id} </select> </mapper>    (payment)   (Subscriber): <source lang="xml"> <resultMap id="subscriber" type="kz.jazzsoft.dal.Subscriber"> <id property="id" column="id"/> <result property="name" column="name"/> <association property="tariff" column="ref_tariff" javaType="kz.jazzsoft.dal.Tariff" select="kz.jazzsoft.mapper.TariffMapper.getTariffById" fetchType="eager"/> <collection property="payments" <!--  bean Subscriber--> column="id" <!--id Subscriber--> javaType="List" <!--    ()--> ofType="Payment" <!--     --> select="kz.jazzsoft.mapper.PaymentMapper.getPaymentsByIdSub" <!-- ,   ,       id --> fetchType="eager" <!-- --> /> </resultMap>
      
      





結果のresultMapはSubscriberMapperで置き換えられ、すべてのユーザーの支払いを確認できます。 しかし、ここからが楽しみです。



MyBatisには、渡されたパラメーターに応じてSQLクエリを動的に生成できる機能があります。 たとえば、アクションごとにSQLの束を作成する必要はありません(1つのテーブルから選択しますが、異なるパラメーターに応じて)、複数の列で同じサブスクライバーをフィルター処理するか、まったくフィルター処理せず、入力データに応じてすべてを返す1つのメソッドで取得できます。しかし、最初に最初のもの。



MyBatisの兵器庫でのSQLクエリの動的生成には、ほとんどの問題を解決するのに十分なコンポーネントがあります。 それらの多くがあり、それらを組み合わせることができるなどのため、それらのすべてを検討するつもりはありません。 たとえば、IFステートメントを検討してください。詳細については、公式マニュアルmybatis.github.io/mybatis-3/dynamic-sql.htmlを参照してください。



IF演算子:



 <select id="getSubscribersWithParam" parameterType="map"> select * from subscriber where (1=1) <if test="descr != null" > and decr = #{descr} </if> </select>
      
      





上記のクエリでは、descrキーによるMapのオブジェクトがnullでないことを確認し、ifブロックでクエリに行が追加され、そのようなブロックをできるだけ多く入れ子にすることができます。



 <update id="updateSubscriber" parameterType="kz.jazzsoft.dal.Subscriber"> udpate subscriber <set> <if test="descr != null"> descr = #{descr}, </if> </set> where id = #{id} </update>
      
      







MyBatisを適切に使用すると、アプリケーションの速度を目に見える形で高めることができます。 クエリとマッピングルールを自分で記述するのは恐ろしいかもしれませんが、Hibirnateもそれほど単純ではないようです。



すべての人に適した普遍的なソリューションはありません;それぞれの選択には明確な計算が必要です。 MyBatisは、それが本当に必要な場所でHibernateと一緒に使用でき、あなただけが決定できます。



All Articles