目次
⑤主キーの自動インクリメントをサポートしていないデータベース
6. データベーステーブルのフィールドとエンティティクラスの属性の対応
第 1 章 はじめに
1. 全体的な技術体系
①単一アーキテクチャ
プロジェクトは war パッケージとしてエクスポートされ、Tomcat 上で実行されます。オールインワンとも言います。
②分散アーキテクチャ
プロジェクト (IDEA のプロジェクトに対応) は多くのモジュールに分割されており、各モジュールは IDEA のモジュールです。各プロジェクトは独自の Tomcat 上で実行されます。モジュールは相互に呼び出すことができます。各モジュールは内部的には単一アーキテクチャのアプリケーションとして見ることができます。
2. フレームワークの概念
フレームワーク = jar パッケージ + 設定ファイル
3. マイバティスの歴史
MyBatis はもともと、Apache のオープン ソース プロジェクトである iBatis でしたが、2010 年 6 月に、このプロジェクトは Apache Software Foundation によって Google Code に移行されました。開発チームが Google Code に移行したため、iBatis3.x は正式に MyBatis に名前変更されました。コードは 2013 年 11 月に Github に移行されました。
iBatis という言葉は、「インターネット」と「アバティス」の組み合わせから来ており、Java をベースにした永続層フレームワークです。iBatis が提供する永続層フレームワークには、SQL マップとデータ アクセス オブジェクト (DAO) が含まれています。
4. Mybatisのダウンロードアドレス
https://github.com/mybatis/mybatis-3
5. Mybatisの特徴
- MyBatis は、カスタマイズされた SQL、ストアド プロシージャ、および高度なマッピングをサポートしています
- MyBatis は、ほぼすべての JDBC コード、手動パラメータ設定、および結果セット解析操作を回避します。
- MyBatis は、単純な XML または注釈を使用して構成とオリジナルのマッピングを実装し、インターフェースと Java POJO (Plain Ordinary Java Object、通常の Java オブジェクト) をデータベース内のレコードにマッピングできます。
- Mybatis は、半自動 ORM (オブジェクト関係マッピング) フレームワークです。
6. 他の永続化レイヤー技術との比較
- JDBC
- Java コードに SQL が高度な結合で混在しているため、ハードコーディングに内部損傷が発生します。
- メンテナンスは難しく、実際の開発要件では SQL が変更され、頻繁に修正が行われることが一般的です。
- コードが長くて開発効率が低い
- Hibernate と JPA
- 操作が簡単で開発効率が高い
- プログラム内の長くて複雑な SQL はフレームワークをバイパスする必要がある
- 内部で自動生成されるSQLは特別な最適化を行うのが容易ではありません。
- フルマッピングの全自動フレームワークに基づいて、フィールド数が多い POJO を部分的にマッピングすることは困難です。
- リフレクション操作が多すぎるとデータベースのパフォーマンスが低下する
- マイバティス
- 軽量、優れたパフォーマンス
- SQL と Java のコーディングは分離されており、機能の境界は明確です。Java コードはビジネスに重点を置き、SQL ステートメントはデータに重点を置きます
- 開発効率は HIbernate より若干劣りますが、十分許容範囲です。
第2章 Mybatisの基本的な使い方
セクション 1 ハローワールド
1. 物理モデリング
CREATE DATABASE `mybatis-example`;
USE `mybatis-example`;
CREATE TABLE `t_emp`(
emp_id INT AUTO_INCREMENT,
emp_name CHAR(100),
emp_salary DOUBLE(10,5),
PRIMARY KEY(emp_id)
);
INSERT INTO `t_emp`(emp_name,emp_salary) VALUES("tom",200.33);
INSERT INTO `t_emp`(emp_name,emp_salary) VALUES("jerry",666.66);
INSERT INTO `t_emp`(emp_name,emp_salary) VALUES("andy",777.77);
2. ロジックモデリング
①Mavenモジュールを作成する
②Javaエンティティクラスの作成
エンティティ クラスは、現実世界の特定または抽象的な概念に対応し、ソフトウェア開発プロセス中に現実世界のデータを管理するために設計されたモデルです。
エンティティ クラスにはいくつかの異なる名前があります。
ドメイン: ドメインモデル
エンティティ: エンティティ
POJO:Plain Old Java オブジェクト
Java Bean: Java クラス
/**
* 和数据库表 t_emp 对应的实体类
* emp_id INT AUTO_INCREMENT
* emp_name CHAR(100)
* emp_salary DOUBLE(10,5)
*
* Java 的实体类中,属性的类型不要使用基本数据类型,要使用包装类型。因为包装类型可以赋值为null,表示空,而基本数据类型不可以。
*/
public class Employee {
private Integer empId;
private String empName;
private Double empSalary;
public Employee() {
}
public Integer getEmpId() {
return empId;
}
public void setEmpId(Integer empId) {
this.empId = empId;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public Double getEmpSalary() {
return empSalary;
}
public void setEmpSalary(Double empSalary) {
this.empSalary = empSalary;
}
@Override
public String toString() {
return "Employee{" +
"empId=" + empId +
", empName='" + empName + '\'' +
", empSalary=" + empSalary +
'}';
}
public Employee(Integer empId, String empName, Double empSalary) {
this.empId = empId;
this.empName = empName;
this.empSalary = empSalary;
}
}
3. フレームワーク開発環境の構築
①依存関係をインポートする
<dependencies>
<!-- Mybatis核心 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
<!-- junit测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- MySQL驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.3</version>
</dependency>
</dependencies>
②設定ファイルの準備
[1]Mybatisグローバル設定ファイル
mybatis-config.xml という名前を付けるのが一般的ですが、このファイル名は単なる提案であり、必須ではありません。将来 Spring が統合された後は、この設定ファイルは省略可能ですので、運用時に直接コピー&ペーストすることができます。
<?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>
<!-- environments表示配置Mybatis的开发环境,可以配置多个环境,在众多具体环境中,使用default属性指定实际运行时使用的环境。default属性的取值是environment标签的id属性的值。 -->
<environments default="development">
<!-- environment表示配置Mybatis的一个具体的环境 -->
<environment id="development">
<!-- Mybatis的内置的事务管理器 -->
<transactionManager type="JDBC"/>
<!-- 配置数据源 -->
<dataSource type="POOLED">
<!-- 建立数据库连接的具体信息 -->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis-example"/>
<property name="username" value="root"/>
<property name="password" value="atguigu"/>
</dataSource>
</environment>
</environments>
<mappers>
<!-- Mapper注册:指定Mybatis映射文件的具体位置 -->
<!-- mapper标签:配置一个具体的Mapper映射文件 -->
<!-- resource属性:指定Mapper映射文件的实际存储位置,这里需要使用一个以类路径根目录为基准的相对路径 -->
<!-- 对Maven工程的目录结构来说,resources目录下的内容会直接放入类路径,所以这里我们可以以resources目录为基准 -->
<mapper resource="mappers/EmployeeMapper.xml"/>
</mappers>
</configuration>
注: 構成ファイルは src/main/resources ディレクトリに保存されます。
[2]Mybatisマッピングファイル
関連概念: ORM (オブジェクト関係マッピング) オブジェクト関係マッピング。
- オブジェクト: Javaエンティティクラスオブジェクト
- リレーショナル: リレーショナル データベース
- マッピング: 2 つの間の対応関係
次の表は、最も単純な単一テーブル マッピング (1 つのテーブルと 1 つのクラス) を示しています。
Javaの概念 | データベースの概念 |
---|---|
親切 | 表面 |
属性 | フィールド/列 |
物体 | レコード/行 |
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- mapper是根标签,namespace属性:在Mybatis全局范围内找到一个具体的Mapper配置 -->
<!-- 引入接口后,为了方便通过接口全类名来找到Mapper配置文件,所以通常将namespace属性设置为接口全类名 -->
<mapper namespace="com.atguigu.mybatis.dao.EmployeeMapper">
<!-- 编写具体的SQL语句,使用id属性唯一的标记一条SQL语句 -->
<!-- resultType属性:指定封装查询结果的Java实体类的全类名 -->
<select id="selectEmployee" resultType="com.atguigu.mybatis.entity.Employee">
<!-- Mybatis负责把SQL语句中的#{}部分替换成“?”占位符,在#{}内部还是要声明一个见名知意的名称 -->
select emp_id empId,emp_name empName,emp_salary empSalary from t_emp where emp_id=#{empId}
</select>
</mapper>
注: EmployeeMapper.xml が配置されているディレクトリは、mybatis-config.xml の Mapper タグを使用して構成されたディレクトリと一致している必要があります。
4. junit テストコード
@Test
public void testSelectEmployee() throws IOException {
// 1.创建SqlSessionFactory对象
// ①声明Mybatis全局配置文件的路径
String mybatisConfigFilePath = "mybatis-config.xml";
// ②以输入流的形式加载Mybatis配置文件
InputStream inputStream = Resources.getResourceAsStream(mybatisConfigFilePath);
// ③基于读取Mybatis配置文件的输入流创建SqlSessionFactory对象
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 2.使用SqlSessionFactory对象开启一个会话
SqlSession session = sessionFactory.openSession();
// 3.根据Mapper配置文件的名称空间+SQL语句的id找到具体的SQL语句
// 格式是:名称空间.SQL语句的id
String statement = "com.atguigu.mybatis.dao.EmployeeMapper.selectEmployee";
// 要传入SQL语句的参数
Integer empId = 1;
// 执行SQL语句
Object result = session.selectOne(statement, empId);
System.out.println("o = " + result);
// 4.关闭SqlSession
session.close();
}
例証します:
- SqlSession: Java プログラムとデータベース間のセッションを表します。(HttpSession は Java プログラムとブラウザ間のセッションです)
- SqlSessionFactory: SqlSession を「生成」する「ファクトリー」です。
- ファクトリ パターン: オブジェクトの作成に使用されるプロセスが基本的に固定されている場合、このオブジェクトを作成するための関連コードを「ファクトリ クラス」にカプセル化し、このファクトリ クラスを使用して将来必要なオブジェクトを「生成」できます。
5.誤解を正す
①誤解
初めてフレームワークに触れるとき、Java プログラムは実行のために XML 構成ファイルに転送されると考えますが、実際には、フレームワークは初期化中に XML ファイルを読み取り、それをオブジェクトにカプセル化してから、すべての処理を実行します。 Java コードは実行されますが、XML の設定は実行できません。
②イラスト
③ソースコード
[1] 構成オブジェクトのカプセル化
クラス: org.apache.ibatis.session.defaults.DefaultSqlSessionFactory
[2] マップされた命令を取得する準備をする
クラス: org.apache.ibatis.session.defaults.DefaultSqlSession
[3] マップされた命令を正式に入手する
クラス: org.apache.ibatis.session.Configuration
[4]mappedStatements オブジェクト構造
mappedStatements オブジェクトの種類: Configuration クラスの静的内部クラス: StrictMap
セクション 2 HelloWorld の機能強化
1. ログを追加する
①目的
Mybatis の作業プロセスでは、実行される SQL ステートメントがログの出力によって出力されます。
②操作
[1]依存関係を追加する
<!-- log4j日志 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
[2] log4j設定ファイルの追加
XML ファイルとプロパティ ファイルの両方をサポートします。どの形式が使用されるかに関係なく、ファイル名は固定されます。
- log4j.xml
- log4j.プロパティ
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
<param name="Encoding" value="UTF-8" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS} %m (%F:%L) \n" />
</layout>
</appender>
<logger name="java.sql">
<level value="debug" />
</logger>
<logger name="org.apache.ibatis">
<level value="info" />
</logger>
<root>
<level value="debug" />
<appender-ref ref="STDOUT" />
</root>
</log4j:configuration>
③ログレベル
FATAL(致命的)>ERROR(エラー)>WARN(警告)>INFO(情報)>DEBUG(デバッグ)
左から右に印刷されるコンテンツはますます詳細になります
④標準出力
Standard Outputの略で、標準出力という意味です。Java プログラムの場合、標準出力への出力はコンソールへの出力を意味します。
⑤プリント効果
デバッグ 05-24 18:51:13,331 ==> 準備中: t_emp から emp_id empId,emp_name empName,emp_salary empSalary を選択します (emp_id=?) (BaseJdbcLogger.java:137) デバッグ 05-24 18:51:13,371 ==> パラメータ: 1(整数) (BaseJdbcLogger.java:137) デバッグ 05-24 18:51:13,391 <== 合計: 1 (BaseJdbcLogger. java:137) o = 従業員{empId=1, empName='tom', empSalary=200.33}
2. 外部プロパティファイルを関連付ける
①需要
実際の開発では、同じコード セットが複数の異なる特定のサーバー環境に対応することがよくあります。使用されるデータベース接続パラメータも異なります。この情報をより適切に維持するために、データベース接続情報を Mybatis グローバル構成ファイルの外部に抽出することをお勧めします。
②やり方
jdbc.properties 構成ファイルを作成する
wechat.dev.driver=com.mysql.jdbc.Driver
wechat.dev.url=jdbc:mysql://192.168.198.100:3306/mybatis-example
wechat.dev.username=root
wechat.dev.password=atguigu
wechat.test.driver=com.mysql.jdbc.Driver
wechat.test.url=jdbc:mysql://192.168.198.150:3306/mybatis-example
wechat.test.username=root
wechat.test.password=atguigu
wechat.product.driver=com.mysql.jdbc.Driver
wechat.product.url=jdbc:mysql://192.168.198.200:3306/mybatis-example
wechat.product.username=root
wechat.product.password=atguigu
Mybatis グローバル構成ファイル内の外部 jdbc.properties ファイルの場所を指定します。
<properties resource="jdbc.properties"/>
特定の属性値が必要な場合は、${key} 形式を使用して属性ファイル内のキーを参照します。
<dataSource type="POOLED">
<!-- 建立数据库连接的具体信息(引用了外部属性文件中的数据) -->
<property name="driver" value="${wechat.dev.driver}"/>
<property name="url" value="${wechat.dev.url}"/>
<property name="username" value="${wechat.dev.username}"/>
<property name="password" value="${wechat.dev.password}"/>
</dataSource>
3. マッパーインターフェイスを使用する
Mybatis の Mapper インターフェイスは、以前の Dao と同等です。ただし、異なる点は、Mapper はインターフェイスを構築するだけであり、実装クラスを提供する必要がないことです。
①思考
②junitコードを調整する
public class ImprovedMybatisTest {
private SqlSession session;
// junit会在每一个@Test方法前执行@Before方法
@Before
public void init() throws IOException {
session = new SqlSessionFactoryBuilder()
.build(
Resources.getResourceAsStream("mybatis-config.xml"))
.openSession();
}
// junit会在每一个@Test方法后执行@After方法
@After
public void clear() {
session.commit();
session.close();
}
}
③ マッパーインターフェースを完成させる
public interface EmployeeMapper {
Employee selectEmployee(Integer empId);
}
- メソッド名は SQL ID と一致します。
- メソッドの戻り値は resultType と一致します
- メソッドのパラメータは SQL のパラメータと一致しています
- インターフェイスの完全なクラス名は、マッピング構成ファイルの名前空間と一致しています。
④最終的なjunitテスト方法
@Test
public void testUsrMapperInterface() {
// 1.根据EmployeeMapper接口的Class对象获取Mapper接口类型的对象
EmployeeMapper employeeMapper = session.getMapper(EmployeeMapper.class);
// 2.调用EmployeeMapper接口的方法完成对数据库的操作
Emp emp = employeeMapper.selectEmployee(1L);
// 3.打印查询结果
System.out.println("emp = " + emp);
}
4. 操作の追加、削除、変更
①入れる
SQL文
<insert id="insertEmployee">
<!-- 现在在这条SQL语句中,#{}中的表达式需要被用来从Emp emp实体类中获取emp_name的值、emp_salary的值 -->
<!-- 而我们从实体类中获取值通常都是调用getXxx()方法 -->
<!-- 而getXxx()方法、setXxx()方法定义了实体类的属性 -->
<!-- 定义属性的规则是:把get、set去掉,剩下部分首字母小写 -->
<!-- 所以我们在#{}中使用getXxx()方法、setXxx()方法定义的属性名即可 -->
insert into t_emp(emp_name,emp_salary) values(#{empName},#{empSalary})
</insert>
Java コードのマッパー インターフェイス:
public interface EmployeeMapper {
Employee selectEmployee(Integer empId);
int insertEmployee(Employee employee);
}
Javaコードでのjunitテスト:
@Test
public void testSaveEmployee() {
EmployeeMapper employeeMapper = session.getMapper(EmployeeMapper.class);
// 创建要保存到数据库的对象
Employee employee = new Employee();
// 给实体类对象设置具体属性值
employee.setEmpName("jerry");
employee.setEmpSalary(5000.33);
// 执行保存操作
int result = employeeMapper.insertEmployee(employee);
// 打印受影响的行数
System.out.println("result = " + result);
}
②削除
SQL文
<delete id="deleteEmployee">
delete from t_emp where emp_id=#{empId}
</delete>
Java コードのマッパー インターフェイス:
public interface EmployeeMapper {
Employee selectEmployee(Integer empId);
int insertEmployee(Employee employee);
int deleteEmployee(Integer empId);
}
Javaコードでのjunitテスト:
@Test
public void testRemoveEmployee() {
EmployeeMapper employeeMapper = session.getMapper(EmployeeMapper.class);
int result = employeeMapper.deleteEmployee(1);
System.out.println("result = " + result);
}
③アップデート
SQL ステートメント:
<update id="updateEmployee">
update t_emp set emp_name=#{empName},emp_salary=#{empSalary} where emp_id=#{empId}
</update>
Java コードのマッパー インターフェイス:
public interface EmployeeMapper {
Employee selectEmployee(Integer empId);
int insertEmployee(Employee employee);
int deleteEmployee(Integer empId);
int updateEmployee(Employee employee);
}
Javaコードでのjunitテスト:
@Test
public void testUpdateEmployee() {
EmployeeMapper employeeMapper = session.getMapper(EmployeeMapper.class);
Employee employee = new Employee(2, "AAAAAA", 6666.66);
int result = employeeMapper.updateEmployee(employee);
System.out.println("result = " + result);
}
セクション 3 SQL ステートメントにパラメータを渡す
1. #{}メソッド
実行プロセス中に、Mybatis は構成ファイル内の SQL ステートメントの #{} を「?」プレースホルダーに変換し、実行のためにデータベースに送信します。
構成ファイル内の SQL:
<delete id="deleteEmployeeById">
delete from t_emp where emp_id=#{empId}
</delete>
実際に実行されたSQL:
delete from t_emp where emp_id=?
2. ${} メソッド
将来的には、文字列は ${} に基づいて綴られるようになるでしょう。
①SQL文
<select id="selectEmployeeByName" resultType="com.atguigu.mybatis.entity.Employee">
select emp_id empId,emp_name empName,emp_salary empSalary from t_emp where emp_name like '%${empName}%'
</select>
②マッパーインターフェース
注: Mapper インターフェイスのメソッド名は SQL ステートメント ラベルの ID であり、繰り返すことはできないため、同じ名前のメソッドを Mapper インターフェイスに表示することはできず、オーバーロードは許可されません。
public interface EmployeeMapper {
Employee selectEmployee(Integer empId);
Employee selectEmployeeByName(@Param("empName") String empName);
int insertEmployee(Employee employee);
int deleteEmployee(Integer empId);
int updateEmployee(Employee employee);
}
③junitテスト
@Test
public void testDollar() {
EmployeeMapper employeeMapper = session.getMapper(EmployeeMapper.class);
Employee employee = employeeMapper.selectEmployeeByName("r");
System.out.println("employee = " + employee);
}
④実際に出力されたSQL
select emp_id empId,emp_name empName,emp_salary empSalary from t_emp where emp_name like '%r%'
⑤活用シーン例
SQL 文では、データベース テーブルのテーブル名が不定であるため、外部から動的に入力する必要がありますが、SQL 構文ではテーブル名に疑問符プレースホルダを使用できないため、このとき #{} は使用できません現時点では、${} のみを使用できます。
それ以外の場合は、#{} が使用できる限り、SQL インジェクションを回避するために ${} を使用してはなりません。
セクション 4 データ入力
1. Mybatisの全体的な仕組みの概要
2. コンセプトの説明
ここでのデータ入力とは、具体的には、上位層のメソッド (Service メソッドなど) が Mapper インターフェイスを呼び出すときにデータが渡される形式を指します。
- 単純型: 値を 1 つだけ含むデータ型
- 基本データ型: int、byte、short、double、…
- 基本データ型のパッケージ化タイプ: Integer、Character、Double など
- 文字列タイプ: 文字列
- 複合型: 複数の値を含むデータ型
- エンティティ クラス タイプ: 従業員、部門など
- コレクションの種類: リスト、セット、マップなど
- 配列型: int[]、String[]、…
- 複合タイプ: List<Employee>、エンティティ クラスにはコレクションが含まれています...
3. 単一の単純型パラメータ
①Mapperインターフェースでの抽象メソッドの宣言
Employee selectEmployee(Integer empId);
②SQL文
<select id="selectEmployee" resultType="com.atguigu.mybatis.entity.Employee">
select emp_id empId,emp_name empName,emp_salary empSalary from t_emp where emp_id=#{empId}
</select>
4. エンティティクラス型パラメータ
①Mapperインターフェースでの抽象メソッドの宣言
int insertEmployee(Employee employee);
②SQL文
<insert id="insertEmployee">
insert into t_emp(emp_name,emp_salary) values(#{empName},#{empSalary})
</insert>
③対応
④結論
Mybatis は #{} で渡されたデータに基づいて getXxx() メソッドを処理し、リフレクションを通じてエンティティ クラス オブジェクトでこのメソッドを呼び出して、対応するデータを取得します。#{} の位置を埋めます。
5. 散在する単純型データ
①Mapperインターフェースでの抽象メソッドの宣言
int updateEmployee(@Param("empId") Integer empId,@Param("empSalary") Double empSalary);
②SQL文
<update id="updateEmployee">
update t_emp set emp_salary=#{empSalary} where emp_id=#{empId}
</update>
③対応
6. マップタイプパラメータ
①Mapperインターフェースでの抽象メソッドの宣言
int updateEmployeeByMap(Map<String, Object> paramMap);
②SQL文
<update id="updateEmployeeByMap">
update t_emp set emp_salary=#{empSalaryKey} where emp_id=#{empIdKey}
</update>
③junitテスト
@Test
public void testUpdateEmpNameByMap() {
EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("empSalaryKey", 999.99);
paramMap.put("empIdKey", 5);
int result = mapper.updateEmployeeByMap(paramMap);
System.out.println("result = " + result);
}
④対応
{}内のマップにキーを書き込みます
⑤利用シーン
渡す必要がある散在パラメータが多数ありますが、対応するエンティティ クラス タイプは使用できません。@Param アノテーションを使用して 1 つずつ渡すのは面倒すぎます。したがって、それらはすべて Map にカプセル化されます。
セクション 5 データ出力
ヒント
データ出力は通常、次の 2 つの形式で行われます。
- 追加、削除、および変更操作によって返される、影響を受ける行の数。直接受け取るには、int または long 型を使用するだけです。
- クエリ操作のクエリ結果
1. 単一の単純型データを返します。
①Mapperインターフェースの抽象メソッド
int selectEmpCount();
②SQL文
<select id="selectEmpCount" resultType="int">
select count(*) from t_emp
</select>
③junitテスト
@Test
public void testEmpCount() {
EmployeeMapper employeeMapper = session.getMapper(EmployeeMapper.class);
int count = employeeMapper.selectEmpCount();
System.out.println("count = " + count);
}
ヒント
Mybatis は、一般的に使用されるデータ型に対して多くのエイリアスを内部的に設定します。int型を例にとると、記述できる名前は、int、integer、Integer、java.lang.Integer、Int、INT、INTEGERなどです。
2. エンティティクラスオブジェクトを返す
①Mapperインターフェースの抽象メソッド
Employee selectEmployee(Integer empId);
②SQL文
<!-- 编写具体的SQL语句,使用id属性唯一的标记一条SQL语句 -->
<!-- resultType属性:指定封装查询结果的Java实体类的全类名 -->
<select id="selectEmployee" resultType="com.atguigu.mybatis.entity.Employee">
<!-- Mybatis负责把SQL语句中的#{}部分替换成“?”占位符 -->
<!-- 给每一个字段设置一个别名,让别名和Java实体类中属性名一致 -->
select emp_id empId,emp_name empName,emp_salary empSalary from t_emp where emp_id=#{maomi}
</select>
データベース テーブルのフィールドにエイリアスを追加すると、クエリ結果の各列が Java エンティティ クラスの属性に対応します。
③対応関係を自動認識するグローバル設定を追加
Mybatisのグローバル設定ファイルでは以下のような設定になっており、select文のフィールドにエイリアスを設定する必要はありません。
<!-- 在全局范围内对Mybatis进行配置 -->
<settings>
<!-- 具体配置 -->
<!-- 从org.apache.ibatis.session.Configuration类中可以查看能使用的配置项 -->
<!-- 将mapUnderscoreToCamelCase属性配置为true,表示开启自动映射驼峰式命名规则 -->
<!-- 规则要求数据库表字段命名方式:单词_单词 -->
<!-- 规则要求Java实体类属性名命名方式:首字母小写的驼峰式命名 -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
3. マップの種類を返す
SQL クエリによって返されるフィールドは、既存のエンティティ クラスに対応しないため、エンティティ クラス オブジェクトにカプセル化できません。エンティティ クラス タイプにカプセル化できる場合、Map タイプは使用されません。
①Mapperインターフェースの抽象メソッド
Map<String,Object> selectEmpNameAndMaxSalary();
②SQL文
<!-- Map<String,Object> selectEmpNameAndMaxSalary(); -->
<!-- 返回工资最高的员工的姓名和他的工资 -->
<select id="selectEmpNameAndMaxSalary" resultType="map">
SELECT
emp_name 员工姓名,
emp_salary 员工工资,
(SELECT AVG(emp_salary) FROM t_emp) 部门平均工资
FROM t_emp WHERE emp_salary=(
SELECT MAX(emp_salary) FROM t_emp
)
</select>
③junitテスト
@Test
public void testQueryEmpNameAndSalary() {
EmployeeMapper employeeMapper = session.getMapper(EmployeeMapper.class);
Map<String, Object> resultMap = employeeMapper.selectEmpNameAndMaxSalary();
Set<Map.Entry<String, Object>> entrySet = resultMap.entrySet();
for (Map.Entry<String, Object> entry : entrySet) {
String key = entry.getKey();
Object value = entry.getValue();
System.out.println(key + "=" + value);
}
}
4. 戻り値リストの型
クエリ結果は複数のエンティティ クラス オブジェクトを返します。複数のエンティティ クラス オブジェクトを List コレクションに入れて返したいと考えています。この時点では特別な処理は必要ありません。resultType 属性にエンティティ クラスのタイプを設定するだけです。
①Mapperインターフェースの抽象メソッド
List<Employee> selectAll();
②SQL文
<!-- List<Employee> selectAll(); -->
<select id="selectAll" resultType="com.atguigu.mybatis.entity.Employee">
select emp_id empId,emp_name empName,emp_salary empSalary
from t_emp
</select>
③junitテスト
@Test
public void testSelectAll() {
EmployeeMapper employeeMapper = session.getMapper(EmployeeMapper.class);
List<Employee> employeeList = employeeMapper.selectAll();
for (Employee employee : employeeList) {
System.out.println("employee = " + employee);
}
}
5. 自動インクリメント主キーに戻ります
①利用シーン
例: 注文情報を保存します。Order オブジェクトと List<OrderItem> を保存する必要があります。このうち、OrderItem に対応するデータベース テーブルには、Order に対応するテーブルの主キーを指す外部キーが含まれています。
List<OrderItem> を保存するときは、次の SQL を使用する必要があります。
insert into t_order_item(item_name,item_price,item_count,order_id) values(...)
ここで使用する必要がある order_id は、Order オブジェクトの保存時にデータベース テーブルによって自動インクリメント方式で生成されます。この自動インクリメントされる主キー値を取得するには、特別なメソッドが必要です。最大の主キーをクエリしてもこの問題を解決できない理由については、次の図を参照してください。
②Mapper設定ファイルにメソッドを設定する
[1]Mapperインターフェースの抽象メソッド
int insertEmployee(Employee employee);
[2]SQL文
<!-- int insertEmployee(Employee employee); -->
<!-- useGeneratedKeys属性字面意思就是“使用生成的主键” -->
<!-- keyProperty属性可以指定主键在实体类对象中对应的属性名,Mybatis会将拿到的主键值存入这个属性 -->
<insert id="insertEmployee" useGeneratedKeys="true" keyProperty="empId">
insert into t_emp(emp_name,emp_salary)
values(#{empName},#{empSalary})
</insert>
[3]junitテスト
@Test
public void testSaveEmp() {
EmployeeMapper employeeMapper = session.getMapper(EmployeeMapper.class);
Employee employee = new Employee();
employee.setEmpName("john");
employee.setEmpSalary(666.66);
employeeMapper.insertEmployee(employee);
System.out.println("employee.getEmpId() = " + employee.getEmpId());
}
④注意事項
Mybatis は、自動インクリメント主キーの値を、Mapper インターフェイス メソッドの戻り値の形式で返すのではなく、エンティティ クラス オブジェクトに設定します。
⑤主キーの自動インクリメントをサポートしていないデータベース
自動インクリメント主キーをサポートしていないデータベース (Oracle など) の場合は、selectKey サブ要素を使用できます。最初に selectKey 要素が実行され、ID が設定されてから、insert ステートメントが呼び出されます。
<insert id="insertEmployee"
parameterType="com.atguigu.mybatis.beans.Employee"
databaseId="oracle">
<selectKey order="BEFORE" keyProperty="id"
resultType="integer">
select employee_seq.nextval from dual
</selectKey>
insert into orcl_employee(id,last_name,email,gender) values(#{id},#{lastName},#{email},#{gender})
</insert>
または
<insert id="insertEmployee"
parameterType="com.atguigu.mybatis.beans.Employee"
databaseId="oracle">
<selectKey order="AFTER" keyProperty="id"
resultType="integer">
select employee_seq.currval from dual
</selectKey>
insert into orcl_employee(id,last_name,email,gender) values(employee_seq.nextval,#{lastName},#{email},#{gender})
</insert>
6. データベーステーブルのフィールドとエンティティクラスの属性の対応
①別名
エンティティ クラス属性と一致するようにフィールド エイリアスを設定します。
<!-- 编写具体的SQL语句,使用id属性唯一的标记一条SQL语句 -->
<!-- resultType属性:指定封装查询结果的Java实体类的全类名 -->
<select id="selectEmployee" resultType="com.atguigu.mybatis.entity.Employee">
<!-- Mybatis负责把SQL语句中的#{}部分替换成“?”占位符 -->
<!-- 给每一个字段设置一个别名,让别名和Java实体类中属性名一致 -->
select emp_id empId,emp_name empName,emp_salary empSalary from t_emp where emp_id=#{maomi}
</select>
エンティティ クラスの属性に関する規則:
getXxx() メソッドおよび setXxx() メソッドの場合は、メソッド名から get または set を削除し、最初の文字を小文字にします。
②キャメルケースの命名ルールを自動認識するグローバル設定
次の設定を Mybatis グローバル設定ファイルに追加します。
<!-- 使用settings对Mybatis全局进行设置 -->
<settings>
<!-- 将xxx_xxx这样的列名自动映射到xxXxx这样驼峰式命名的属性名 -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
SQL ステートメントでエイリアスを使用する必要はありません
<!-- Employee selectEmployee(Integer empId); -->
<select id="selectEmployee" resultType="com.atguigu.mybatis.entity.Employee">
select emp_id,emp_name,emp_salary from t_emp where emp_id=#{empId}
</select>
③resultMapを利用する
resultMap タグを使用して対応関係を定義し、後続の SQL ステートメントでこの対応関係を参照します。
<!-- 专门声明一个resultMap设定column到property之间的对应关系 -->
<resultMap id="selectEmployeeByRMResultMap" type="com.atguigu.mybatis.entity.Employee">
<!-- 使用id标签设置主键列和主键属性之间的对应关系 -->
<!-- column属性用于指定字段名;property属性用于指定Java实体类属性名 -->
<id column="emp_id" property="empId"/>
<!-- 使用result标签设置普通字段和Java实体类属性之间的关系 -->
<result column="emp_name" property="empName"/>
<result column="emp_salary" property="empSalary"/>
</resultMap>
<!-- Employee selectEmployeeByRM(Integer empId); -->
<select id="selectEmployeeByRM" resultMap="selectEmployeeByRMResultMap">
select emp_id,emp_name,emp_salary from t_emp where emp_id=#{empId}
</select>