Mybatis应用姿势深入解析

1. Mybatis编程式使用(单独使用)

1.1 mybatis和Mysql jar 包依赖

<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
</dependency>
<!-- mysql driver -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.15</version>
    <scope>runtime</scope>
</dependency>

1.2 全局配置文件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>
    <!-- 参数设置 -->
    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <!-- 打印查询语句 -->
        <setting name="logImpl" value="STDOUT_LOGGING" />
        <!-- 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。默认 false  -->
        <setting name="lazyLoadingEnabled" value="true"/>
        <!-- 当开启时,任何方法的调用都会加载该对象的所有属性。默认 false,可通过select标签的 fetchType来覆盖-->
        <setting name="aggressiveLazyLoading" value="false"/>
        <!--  Mybatis 创建具有延迟加载能力的对象所用到的代理工具,默认JAVASSIST -->
        <!--<setting name="proxyFactory" value="CGLIB" />-->

        <setting name="cacheEnabled" value="false" />
        <setting name="lazyLoadingEnabled" value="true" />
        <setting name="aggressiveLazyLoading" value="false"/>
        <setting name="jdbcTypeForNull" value="NULL"/>
        <setting name="callSettersOnNulls" value="true"/>
    </settings>
	<!-- mybatis分页插件-->
    <plugins>
        <plugin interceptor="com.github.miemiedev.mybatis.paginator.OffsetLimitInterceptor">
            <property name="dialectClass" value="com.github.miemiedev.mybatis.paginator.dialect.MySQLDialect"/>
        </plugin>
    </plugins>
</configuration>

