MyBatisコア構成
MyBatisのコアコンポーネント
MyBatisプロジェクトは通常、以下のセクションで構成されます。
- コア構成ファイル:実行環境、データソース、トランザクションマネージャ、およびMapperを構成します。
- Mapperインターフェイス:データベース操作メソッドを宣言します。
- Mapper XML:SQLを記述し、メソッド、パラメータ、返される結果の間のマッピングを確立します。
SqlSessionFactory構成からSqlSessionを作成します。SqlSession:SQLの実行、Mapperエージェントの取得、トランザクションの管理。
コア·プロファイル
コアプロファイルは通常mybatis-config.xmlと呼ばれます。ファイル名はカスタマイズできますが、構成を読み取るときには実際のファイル名を使用する必要があります。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/book_shop"/>
<property name="username" value="root"/>
<property name="password" value="1234"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mapping/BookMapper.xml"/>
</mappers>
</configuration>environmentsは複数の実行環境を構成でき、defaultの値は、あるenvironmentのidと一致する必要があります。この例はmysql環境を選択します。
MyBatisはコア設定ファイル自体を読み取るだけでなく、外部プロパティファイルやMapper XMLなどのリソースを内部設定に基づいて読み込みます。例えば、<mapper resource="..."/>は、マッピングファイルの内容をコア設定ファイルに直接書き込むのではなく、クラスパスから指定されたマッピングファイルをロードすることを意味します。
外部プロパティファイルの使用
データベース接続情報は通常db.propertiesに格納され、XMLに直接記述されない。
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/book_shop
jdbc.username=root
jdbc.password=1234
コア構成ファイルで次のプロパティを導入して使用します。
<configuration>
<properties resource="db.properties"/>
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
</configuration>Mapperインターフェース
Mapperインタフェースは、データベース操作を宣言するために使用されます。MyBatisは実行時にインターフェイスのプロキシオブジェクトを作成するため、通常は手書きの実装クラスは必要ありません。
public interface BookMapper {
List<TbBook> queryAllBook();
TbBook queryById(Integer id);
int insertBook(TbBook book);
}
メソッド名、引数型、戻り値型は、Mapper XMLの対応する文の設定と一致している必要があります。
Mapper XML
Mapper XMLはSQLと結果マップを定義します。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.oracle.dao.BookMapper">
<select id="queryAllBook" resultType="com.oracle.entity.TbBook">
SELECT *
FROM tb_book
</select>
<select id="queryById"
parameterType="java.lang.Integer"
resultType="com.oracle.entity.TbBook">
SELECT *
FROM tb_book
WHERE id = #{id}
</select>
<insert id="insertBook" parameterType="com.oracle.entity.TbBook">
INSERT INTO tb_book(book_name, author, price)
VALUES (#{bookName}, #{author}, #{price})
</insert>
</mapper>namespaceとid
namespaceはMapperインタフェースの完全修飾クラス名を入力し、idはインタフェースメソッド名と一致する必要があります。これにより、BookMapper.queryAllBook()が呼び出されると、MyBatisは対応するSQLステートメントを見つけることができます。
パラメータプレースホルダー
#{}はコンパイル済みパラメータを使用して型を正しく処理し、SQLインジェクションのリスクを軽減します。通常業務パラメータは#{}を優先する。
${}は文字列の直接結合であり、通常は厳密なホワイトリスト検証済みソートフィールドなど、パラメータプレースホルダを使用できない場所でのみ使用されます。ユーザー入力を${}に直接入れないでください。
MyBatis Core APIの概要
SqlSessionFactoryの作成
SqlSessionFactoryBuilderコンフィギュレーションからSqlSessionFactoryが作成されます。ファクトリオブジェクトは作成コストが高く、アプリケーションでは通常 1つしか作成されません。
public final class MyBatisUtil {
private static final SqlSessionFactory SQL_SESSION_FACTORY;
static {
try (InputStream inputStream =
Resources.getResourceAsStream("mybatis-config.xml")) {
SQL_SESSION_FACTORY =
new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
throw new ExceptionInInitializerError(e);
}
}
private MyBatisUtil() {
}
public static SqlSession openSession() {
return SQL_SESSION_FACTORY.openSession();
}
}略称はSqlSession
SqlSessionはスレッドセーフオブジェクトではないため、1 回のビジネスオペレーションで作成し、タイムリーにシャットダウンする必要があります。書き込みが実行された後、トランザクションをコミットする必要があります。例外が発生した場合はロールバックしてください。
public class BookService {
public List<TbBook> queryAllBook() {
try (SqlSession sqlSession = MyBatisUtil.openSession()) {
BookMapper mapper = sqlSession.getMapper(BookMapper.class);
return mapper.queryAllBook();
}
}
public int insertBook(TbBook book) {
try (SqlSession sqlSession = MyBatisUtil.openSession()) {
BookMapper mapper = sqlSession.getMapper(BookMapper.class);
try {
int rows = mapper.insertBook(book);
sqlSession.commit();
return rows;
} catch (RuntimeException e) {
sqlSession.rollback();
throw e;
}
}
}
}openSession(true)を使用して自動コミットをオンにすることもできますが、アトミックな状態に保つために複数のSQLを必要とするビジネスでは手動コミットを使用してください。
結果マップ
自動マッピング
クエリの結果のカラム名がJavaプロパティー名と一致する場合は、resultTypeを直接使用できます。
<select id="queryById" resultType="com.oracle.entity.TbBook">
SELECT id, book_name AS bookName, author, price
FROM tb_book
WHERE id = #{id}
</select>
下線回転キャメル構成が有効な場合、book_nameは自動的にbookNameにマップできます。
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
手動マッピング#マニュアルマッピング#
resultMapは、データベースのカラム名とJavaの属性名が大きく異なる場合や、複雑なマッピングが必要な場合に使用します。
<mapper namespace="com.oracle.dao.UserMapper">
<resultMap id="userMapping" type="com.oracle.entity.User">
<id property="userId" column="user_id"/>
<result property="userName" column="user_name"/>
<result property="realName" column="real_name"/>
<result property="password" column="password"/>
<result property="phone" column="phone"/>
<result property="remain" column="remain"/>
<result property="operator" column="operator"/>
<result property="createTime" column="create_time"/>
</resultMap>
<select id="queryUserById" resultMap="userMapping">
SELECT *
FROM tb_user
WHERE user_id = #{id}
</select>
</mapper>resultTypeとresultMapはどちらも結果を記述するために使用されますが、同じクエリでは通常どちらか一方しか選択されません。単純マッピングではresultTypeを用い,カラムと属性の対応関係を明示的に指定する必要がある場合はresultMapを用いる.
よくある質問
マッピングステートメントが見つかりませんでした
Invalid bound statementが表示された場合は、次の項目を順番に確認してください。
- Mapper XMLが正しいリソースディレクトリに存在するかどうか。
- コア設定は、Mapperがロードされているかどうかです。
namespaceがインタフェースの完全修飾クラス名であるかどうか。- SQLラベルの
idがインタフェース·メソッド名と一致しているかどうか。 - MavenビルドがXMLファイルをクラスパスにコピーするかどうか。
クエリ属性はnullです
データベースの列名、Javaプロパティー名、resultMapが一致しているかどうかを確認してください。また、キャメルを使用する場合は、mapUnderscoreToCamelCaseがオンになっているかどうかも確認してください。
書き込み操作が有効になりません
デフォルトのSqlSessionは自動コミットされません。追加、変更、削除を実行した後はcommit()を呼び出し、例外が発生した場合はrollback()を呼び出し、最後にセッションを閉じます。
気に入ったならばコメントを残してくださいね~