mapper配置

代码参考mybatis-demo

1.基于xml配置的映射器的概率

  • cache - 给定命名空间的缓存配置
  • cache-ref - 其他命名空间缓存配置的引用
  • resultMap - 是最复杂也是最强大的元素,用来描述如何从数据库结果集中加载对象
  • sql - 可被其他语句引用的可重用语句块
  • insert - 映射插入语句
  • update
  • delete
  • select

mapper配置最核心的两个要素是:SQL语句和映射规则。
1)sql insert update delete select是写SQL语句
2)resultMap是写映射规则的

2.select元素

2.1 自动映射和手动映射

    <select id="selectByPrimaryKey" resultMap="BaseResultMap"
            parameterType="java.lang.Integer">
        select
        <include refid="Base_Column_List" />
        from t_user
        where id = #{id,jdbcType=INTEGER}
    </select>

其中BaseResultMap为手动进行映射:

    <resultMap id="BaseResultMap" type="TUser">

        <id column="id" property="id" jdbcType="INTEGER" />
        <result column="user_name" property="userName" jdbcType="VARCHAR" />
        <result column="real_name" property="realName" jdbcType="VARCHAR" />
        <result column="sex" property="sex" jdbcType="TINYINT" />
        <result column="mobile" property="mobile" jdbcType="VARCHAR" />
        <result column="email" property="email" jdbcType="VARCHAR" />
        <result column="note" property="note" jdbcType="VARCHAR" />
        <result column="position_id" property="positionId" jdbcType="INTEGER" />
    </resultMap>
  • 自动映射
    前提:SQL列名和JavaBean的属性是一致的
    自动映射等级autoMappingBehavior设置为PARTIAL,谨慎使用FULL
    使用resultType
    如果列名和JavaBean不一致,mapUnderscoreToCamelCase设置为true。(规范命名时使用)

  • 相关的阿里规范说明——使用手动映射


2.2 传递多个查询入参

  • 使用map传递参数:可读性差,导致可维护性和可扩展性差,杜绝使用
  • 使用注解传递参数:直观明了,当参数小于5个时,建议使用
  • 使用Java Bean的方式传递参数:当参数大于5个时,建议使用

参考TUserMapper.java

    List<TUser> selectByEmailAndSex1(Map<String, Object> param);

    List<TUser> selectByEmailAndSex2(@Param("email")String email, @Param("sex")Byte sex);

    List<TUser> selectByEmailAndSex3(EmailSexBean esb);