1.3 映射器 Mapper.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.inspur.icity.business.neighborhoodbar.logic.repo.SayingRepo">
    <!-- 返回说说以及评论回复的数据格式所需的映射文件-->
    <resultMap id="SayingMap" type="Saying">
        <id column="saying_id" property="saying_id" jdbcType="INTEGER"/>
        <result column="custId" property="custId" jdbcType="VARCHAR"/>
        <result column="userType" property="userType" jdbcType="VARCHAR"/>
        <result column="sayAuthor" property="sayAuthor" jdbcType="VARCHAR"/>
        <result column="phone" property="phone" jdbcType="VARCHAR"/>
        <result column="theme" property="theme" jdbcType="VARCHAR"/>
        <result column="sayingContent" property="sayingContent"/>
        <result column="sayingPicture" property="sayingPicture"/>
        <result column="likes" property="likes" jdbcType="INTEGER"/>
        <result column="commentNum" property="commentNum" jdbcType="INTEGER"/>
        <result column="pass" property="pass" jdbcType="VARCHAR"/>
        <result column="submitTime" property="submitTime" jdbcType="TIMESTAMP"/>
        <result column="passTime" property="passTime" jdbcType="TIMESTAMP"/>
        <collection property="comments" ofType="Comment" column="sayingId">
            <id column="comment_id" property="comment_id" jdbcType="INTEGER"/>
            <result column="sayingId" property="sayingId" jdbcType="INTEGER"/>
            <result column="commentor" property="commentor" jdbcType="VARCHAR"/>
            <result column="commentorId" property="commentorId" jdbcType="VARCHAR"/>
            <result column="commentContent" property="commentContent"/>
            <result column="commentLikes" property="commentLikes" jdbcType="INTEGER"/>
            <result column="commentTime" property="commentTime" jdbcType="TIMESTAMP"/>
            <collection property="replyComments" ofType="ReplyComment" column="commentId">
                <id column="reply_id" property="reply_id" jdbcType="INTEGER"/>
                <result column="sayingId" property="sayingId" jdbcType="INTEGER"/>
                <result column="commentId" property="commentId" jdbcType="INTEGER"/>
                <result column="replier" property="replier" jdbcType="VARCHAR"/>
                <result column="replierId" property="replierId" jdbcType="VARCHAR"/>
                <result column="toCommentor" property="toCommentor" jdbcType="VARCHAR"/>
                <result column="toCommentId" property="toCommentId" jdbcType="VARCHAR"/>
                <result column="replyContent" property="replyContent"/>
                <result column="replyLikes" property="replyLikes"/>
                <result column="replyTime" property="replyTime" jdbcType="TIMESTAMP"/>
            </collection>
        </collection>
    </resultMap>

    <select id="selectSayingById" resultMap="SayingMap" parameterType="long">
    SELECT
	*
    FROM
	(
    SELECT
	*
    FROM
	neighborhood_saying s
	LEFT JOIN neighborhood_firstcomment fc ON s.saying_id = fc.sayingId
    WHERE
	s.saying_id = #{sayingId}
    ORDER BY
	fc.commentTime DESC
	) tmp
	LEFT JOIN neighborhood_replycomment rc ON tmp.comment_id = rc.commentId
    ORDER BY
	rc.replyTime DESC;
    </select>

    <!-- 将用户点赞状态一同返回给前端-->
    <select id="getLikeStatusAndSayingBySayingId" resultType="java.util.Map">
    SELECT
    IF( l.id > 0, 1, 0 ) AS likeStatus,
	s.saying_id,
	s.custId,
	s.userType,
	s.sayAuthor,
	s.phone,
	s.theme,
	s.sayingContent,
	s.sayingPicture,
	s.likes,
	s.commentNum,
	s.pass,
	s.submitTime,
	s.passTime
    FROM
	neighborhood_saying s
	LEFT JOIN neighborhood_like l ON s.saying_id = l.sayingId
	AND l.custId = #{custId}
	AND likeType = '0'
    WHERE
	s.saying_id = #{sayingId}
    </select>
    <!-- 获取所有审核过的贴子 区分模块-->
    <select id="findAllSayings" resultType="Saying">
    select * from neighborhood_saying
    where pass='1'
        <if test="theme != null and theme != ''">
            and
            theme = #{theme}
        </if>
    ;
    </select>
    <!-- 获取自己的贴子-->
    <select id="findMySaying" resultType="Saying">
    select * from neighborhood_saying where custId=#{custId};
    </select>

    <!-- 判断是否自己的贴子-->
    <select id="isMySaying" resultType="java.util.Map">
    select * from neighborhood_saying where custId=#{custId} and saying_id = #{sayingId};
    </select>

    <!-- 提供管理平台关键词 手机号 姓名 时间 模块 审核状态 身份查询-->
    <select id="getSayingByWhat" resultType="Saying">
    SELECT
	saying_id,
	custId,
    userType,
	sayAuthor,
	phone,
	theme,
	sayingContent,
	sayingPicture,
	likes,
	commentNum,
	pass,
	submitTime,
	passTime
    FROM
	neighborhood_saying
    WHERE
        1=1
        <if test="userType != null and userType != ''">
            and
            userType = #{userType}
        </if>
        <if test="sayAuthor != null and sayAuthor != ''">
            and
            sayAuthor = #{sayAuthor}
        </if>
        <if test="phone != null and phone != ''">
            and
            phone = #{phone}
        </if>
        <if test="theme != null and theme != ''">
            and
            theme = #{theme}
        </if>
        <if test="keyWord != null and keyWord != ''">
            and
            sayingContent like concat('%',#{keyWord},'%')
        </if>
        <if test="pass != null and pass != ''">
            and
            pass = #{pass}
        </if>
        <if test="startTime != null and startTime != ''">
            and
            submitTime &gt; #{startTime}
        </if>
        <if test="endTime != null and endTime != ''">
            and
            submitTime &lt; #{endTime}
        </if>
	order by submitTime desc;
    </select>

    <!-- 管理平台审核状态-->
    <update id="passSaying">
    update neighborhood_saying set pass = '1', passTime=now() where saying_id = #{sayingId};
    </update>

    <!-- 及时更新点赞数量和评论数-->
    <update id="increaseLikes">
    update neighborhood_saying set likes = likes+1 where saying_id = #{sayingId};
    </update>
    <update id="reduceLikes">
    update neighborhood_saying set likes = likes-1 where saying_id = #{sayingId};
    </update>

    <!-- 增加说说评论数量-->
    <update id="increaseCommentNum">
    update neighborhood_saying set commentNum = commentNum+1 where saying_id = #{sayingId};
    </update>
    <!-- 减少说说评论数量-->
    <update id="reduceCommentNum">
    update neighborhood_saying set commentNum = commentNum-1 where saying_id = #{sayingId};
    </update>

    <!-- 发表说说-->
    <insert id="add" useGeneratedKeys="true" keyProperty="id" parameterType="Saying">
    INSERT INTO neighborhood_saying
    ( saying_id, custId, userType, sayAuthor, phone, theme, sayingContent, sayingPicture, likes, commentNum, pass, submitTime, passTime )
    VALUES
    (#{saying_id}, #{custId}, #{userType}, #{sayAuthor}, #{phone}, #{theme}, #{sayingContent}, #{sayingPicture}, #{likes}, #{commentNum}, #{pass}, now(), #{passTime});
    </insert>

    <!-- 删除说说 同时删除对应的以及评论和回复 以及点赞记录-->
    <delete id="remove">
    delete from neighborhood_saying where saying_id = #{sayingId};
    delete from neighborhood_firstcomment where sayingId = #{sayingId};
    delete from neighborhood_replycomment where sayingId = #{sayingId};
    delete from neighborhood_like where sayingId = #{sayingId};
    </delete>
</mapper>

1.4 Mapper接口

/**
 * @Description: mapper
 * @Author create by xuchao
 * @Date 2020/7/7 21:14
 */
@Mapper
public interface SayingRepo {
    
    

    List<Saying> getDemoByProperty(String property);

    List<Saying> getSayingByWhat(@Param("sayAuthor") String sayAuthor, @Param("phone") String phone,
                                 @Param("keyWord") String keyWord, @Param("theme") String theme,
                                 @Param("startTime") String startTime, @Param("endTime") String endTime,
                                 @Param("userType") String userType, @Param("pass") String pass,
                                 PageBounds pageBounds);
    List<Saying> findMySaying(@Param("custId") String custId);
    List<Saying> findAllSayings(@Param("theme") String theme);
    Saying selectSayingById(@Param("sayingId") Long sayingId);
    Map<String, Object> isMySaying(@Param("sayingId") Long sayingId, @Param("custId") String custId);
    Map<String, Object> getLikeStatusAndSayingBySayingId(@Param("sayingId") Long sayingId, @Param("custId") String custId);
    void remove(@Param("sayingId") Long sayingId);
    void passSaying(@Param("sayingId") Long sayingId);
    void add(Saying saying);
    void increaseCommentNum(@Param("sayingId") Long sayingId);
    void reduceCommentNum(@Param("sayingId") Long sayingId);
    void increaseLikes(@Param("sayingId") Long sayingId);
    void reduceLikes(@Param("sayingId") Long sayingId);
}

以上素材来自徐师兄之前做的一个类似QQ发说说的功能 功能还有二级评论点赞,简直个人crud巅峰操作
思考:这是mybatis单独使用的情况 使用的mybatis提供的原生API 没有spring的封装

1.4.1 通过mybatis API使用方式

	/**
     * @Description: 使用MyBatis API方式
     * @Author create by xuchao
     * @Date 2020/7/7 21:27
     * @throws IOException
     */
    @Test
    public void testSessionApi() throws IOException {
    
    
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
		// session里面封装了很多操作数据库的方法
        SqlSession session = sqlSessionFactory.openSession();
        try {
    
    
        	// 这里传的mapper的全路径 容易出错 编译时候无法发现错误 运行时候会找不到对应的mapper
            Blog blog = (Blog) session.selectOne("com.qingshan.mapper.BlogMapper.selectBlogById", 1);
            System.out.println(blog);
        } finally {
    
    
            session.close();
        }
    }

1.4.2 通过sql.session.getMapper(XXXMapper.class)

	/**
     * @Description: 通过 SqlSession.getMapper(XXXMapper.class)  接口方式
     * @Author create by xuchao
     * @Date 2020/7/7 21:34
     * @throws IOException
     */
    @Test
    public void testSelect() throws IOException {
    
    
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        SqlSession session = sqlSessionFactory.openSession(); // ExecutorType.BATCH
        try {
    
    
        	// 这里虽然也是通过反射机制获取对应的mapper对应的方法 但是传的字节码对象 不容易出错!
            BlogMapper mapper = session.getMapper(BlogMapper.class);
            Blog blog = mapper.selectBlogById(1);
            System.out.println(blog);
        } finally {
    
    
            session.close();
        }
    }

2. Mybatis核心配置

点击进入mybatis中文官网
每一个标签其实都是对应源码里面的一个配置类

2.1 configuration根标签

大部分mybatis的配置都会有对应的默认值,所以最简单的配置是啥也不写就留一个根标签

2.2 properties标签

<!-- 对应我们properties配置文件当中 一般配置数据库的连接信息-->
<!-- 这个resource也可以是 URL-->
<!-- 直接修改我的配置文件 方便不同开发环境修改信息 而不需要编译重启项目-->
<properties resource="db.properties"></properties>

2.3 setting标签!

2.4 environments标签

<environments default="development">
    <environment id="development">
        <transactionManager type="JDBC"/><!-- 单独使用时配置成MANAGED没有事务 -->
        <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>

2.5 typeAliases标签

<typeAliases>
	<!-- 类型别名 类似spring里面bean的alias-->
	<!-- 这样在使用的时候就不要全路径 写对应的别名就行 简化配置文件-->
    <typeAlias alias="saying" type="com.xuchao.p5.Saying" />
</typeAliases>

2.6 typeHandlers标签

public class MyTypeHandler extends BaseTypeHandler<String> {
    
    
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType)
            throws SQLException {
    
    
        // 设置 String 类型的参数的时候调用,Java类型到JDBC类型
        // 注意只有在字段上添加typeHandler属性才会生效
        // insertBlog name字段
        System.out.println("---------------setNonNullParameter1:"+parameter);
        ps.setString(i, parameter);
    }

    @Override
    public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
    
    
        // 根据列名获取 String 类型的参数的时候调用,JDBC类型到java类型
        // 注意只有在字段上添加typeHandler属性才会生效
        System.out.println("---------------getNullableResult1:"+columnName);
        return rs.getString(columnName);
    }

    @Override
    public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
    
    
        // 根据下标获取 String 类型的参数的时候调用
        System.out.println("---------------getNullableResult2:"+columnIndex);
        return rs.getString(columnIndex);
    }

    @Override
    public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
    
    
        System.out.println("---------------getNullableResult3:");
        return cs.getString(columnIndex);
    }
}
<typeHandlers>
	<!-- 使用自己编写的typeHandler-->
    <typeHandler handler="com.xuchao.type.MyTypeHandler"></typeHandler>
