こんにちは、シェンディです
https://sdpro.top/blog/html/article/1044.html
要件の説明
SpringBootを使ったMybatisの統合は古くから行われており、Springを持たないがデータベースを操作するプログラムを書く場合、より効率的でシンプルなインターフェース+アノテーションの形を考えることになります。
@Autowirted
Spring では、インターフェイス マッピングを記述するだけでよく、その後、アノテーションを使用して、使用する必要がある場所に自動的にロードされ、直接使用できます。
Springを使わない場合、Mybatisを利用するためにSqlSessionFactoryを使用してSqlSessionを取得し、操作を処理し、操作後にSqlSessionを閉じる必要があり、非常に面倒です。
SqlSession.getMapper はインターフェイスインスタンスを常時使用できると思っていましたが、接続が切断されるとインスタンスが使用できなくなり、エラーが報告されることがわかったので、要件を満たすようにメソッドを変更しました
以下は、Mybatis の使用プロセスの紹介です (インターフェース + アノテーション フォーム、XML フォームは記載されていません)
依存関係のインポート
2 つの jar パッケージが必要です。1 つは jdbc ドライバーです。たとえば、mysql はオンラインで見つかる mysql-connector-java.jar を使用します。
mybatis の jar パッケージも使用します。mybatis の github から直接ダウンロードできます。
Maven の使用は、SpringBoot での依存関係の導入に似ています。インポートされた依存関係は Baidu で見つけることができます。jdbc と mybatis を導入する必要があります。
Mybatis設定ファイルの書き込み
形式は xml です。Mybatis の公式ドキュメントを参照できます。中国語です。ファイル名は任意で、通常は config.xml または mybatis-config.xml です。
設定ファイルをどこに置きますか。通常は src ディレクトリに置きます。この設定ファイルを見つける必要があるため、Mybatis はクラスを提供します。
MyBatis には、クラスパスまたは他の場所からリソース ファイルを簡単にロードできるようにするユーティリティ メソッドが含まれる Resources と呼ばれるユーティリティ クラスが含まれています。
プログラムがこのファイルを見つけることができる限り (Mybatis が提供する Resources クラスはあまり使いやすいとは思えません。このファイルは src ディレクトリにしか見つからず、src 下のサブディレクトリは見つかりません...)
私の構成をここに投稿しました。変更を確認できます
<?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>
<!-- 这里的default指向的是使用的是哪个配置(id) 可以有多个 environment 指向多个数据库 -->
<environments default="devMySql">
<environment id="devMySql">
<!-- 基于jdbc -->
<transactionManager type="JDBC" />
<!-- 数据源 配置一些数据库配置 type="POOLED" 使用MyBatis自带的连接池 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver" />
<!-- 数据库 -->
<property name="url" value="jdbc:mysql://localhost:3306/数据库?serverTimezone=UTC&allowMultiQueries=true" />
<property name="username" value="数据库用户名" />
<property name="password" value="数据库密码" />
</dataSource>
</environment>
</environments>
<!-- 使用注解的方式 -->
<mappers>
<mapper class='shendi.TestMapper'/>
</mappers>
</configuration>
XML から SqlSessionFactory を構築する
すべての MyBatis ベースのアプリケーションは、SqlSessionFactory のインスタンスを中心としています。SqlSessionFactory のインスタンスは、SqlSessionFactoryBuilder を通じて取得できます。SqlSessionFactoryBuilder は、XML 構成ファイルまたは事前構成された構成インスタンスから SqlSessionFactory インスタンスを構築できます。
SqlSessionFactoryには上記設定ファイルの情報が含まれており、後ほど使用するSqlSessionはこのクラスインスタンスから取得されます。
これは接続プールとして理解でき、SqlSession は接続です。
施工方法は以下の通りです(公式例)
String resource = "org/mybatis/example/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
上記のリソースは構成ファイルのパスを表します (実際に試行するとエラーが表示されます)
構成ファイルを src フォルダーに置くと、 resource は構成ファイルのファイル名を直接指定できます。
マッパーインターフェースを書く
SQL文には3つの方法があり、1つはxmlの方法、もう1つは直接インターフェース+アノテーションの方法、もう1つはインターフェース+xmlの方法です。
もちろん、私にとっては、直接インターフェイス + アノテーションの方法が使いやすく、シンプルで効率的です。
インターフェイスを作成し、それを注釈で関数上にマークするだけで、関数は対応する SQL 操作を表すことができます。一般的に使用される追加、削除、変更、およびクエリ
- @入れる
- @消去
- @アップデート
- @選択する
コードはここに直接掲載されています。結局のところ、ID に基づいてユーザーをクエリするなど、非常に単純です。
public interface TestMapper {
@Select("SELECT * FROM user WHERE id=${id} LIMIT 1")
HashMap<String,String> userById(int id);
}
上記は単なる例であり、HashMap 方法の代わりに Bean 方法を使用して戻り値を取得することもできます。
if判定、forループ、再帰クエリ(@Results)などでも
詳細については、他の記事を参照してください。この記事の焦点はここではありません
Java のコンパイル処理中にパラメータ名が arg0、arg1 などに変更され、元の名前が失われることに注意してください。Mybatis はリフレクションを通じてパラメータを見つけます。解決策は 2 つあります。
1. @Param アノテーションをパラメータに追加して名前を指定します
@Select("SELECT * FROM user WHERE id=${id} LIMIT 1")
HashMap<String,String> userById(@Param("id") int id);
2. コンパイル時にパラメータを指定する
javac -parameters このようにコンパイルしますが、もちろんコマンドラインを直接使用することはできず、通常は Eclipse や IDEA などの IDE を使用します。
- アイディア
- [設定] - [ビルド]、[実行]、[デプロイメント] - [コンパイラ] - [Java コンパイラ] をクリックします。
- 追加のコマンドラインパラメータを入力します
-parameters
- 日食
- ウィンドウ - 設定 - Java - コンパイラ
- 勾配オプション メソッドパラメータに関するストア情報(リフレクション経由で使用可能)
私は2番目のほうが好きです
構成マップ
Mapperでは設定が必要ですが、初期設定ファイルに書かれている部分には、
<!-- 使用注解的方式 -->
<mappers>
<mapper class='shendi.TestMapper'/>
</mappers>
このうち、class はクラスパス、TestMapper はマッピングクラスを表し、マッパーが複数ある場合は複数のマッパーを設定するだけです。
公式Webサイトにも、パッケージ全体のインターフェースをマッピングクラスとして使用できるものがありましたが、エラーを報告するために使用しています...
<mappers>
<package name="shendi"/>
</mappers>
使用
構成、SQL、ファクトリ、すべてOKです。最後のステップは使用することです。単純すぎるため、コードを直接ここに示します。
// 拿到工厂
String resource = "config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(inputStream);
// 通过工厂获取SqlSession(连接)
SqlSession ss = ssf.openSession();
// 通过SqlSession获取接口映射实例
TestMapper tm = ss.getMapper(TestMapper.class);
// 直接使用接口就可以了
HashMap<String,String> user = tm.userById(1);
// 最后关闭SqlSession连接
ss.close();
SqlSessionを閉じるとgetMapperで取得したインターフェースインスタンスは使用できなくなり、直接エラーが報告されるためクラスメンバーとして保存することができません。
SpringBootに慣れている私にとっては面倒すぎる SpringBootインターフェースMapperのインスタンスは一つしかなく、接続の取得と接続のクローズを気にする必要がないので、ツールクラスをカプセル化しました
ツールクラス(接続を気にする必要がなく、使いやすい)
動的プロキシを使用して実装されたコア コードは、次の図に示されています。
まず使い方を説明しますと、先ほどと同様に 1 行のコードだけでユーザー情報を取得できます。
HashMap<String,String> user = MapperUtil.TEST.userById(1);
ツールクラスの完全なコードは次のとおりです。
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
/**
* 所有的映射对象.
* <br>
* @author Shendi <a href='tencent://AddContact/?fromId=45&fromSubId=1&subcmd=all&uin=1711680493'>QQ</a>
*/
public class MapperUtil {
public static final SqlSessionFactory SSF;
// 映射类,全局放出去供调用
public static final TestMapper TEST;
static {
SqlSessionFactory ssf = null;
// 这个地方是找配置文件,用的自己写的,可以根据自己需求改掉
try (FileInputStream fi = new FileInputStream(PathFactory.getPath(PathFactory.PROJECT, "/files/mybatis/config.xml"))) {
ssf = new SqlSessionFactoryBuilder().build(fi);
} catch (IOException e) {
e.printStackTrace();
// 日志,根据自己需求改掉
Log.printErr("SqlSessionFactory创建失败,程序终止: %s", e.getMessage());
System.exit(0);
}
SSF = ssf;
ssf = null;
// 拿到接口实例,后面多一个接口就照着多加一行就可以了
TEST = getMapper(TestMapper.class);
}
// 动态代理,将接口实例的每个函数都代理了,执行前拿到SqlSession,执行完关闭SqlSession
private static <T> T getMapper(Class<T> clazz) {
@SuppressWarnings("unchecked")
T obj = (T) Proxy.newProxyInstance(MapperUtil.class.getClassLoader(), new Class[] {
clazz}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try (SqlSession ss = SSF.openSession()) {
T mapper = ss.getMapper(clazz);
Object result = method.invoke(mapper, args);
return result;
}
}
});
return obj;
}
}
補足(重要)
Mybatis の追加、削除、変更を有効にする (トランザクション) には手動で SqlSession.commit を呼び出す必要があるため、上記のツールを少し変更する必要があります。
コミットしない場合、エラーは報告されませんが、データベースにはデータがありません。
以下に変更します
private static <T> T getMapper(Class<T> clazz) {
@SuppressWarnings("unchecked")
T obj = (T) Proxy.newProxyInstance(MapperUtil.class.getClassLoader(), new Class[] {
clazz}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
SqlSession ss = SSF.openSession();
try {
T mapper = ss.getMapper(clazz);
Object result = method.invoke(mapper, args);
return result;
} finally {
ss.commit();
ss.close();
}
}
});
return obj;
}
具体的には、コミットを単独でパッケージ化できる場所
終わり