アーキテクチャMyBatisのとMyBatisののまず、全体的な理解

、MyBatisのコアコンセプト


知識ポイント

  1. 基本コンセプト
  2. コアターゲットスコープとライフサイクル
  3. プログラミングインタフェース

1、基本的な考え方

MyBatisのは、カスタムSQL、ストアドプロシージャと高度なマッピングをサポートしている優れた永続化フレームワークです。MyBatisのは、ほぼすべてのJDBCコードとマニュアル設定パラメータを回避し、結果セットを取得します。MyBatisの構成およびデータベース・レコードへのネイティブ情報、インターフェースおよびJavaのPOJO(プレーン通常のJavaオブジェクト、通常のJavaオブジェクト)をマッピングするために、単純なXMLまたは注釈を使用することができます。

その他の永続化ソリューション:JDBC、DBUtils、JdbcTemplate、休止状態

図2に示すように、コア対象範囲とライフサイクル

1)データベーステーブルを作成します。ユーザーを

CREATE TABLE `user` (
  `id` tinyint(4) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) DEFAULT NULL,
  `create_time` datetime DEFAULT NULL,
  `update_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
复制代码

2)新しいPOJOエンティティクラス:ユーザー

public class User implements Serializable {

    private static final long serialVersionUID = -6611101295813775324L;

    private Integer id;
    private String name;
    private Date createTime;
    private Long updateTime;

    //省略setter、getter方法
}
复制代码

jdbc.properties:3)データベース接続プロパティを設定

jdbc.driverClassName=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true
jdbc.username=root
jdbc.password=root
default.environment=dev
复制代码

4)設定MyBatisのプロフィール: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="jdbc.properties"></properties>

    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>

    <environments default="${default.environment}">
        <environment id="dev">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driverClassName}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>

    <mappers
        <mapper resource="mapper/UserMapper.xml"></mapper>
    </mappers>
</configuration>
复制代码

5)カスタムプロセッサの種類:CustomHandler

@MappedJdbcTypes(JdbcType.TIMESTAMP)
@MappedTypes(Long.class)
public class CustomHandler extends BaseTypeHandler<Long> {

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Long parameter, JdbcType jdbcType) throws SQLException {
        //ps.setDate(i,new Date(parameter));
        ps.setTimestamp(i,new Timestamp(parameter));
    }

    @Override
    public Long getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return rs.getDate(columnName).getTime();
    }

    @Override
    public Long getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return rs.getDate(columnIndex).getTime();
    }

    @Override
    public Long getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return cs.getDate(columnIndex).getTime();
    }
}
复制代码

6)mapper.xml設定ファイル:UserMapper.xml

<?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="com.cyan.mapper.UserMapper">
    <resultMap id="baseResultMap" type="com.cyan.pojo.User">
        <id property="id" column="id" jdbcType="INTEGER"></id>
        <result property="name" column="name" jdbcType="VARCHAR"></result>
        <result property="createTime" column="create_time" jdbcType="TIMESTAMP"></result>
        <result property="updateTime" column="update_time" jdbcType="TIMESTAMP" typeHandler="com.cyan.handler.CustomHandler"></result>
    </resultMap>

    <select id="selectUserById" parameterType="java.lang.Integer" resultMap="baseResultMap">
        select * from user where id = #{id}
    </select>
</mapper>
复制代码

7)テストケースを書く:UserTest

public class UserTest {

    private SqlSession session;

    @Before
    public void init()throws IOException{
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        session = sqlSessionFactory.openSession(true);
    }

    @Test
    public void test01() throws IOException {
        User result = session.selectOne("com.cyan.mapper.UserMapper.selectUserById", 1);
        System.out.println(result.toString());
    }
}
复制代码

SqlSessionFactoryBuilder:完了後に使い捨てできるように構築セッションを構築するために使用される植物、ベースMyBatisの-config.xmlの環境、小道具の工場の建物セッション、。

SqlSessionFactory:一般的に、アプリケーション全体の動作中に動作するセッションを生成するために使用される植物、オブジェクトプラントの複数を構築する必要はありません

SQLSESSION:それは、スレッドセーフであるため、このようなWEB要求として、単一のセッションに作用する時には、画像の属性で使用することはできませんが、複数のスレッド間で共有することはできません。

図3に示すように、プログラミング・インターフェース

すべてので、特に友好的ではないを使用して、アプリケーションの声明とアセンブリのパラメータの呼び出しごとに行ってきました

MyBatisのインタフェースメカニズムが導入され、名前空間名は、結合mapper.xmlインターフェースは、インターフェースのMyBatisのインスタンスを動的ASMツールに応じて構築することができます。

1)マッパーインターフェイスを作成:UserMapperを

User selectUser(Integer id);
复制代码

2)mapper.xml設定ファイル:UserMapper.xml

<select id="selectUser" resultType="com.tuling.ssm.pojo.User">
    select * from user where id = #{id}
</select>
复制代码

3)テストケースを書く:UserTest

UserMapper $proxy = session.getMapper(UserMapper.class);
User user = $proxy.selectUserById(2);
System.out.println(user.toString());
复制代码

第二に、グローバルコンフィギュレーション設定


知識ポイント

  1. プロパティのプロパティ
  2. 環境プロパティ
  3. 属性設定
  4. typeAliasesプロパティ
  5. typeHandlersプロパティ
  6. マッパーマッパー

図1に示すように、プロパティのプロパティ

properties要素のプロパティは、プロパティ属性が直接提供することができる、外部リソースファイル属性またはURLを読み込むことができます。その後、XMLで参照プロパティ名$ {}で置き換えることができます。

<properties resource="jdbc.properties"></properties>
复制代码

ウェイ参照プロパティ

${jdbc.driverClassName}
# MyBatis3.4.2开始,支持指定默认值
${jdbc.driverClassName:com.mysql.jdbc.Driver}
复制代码

2、環境プロパティ

プロジェクトは、しばしば、このような悪い環境を開発するなどの特性、試験環境、前にオンライン環境、異なる環境展開における生産培地を必要とする、に対応する各パラメータの設定は、同じではないMyBatisの環境のことで異なる環境に配置されてもよいということです。

# 指定应用环境
default.environment=dev
复制代码
<environments default="${default.environment}">
    <environment id="dev">
        <transactionManager type="JDBC"/>
        <dataSource type="POOLED">
            <property name="driver" value="${jdbc.driverClassName}"/>
            <property name="url" value="${jdbc.url}"/>
            <property name="username" value="${jdbc.username}"/>
            <property name="password" value="${jdbc.password}"/>
        </dataSource>
    </environment>
    <environment id="test">
        <transactionManager type="JDBC"/>
        <dataSource type="POOLED">
            <property name="driver" value="${jdbc.driverClassName}"/>
            <property name="url" value="${jdbc.url}"/>
            <property name="username" value="${jdbc.username}"/>
            <property name="password" value="${jdbc.password}"/>
        </dataSource>
    </environment>
</environments>
复制代码

3、設定のプロパティ

MyBatisのは、グローバルパラメータを設定しMyBatisのグローバルな振る舞いを合意しました

<settings>
    <setting name="cacheEnabled" value="true"/>
    <setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
复制代码

4、typeAliasesプロパティ

多くの場合、JavaでこのようなブロックのSQLのJavaTypeパラメータセット、結果セットマップのJavaType等のタイプを、MyBatisの使用フルパス名のJavaを使用する必要があり、別名によって提供されてもよいtypeAliases属性

<typeAliases>
    <!--<typeAlias type="com.cyan.pojo.User" alias="User"></typeAlias>-->
    <package name="com.cyan.pojo"></package>
</typeAliases>
复制代码

5、typeHandlersプロパティ

永続化フレームワークは、Javaの型JDBCの型パラメータに変換し、より重要な仕事マッピングデータ変換処理の1、および統合型のJDBC Java型の結果を変換する必要があります。これは、中TypeHandlerインターフェースMyBatisのによって達成されます。

カスタム型プロセッサ

public class CustomHandler extends BaseTypeHandler<Long> {

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Long parameter, JdbcType jdbcType) throws SQLException {
        //ps.setDate(i,new Date(parameter));
        ps.setTimestamp(i,new Timestamp(parameter));
    }

    @Override
    public Long getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return rs.getDate(columnName).getTime();
    }

    @Override
    public Long getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return rs.getDate(columnIndex).getTime();
    }

    @Override
    public Long getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return cs.getDate(columnIndex).getTime();
    }
}
复制代码

プロファイルウェイアプリケーション

<typeHandlers>
    <typeHandler handler="com.cyan.handler.CustomHandler"
                 javaType="long" jdbcType="TIMESTAMP" />
</typeHandlers>
复制代码

Notesアプリケーションモード

@MappedJdbcTypes(JdbcType.TIMESTAMP)
@MappedTypes(Long.class)
public class CustomHandler extends BaseTypeHandler<Long> {}
复制代码

6、マッパーマッパー

<mappers>
    <mapper resource="mapper/UserMapper.xml"></mapper>
    <mapper resource="mapper/AccountMapper.xml"></mapper>
    <!-- mapper与对应的xml文件必须在一个包下 -->
    <!--<mapper class="com.cyan.mapper.UserMapper"/>-->
    <!--<package name="com.cyan.mapper"/>-->
</mappers>
复制代码

リソース:ベースのクラスパス・ロード・xmlファイル

クラス:ロードベースのインターフェース

パッケージ:パッケージは、ロード、すべてのクラスをスキャン

婚約のルール

1)マッパー名前空間は、対応するインタフェース名に対応する必要があります

クラスまたはパッケージによってロードされたとき2)、XMLファイルが同じディレクトリ・レベル・インターフェースである必要があります

三、マッパーマッピングファイル


知識ポイント

  1. SQLステートメントブロック文
  2. パラメータマッピング
  3. 結果セットマッピング

1. SQLステートメントブロック文

1)マッパーは、共通の要素であります

resultMap – 结果集映射
select – 查询语句
insert – 插入语句
cache – 对给定命名空间的缓存配置
parameterMap - 参数集映射
update – 更新语句
delete – 删除语句
cache-ref - 指定缓存命名空间
sql – 可被其他语句引用的可重用语句块。
复制代码

2)一般的なプロパティを選択

id - 语句块的唯一标识,与接口中方法名称对应
parameterMap - 参数集映射
parameterType - 参数java类型
resultMap - 返回结果映射
resultType - 返回结果java类型
statementType - 预处理类型 
timeout - 超时时间
flushCache - 每次调用都会刷新一二级缓存
useCache - 是否保存至二级缓存当中去
复制代码

3)共通の属性を挿入&更新&削除

id - 语句块的唯一标识,与接口中方法名称对应
parameterMap - 参数集映射
parameterType - 参数java类型
statementType - 预处理类型
timeout - 超时时间
flushCache- true每次调用都会刷新一二级缓存

# insert、update还具有如下三个属性(delete则没有)
keyProperty - 主键对应的java属性,多个用 逗号分割
keyColumn - 主键列,多个用逗号分割
useGeneratedKeys - 插入成功后可以获取到数据库自动生成的主键值
复制代码

2、パラメータマッピング

パラメータマッピングは、次の方法で参照することができる最も強力な機能の一つであり、

1)単純な単一の基準パラメータ:この方法は、唯一のパラメータである場合、任意の参照名によって行うことができます

User selectUserById(Integer id);

<select id="selectUserById" parameterType="java.lang.Integer" resultMap="baseResultMap">
    select * from user where id = #{id}
</select>
复制代码

2)参照複数のパラメータは単純である:indexパラメータによって参照される#{PARAM1}、{#} PARAM2

Integer insertUser(String name, Date createTime, Date updateTime);

<insert id="insertUser">
    insert into user(name,create_time,update_time) values (#{param1},#{param2},#{param3})
</insert>
复制代码

3)オブジェクトの参照属性:直接参照することによってオブジェクト属性名、ネストされたオブジェクトによって参照されます。

Integer saveUser(User user);

<insert id="saveUser" parameterType="com.cyan.pojo.User"
        keyColumn="id" keyProperty="id" useGeneratedKeys="true">
    insert into user(name,create_time,update_time) values (#{name},#{createTime},#{updateTime,typeHandler=com.cyan.handler.CustomHandler})
</insert>
复制代码

4)マップキー基準値

<update id="updateUserById" parameterType="java.util.Map">
    update user set name = #{name},update_time = #{updateTime} where id = #{id}
</update>
复制代码

5)変数名で参照

Integer modifyUserById(@Param("id") Integer id,@Param("name") String name,@Param("updateTime")Date updateTime);

<update id="modifyUserById">
    update user set name = #{name},update_time = #{updateTime} where id = #{id}
</update>
复制代码

6)ステッチパラメータ

参照パラメータ#に基づいて、その原理は?プレースホルダの前処理は、(SQLインジェクションを防ぐために)より良いパフォーマンスとセキュリティを得ることができますが、いくつかの需要はによってある?プレースホルダは、このようないくつかのサブサブライブラリーのように、達成することはできません我々は、動的テーブル構造をスプライスする必要があるテーブルのシーン。たとえば、システムログテーブルが2018_systemlogの年間カットされ、2019_systemlogあなたは次の文によるものとすることができます

@Select("select * from ${year}_user where id = #{id}")
User selectUserTableByYear(String year, Integer id);
复制代码

3、結果は、マッピングを設定します

1)自動マッピングを設定結果

在select中指定resultType=""后无需要任何配置 myBatis会基于resultType中的java类型及属性自动推断生成一个隐示的resultMap,从而完成结果映射
复制代码

2)このresultMap

時には、JDBCおよびJava Beanが、その後、手動でこのresultMapを設定する必要が完全にフィットではありません

<resultMap id="baseResultMap" type="com.cyan.pojo.User">
    <id property="id" column="id" jdbcType="INTEGER"></id>
    <result property="name" column="name" jdbcType="VARCHAR"></result>
    <result property="createTime" column="create_time" jdbcType="TIMESTAMP"></result>
    <result property="updateTime" column="update_time" jdbcType="TIMESTAMP" typeHandler="com.cyan.handler.CustomHandler"></result>
</resultMap>

<select id="selectUserById" parameterType="java.lang.Integer" resultMap="baseResultMap">
    select * from user where id = #{id}
</select>

ID:用于结果集中的唯一标识
result:设置一个某通过字段
property:java属性名
jdbcType:jdbc类型
javaType:java类型
column:数据库列名
typeHandler:类型处理器
复制代码

3)ネストされた結果のマッピング(一から一)

リレーショナルデータベースを作成します。

CREATE TABLE `account` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) DEFAULT NULL,
  `money` int(11) DEFAULT NULL,
  `create_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