</typeHandlers>
<!-- resultMap对应类型转换的时候使用 -->
<result column="name" property="name" jdbcType="VARCHAR" typeHandler="com.xuchao.type.MyTypeHandler"/>

2.7 objectFactory标签

objectFactory

每次 MyBatis 创建结果(结果集转化JAVA对象)对象的新实例时,它都会使用一个对象工厂(ObjectFactory)接口来完成实例化工作。 默认的对象工厂需要做的仅仅是实例化目标类,要么通过默认无参构造方法,要么通过存在的参数映射来调用带有参数的构造方法。 如果想覆盖对象工厂的默认行为,可以通过创建自己的对象工厂来实现

如果说自定义的对象工厂 在全局配置文件中配置之后 就可以了

/**
 * <p>
 * 自定义ObjectFactory,通过反射的方式实例化对象
 * 一种是无参构造函数,一种是有参构造函数——第一个方法调用了第二个方法
 */
public class MyObjectFactory extends DefaultObjectFactory {
    
    
    @Override
    public Object create(Class type) {
    
    
        System.out.println("--------------------调用了创建对象的方法:" + type);
        if (type.equals(Blog.class)) {
    
    
            Blog blog = (Blog) super.create(type);
            blog.setName("object factory");
            blog.setBid(1111);
            blog.setAuthorId(2222);
            return blog;
        }
        Object result = super.create(type);
        return result;
    }
}
<objectFactory type="com.xuchao.objectfactory.MyObjectFactory">
    <property name="test" value="69"/>