参考TUserMapper.xml

    <select id="selectByEmailAndSex1" resultMap="BaseResultMap"
            parameterType="map">
        select
        <include refid="Base_Column_List" />
        from t_user a
        where a.email like CONCAT('%', #{email}, '%') and
        a.sex = #{sex}
    </select>

    <select id="selectByEmailAndSex2" resultMap="BaseResultMap">
        select
        <include refid="Base_Column_List" />
        from t_user a
        where a.email like CONCAT('%', #{email}, '%') and
        a.sex = #{sex}
    </select>


    <select id="selectByEmailAndSex3" resultMap="BaseResultMap"
            parameterType="com.enjoylearning.mybatis.entity.EmailSexBean">
        select
        <include refid="Base_Column_List" />
        from t_user a
        where a.email like CONCAT('%', #{email}, '%') and
        a.sex = #{sex}
    </select>

测试代码参考MybatisDemo.java

    // 多参数查询
    @Test
    public void testManyParamQuery() {
        // 2.获取sqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 3.获取对应mapper
        TUserMapper mapper = sqlSession.getMapper(TUserMapper.class);

        String email = "qq.com";
        Byte sex = 1;

        // 第一种方式使用map
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("email", email);
        params.put("sex", sex);
        List<TUser> list1 = mapper.selectByEmailAndSex1(params);
        System.out.println(list1.size());

        // 第二种方式直接使用参数
        List<TUser> list2 = mapper.selectByEmailAndSex2(email, sex);
        System.out.println(list2.size());

        // 第三种方式用对象
        EmailSexBean esb = new EmailSexBean();
        esb.setEmail(email);
        esb.setSex(sex);
        List<TUser> list3 = mapper.selectByEmailAndSex3(esb);
        System.out.println(list3.size());
    }

3.resultMap元素

  • 互联网应用中,大多数是用单表查询。因为数据量巨大,实现时是分库分表分布式的。

resultMap是Mybatis中最重要最强大的元素,让你从90%的JDBC ResultSets数据提取代码中解放出来。
设计思想是:简单的语句不需要明确的结果映射,复杂的语句只需要描述它们的关系即可。

    <resultMap id="BaseResultMap" type="TUser">
        
        <!-- <constructor>
            <idArg column="id" javaType="int"/>
            <arg column="user_name" javaType="String"/>
        </constructor>  -->
        <id column="id" property="id" jdbcType="INTEGER" />
        <result column="user_name" property="userName" jdbcType="VARCHAR" />
        <result column="real_name" property="realName" jdbcType="VARCHAR" />
        <result column="sex" property="sex" jdbcType="TINYINT" />
        <result column="mobile" property="mobile" jdbcType="VARCHAR" />
        <result column="email" property="email" jdbcType="VARCHAR" />
        <result column="note" property="note" jdbcType="VARCHAR" />
        <result column="position_id" property="positionId" jdbcType="INTEGER" />
    </resultMap>

3.1 属性

3.2 子元素

3.2.1 id & result

  • id和result都将一个列的值映射到一个简单数据类型的属性或字段;
    区别是,id表示的结果将是对象的标识属性(key主键一样),在比较对象实例时用到。可以提高整体的性能,尤其是缓存和嵌套结果映射(也就是联合映射)的时候。


3.2.2 constructor

  • 一个pojo不存在没有参数的构造方法,就需要使用construtor
    为了通过名称来引用构造方法参数,可以添加@Param注解,指定参数名称的前提下,以任意顺序编写arg元素。
<constructor>
  <idArg column="id" javaType="int"/>
  <arg column="user_name" javaType="String"/>
</constructor>  

4.insert、update和delete元素

int insert1(TUser record);
    <insert id="insert1" parameterType="TUser" useGeneratedKeys="true"      keyProperty="id">
        insert into t_user (id, user_name, real_name,
        sex, mobile,
        email,
        note, position_id)
        values (#{id,jdbcType=INTEGER},
        #{userName,jdbcType=VARCHAR},
        #{realName,jdbcType=VARCHAR},
        #{sex,jdbcType=TINYINT}, #{mobile,jdbcType=VARCHAR},
        #{email,jdbcType=VARCHAR},
        #{note,jdbcType=VARCHAR},
        #{positionId,jdbcType=INTEGER})
    </insert>`

测试代码:

    @Test
    // 测试插入数据自动生成id
    public void testInsertGenerateId1() throws IOException {
        // 2.获取sqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 3.获取对应mapper
        TUserMapper mapper = sqlSession.getMapper(TUserMapper.class);
        // 4.执行查询语句并返回结果
        TUser user1 = new TUser();
        user1.setUserName("test1");
        user1.setRealName("realname1");
        user1.setEmail("myemail1");
        mapper.insert1(user1);
        sqlSession.commit();
        System.out.println(user1.getId());
    }

4.1 selectKey元素——无自动增长时使用

对于id,Mysql是在插入之后拿到主键id,Oracle是在插入之前拿到主键id。

int insert2(TUser record);
    <insert id="insert2" parameterType="TUser">
    
        <selectKey  keyProperty="id" order="AFTER" resultType="int">
            select LAST_INSERT_ID()
        </selectKey>
        insert into t_user (id, user_name, real_name,
        sex, mobile,
        email,
        note, position_id)
        values (#{id,jdbcType=INTEGER},
        #{userName,jdbcType=VARCHAR},
        #{realName,jdbcType=VARCHAR},
        #{sex,jdbcType=TINYINT}, #{mobile,jdbcType=VARCHAR},
        #{email,jdbcType=VARCHAR},
        #{note,jdbcType=VARCHAR},
        #{positionId,jdbcType=INTEGER})
    </insert>

测试代码:

    @Test
    // 测试插入数据自动生成id
    public void testInsertGenerateId2() throws IOException {
        // 2.获取sqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 3.获取对应mapper
        TUserMapper mapper = sqlSession.getMapper(TUserMapper.class);
        // 4.执行查询语句并返回结果
        TUser user2 = new TUser();
        user2.setUserName("test2");
        user2.setRealName("realname2");
        user2.setEmail("myemai2l");
        mapper.insert2(user2);
        sqlSession.commit();
        System.out.println(user2.getId());
    }

5.sql元素

    <sql id="Base_Column_List">
        id, user_name, real_name, sex, mobile, email, note,
        position_id
    </sql>


    <select id="selectByPrimaryKey" resultMap="BaseResultMap"
            parameterType="java.lang.Integer">
        select
        <include refid="Base_Column_List" />
        from t_user
        where id = #{id,jdbcType=INTEGER}
    </select>

6.参数:向sql语句中传递的可变参数

  • 传值${}:传入的数据直接显式生成在sql中,无法防止sql注入
    直接插入到sql语句中。

  • 预编译#{}:将传入的数据当成一个字符串,会对自动传入的数据加一个单引号,能够很大程序防止sql注入
    使用占位符?表示。

  • 表名、选取的列是动态的,order by和in操作,可以考虑使用$

    <select id="selectBySymbol" resultMap="BaseResultMap">
        select
        ${inCol}
        from ${tableName} a
        where a.sex = #{sex}
        order by ${orderStr}
    </select>

测试程序:

    @Test
    // 参数#和参数$区别测试(动态sql 入门)
    public void testSymbol() {
        // 2.获取sqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 3.获取对应mapper
        TUserMapper mapper = sqlSession.getMapper(TUserMapper.class);

        String inCol = "id, user_name, real_name, sex, mobile, email, note";
        String tableName = "t_user";
        Byte sex = 1;
        String orderStr = "sex,user_name";

        List<TUser> list = mapper.selectBySymbol(tableName, inCol, orderStr, sex);
        System.out.println(list.size());

    }

测试结果:

2018-09-24 15:03:30.859 [main] DEBUG c.e.mybatis.mapper.TUserMapper.selectBySymbol - ==>  Preparing: select id, user_name, real_name, sex, mobile, email, note from t_user a where a.sex = ? order by sex,user_name 
2018-09-24 15:03:30.920 [main] DEBUG c.e.mybatis.mapper.TUserMapper.selectBySymbol - ==> Parameters: 1(Byte)
2018-09-24 15:03:30.940 [main] DEBUG c.e.mybatis.mapper.TUserMapper.selectBySymbol - <==      Total: 3

7.注解方式配置

注解方式就是将SQL语句直接写在接口上,对于需求比较简单的系统,效率较高。缺点在于,每次修改sql语句都要编译代码,对于复杂的sql语句可编辑性和可读性都差,一般不建议使用这种配置方式。

  • @Select
    @Results
    @ResultMap
    @Insert
    @Update
    @Delete
public interface TJobHistoryAnnoMapper {

    int deleteByPrimaryKey(Integer id);


    int insertSelective(TJobHistory record);

    TJobHistory selectByPrimaryKey(Integer id);

    int updateByPrimaryKeySelective(TJobHistory record);

    int updateByPrimaryKey(TJobHistory record);


    @Results(id="jobInfo",value={
            @Result(property="id",column="id",id = true),
            @Result(property="userId",column="user_id"),
            @Result(property="compName",column="comp_name"),
            @Result(property="years",column="years"),
            @Result(property="title",column="title")
    })
    @Select("select id, user_id, comp_name, years, title from t_job_history"
            + " where user_id = #{userId}")
    List<TJobHistory> selectByUserId(int userId);

    @ResultMap("jobInfo")
    @Select("select id, user_id, comp_name, years, title from t_job_history")
    List<TJobHistory> selectAll();

    @Insert("insert into t_job_history (id, user_id, comp_name, years, title)"
            + " values (#{id,jdbcType=INTEGER}, #{userId,jdbcType=INTEGER},"
            + "#{compName,jdbcType=VARCHAR},"
            + "#{years,jdbcType=INTEGER}, #{title,jdbcType=VARCHAR})")
    @Options(useGeneratedKeys=true,keyProperty="id")
    int insert(TJobHistory record);
}

测试代码

    @Test
    // 注解测试
    public void testAnno() {
        // 2.获取sqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 3.获取对应mapper
        TJobHistoryAnnoMapper mapper = sqlSession.getMapper(TJobHistoryAnnoMapper.class);

        List<TJobHistory> list = mapper.selectByUserId(1);
        System.out.println(list.size());

        List<TJobHistory> listAll = mapper.selectAll();
        System.out.println(listAll.size());

        TJobHistory job = new TJobHistory();
        job.setTitle("产品经理");
        job.setUserId(1);
        job.setCompName("美团");
        job.setYears(3);

        mapper.insert(job);
        System.out.println(job.getId());
    }

mapper配置:

    <!-- 映射文件,mapper的配置文件 -->
    <mappers>
        <mapper resource="sqlmapper/TUserMapper.xml" />
         <mapper class="com.enjoylearning.mybatis.mapper.TJobHistoryAnnoMapper"/>
    </mappers>

结果:

018-09-24 15:22:50.596 [main] DEBUG c.e.m.mapper.TJobHistoryAnnoMapper.selectByUserId - ==>  Preparing: select id, user_id, comp_name, years, title from t_job_history where user_id = ? 
2018-09-24 15:22:50.636 [main] DEBUG c.e.m.mapper.TJobHistoryAnnoMapper.selectByUserId - ==> Parameters: 1(Integer)
2018-09-24 15:22:50.686 [main] DEBUG c.e.m.mapper.TJobHistoryAnnoMapper.selectByUserId - <==      Total: 1
1
2018-09-24 15:22:50.690 [main] DEBUG c.e.mybatis.mapper.TJobHistoryAnnoMapper.selectAll - ==>  Preparing: select id, user_id, comp_name, years, title from t_job_history 
2018-09-24 15:22:50.693 [main] DEBUG c.e.mybatis.mapper.TJobHistoryAnnoMapper.selectAll - ==> Parameters: 
2018-09-24 15:22:50.696 [main] DEBUG c.e.mybatis.mapper.TJobHistoryAnnoMapper.selectAll - <==      Total: 6
6
2018-09-24 15:22:50.697 [main] DEBUG c.e.mybatis.mapper.TJobHistoryAnnoMapper.insert - ==>  Preparing: insert into t_job_history (id, user_id, comp_name, years, title) values (?, ?,?,?, ?) 
2018-09-24 15:22:50.698 [main] DEBUG c.e.mybatis.mapper.TJobHistoryAnnoMapper.insert - ==> Parameters: null, 1(Integer), 美团(String), 3(Integer), 产品经理(String)
2018-09-24 15:22:50.699 [main] DEBUG c.e.mybatis.mapper.TJobHistoryAnnoMapper.insert - <==    Updates: 1
7

参考

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容

  • 1. 简介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的...
    笨鸟慢飞阅读 5,459评论 0 4
  • Java数据持久化之mybatis 一. mybatis简介 1.1 原始的JDBC操作: Java 通过 Jav...
    小Q逛逛阅读 4,903评论 0 16
  • 1 Mybatis入门 1.1 单独使用jdbc编程问题总结 1.1.1 jdbc程序 上边使...
    哇哈哈E阅读 3,295评论 0 38
  • 眼前的世界很色彩斑斓 我看过腊月里的梅花 看过夏天池塘里的青蛙 看过秋天那一山的落叶 看过没有星星的黑夜 我看过山...
    懂小孩阅读 238评论 10 3
  • 感赏自己每天坚持锻炼,这样颈椎病就会好一些,今天锻炼结束回,带了女儿喜欢吃的西瓜、葡萄。感觉自己每天中午利用午休时...
    吴洁_3015阅读 246评论 1 6