复制代码

AccountMapper.xml:

<resultMap id="accountAndUserResultMap" type="com.cyan.pojo.Account">
    <id property="id" column="id"/>
    <association property="user" javaType="com.cyan.pojo.User">
        <id property="id" column="user_id"/>
        <result property="name" column="userName"/>
    </association>
</resultMap>

<select id="getAccountList" resultMap="accountAndUserResultMap">
    SELECT a.*, u.name userName from account a,user u where a.user_id=u.id
</select>
复制代码

4)外部の導入)は、(いずれかを選択します

AccountMapper.xml:

<resultMap id="accountAmpUserResultMap" type="com.cyan.pojo.Account">
    <id property="id" column="id"/>
    <association property="user" javaType="com.cyan.pojo.User"
                 select="com.cyan.mapper.UserMapper.selectUserById" column="user_id">
    </association>
</resultMap>

<select id="selectAccountList" resultMap="accountAmpUserResultMap">
    SELECT a.*, u.name userName from account a,user u where a.user_id=u.id
</select>
复制代码

多く5)ネストマッピング結果(1)

リレーショナルデータベースを作成します。

CREATE TABLE teacher(
    t_id INT PRIMARY KEY AUTO_INCREMENT,
    t_name VARCHAR(20)
);
INSERT INTO teacher(t_name) VALUES('LS1');
INSERT INTO teacher(t_name) VALUES('LS2');