</objectFactory>

2.8 mappers标签

点击了解更多mappers

2.8 resultMap!!

resultMap是mybatis最强大的标签 在这里重点介绍!!!

<!--column不做限制,可以为任意表的字段,而property须为type 定义的pojo属性-->
<resultMap id="唯一的标识" type="映射的pojo对象">
<id column="表的主键字段,或者可以为查询语句中的别名字段" jdbcType="字段类型" property="映射pojo对象的主键属性" />
<result column="表的一个字段(可以为任意表的一个字段)" jdbcType="字段类型" property="映射到pojo对象的一个属性(须为type定义的pojo对象中的一个属                        
性)"/>
<association property="pojo中的一个对象属性" javaType="pojo中关联的对象">
<id column="关联pojo对象对应表的主键字段" jdbcType="字段类型" property="关联pojo对象的主键属性"/>
<result  column="任意表的字段" jdbcType="字段类型" property="关联pojo对象的属性"/>
</association>
<!-- 集合中的property须为oftype定义的pojo对象的属性-->
<collection property="pojo的集合属性" ofType="集合中的pojo对象">
<id column="集合中pojo对象对应的表的主键字段" jdbcType="字段类型" property="集合中pojo对象的主键属性" />
<result column="可以为任意表的字段" jdbcType="字段类型" property="集合中的pojo对象的属性" />  
</collection>
</resultMap>

<strong>如果collection标签是使用嵌套查询,格式如下:</strong>

<collection column="传递给嵌套查询语句的字段参数" property="pojo对象中集合属性" ofType="集合属性中的pojo对象" select="嵌套的查询语句" > 
</collection>

3. Mybatis与spring整合

4. Mybatis与SpringBoot整合

5. Mybatis Generator (MBG)

猜你喜欢

转载自blog.csdn.net/blackxc/article/details/107189345