CREATE TABLE class(
    c_id INT PRIMARY KEY AUTO_INCREMENT,
    c_name VARCHAR(20),
    teacher_id INT
);
ALTER TABLE class ADD CONSTRAINT fk_teacher_id FOREIGN KEY (teacher_id) REFERENCES teacher(t_id);
INSERT INTO class(c_name, teacher_id) VALUES('bj_a', 1);
INSERT INTO class(c_name, teacher_id) VALUES('bj_b', 2);

CREATE TABLE student(
    s_id INT PRIMARY KEY AUTO_INCREMENT,
    s_name VARCHAR(20),
    class_id INT
);
INSERT INTO student(s_name, class_id) VALUES('xs_A', 1);
INSERT INTO student(s_name, class_id) VALUES('xs_B', 1);
INSERT INTO student(s_name, class_id) VALUES('xs_C', 1);
INSERT INTO student(s_name, class_id) VALUES('xs_D', 2);
INSERT INTO student(s_name, class_id) VALUES('xs_E', 2);
INSERT INTO student(s_name, class_id) VALUES('xs_F', 2);
复制代码

ClassesMapper.xml:

<!-- 根据 classId 查询对应的班级信息,包括学生,老师 -->
<!-- 方式一:嵌套结果(使用嵌套结果映射来处理重复的联合结果的子集) -->
<resultMap id="baseResultMap1" type="com.cyan.pojo.Classes">
    <id property="id" column="c_id" />
    <id property="name" column="c_name" />
    <association property="teacher" column="teacher_id" javaType="com.cyan.pojo.Teacher">
        <id property="id" column="t_id" />
        <result property="name" column="t_name" />
    </association>
    <collection property="students" column="c_id" ofType="com.cyan.pojo.Student">
        <id property="id" column="s_id" />
        <result property="name" column="s_name" />
    </collection>
</resultMap>

<select id="getClassesById" parameterType="int" resultMap="baseResultMap1">
    select * from class c,teacher t, student s
    where c.teacher_id = t.t_id
    and c.c_id = s.class_id
    and c.c_id = #{id}
</select>
复制代码

外部セレクト6)導入(多数)

ClassesMapper.xml:

<!-- 根据 classId 查询对应的班级信息,包括学生,老师 -->
<!-- 方式二:嵌套查询(通过执行另外一个SQL映射语句来返回预期的复杂类型) -->
<resultMap id="baseResultMap2" type="com.cyan.pojo.Classes">
    <id property="id" column="c_id" />
    <id property="name" column="c_name" />
    <association property="teacher" column="teacher_id" javaType="com.cyan.pojo.Teacher"
        select="com.cyan.mapper.TeacherMapper.getTeacherById" />
    <collection property="students" column="c_id" ofType="com.cyan.pojo.Student"
        select="com.cyan.mapper.StudentMapper.getStudentById"/>
</resultMap>

<select id="findClassesById" parameterType="int" resultMap="baseResultMap2">
    select * from class where c_id = #{id}
</select>
复制代码

TeacherMapper.xml:

<resultMap id="baseResultMap" type="com.cyan.pojo.Teacher">
    <id property="id" column="t_id" />
    <result property="name" column="t_name" />
</resultMap>

<select id="getTeacherById" resultMap="baseResultMap" parameterType="int">
    select * from teacher where t_id = #{id}
</select>
复制代码

StudentMapper.xml:

<resultMap id="baseResultMap" type="com.cyan.pojo.Student">
    <id property="id" column="s_id" />
    <result property="name" column="s_name" />
</resultMap>

<select id="getStudentById" resultMap="baseResultMap" parameterType="int">
    select * from student where class_id = #{id}
</select>
复制代码

おすすめ

転載: juejin.im/post/5da28474e51d4577e86d0daf