zoukankan      html  css  js  c++  java
  • java架构之路-(mybatis源码)mybatis基本使用

      我们今天先来简单了解一下我们持久层框架,mybatis的使用。而且现在的注解成为趋势,我主要说一下注解方向的使用吧(配置文件也会说)

    从使用角度只要是三个部分,mybatis-config.xml,mapper.xml,执行文件三个部分。

    mybatis-config.xml:

      主键标签为configuration成对出现的,然后是properties也就是我们的配置,用于配置数据库。settings声明一些配置,比如打印sql语句等,后面会一个个去说。然后就是我们的mappers,里面包含多个mapper标签,也就是对应我们的mapper.xml文件,在这里说一下一共有三种注入的方式,resource,class,url,resource是通过classpath配置的,如果你没有把mapper放置在resources配置下面,需要在maven里设置编译,不然我们的mapper.xml不会编译到classpath里,class通过类来注入mapper,url一般是远程注入的。再就是我们的typehandlers,可以指定类型转换的。我们也可以继承BaseTypeHandler来重写父类的方法来自定义类型转换。

    来一个我自己的简单配置。

    <?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="app.properties">
            <property name="jdbc.driver" value="com.mysql.jdbc.Driver"/>
        </properties>
    
        <settings>
            <!-- 打印查询语句 -->
            <setting name="logImpl" value="STDOUT_LOGGING"/>
        </settings>
    
        <environments default="${default.environment}">
            <environment id="dev">
                <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>
        <mappers>
            <mapper resource="mybatis/dao/StudentMapper.xml"/>
            <!--        <mapper class="com.tuling.mybatis.dao.UserMapper"></mapper>-->
            <!--        <mapper url="mybatis.dao.StudentDao"></mapper>-->
        </mappers>
    
    </configuration>

    配置还要很多,后面源码解析里面会一点点来说明。

    mapper.xml:

      这个文件就是我们的编写sql的文件了,里面主要标签就是select,insert,update,delete我们的增删改查标签,再就是我们的缓存设置(二级缓存)。下次博客主要说博客,源码级的。
    select里包含我们常见的id,resultType,resultMap,id用来指向我们的接口文件的类名,resultType为我们mybatis自带的类型,也可以是我们设置的对象Bean,resultMap是我们自己定义的返回类型。这里可能会有疑问,一堆多应该怎么来配置?
    association我们可以用他来指定一对多的配置,同时可以配置懒查询还是及时查询的。我们来看一个实例,我们现有学生表格分数表,学生对应很多科目的分数,我们来看一下。先来一段测试代码。
    <?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 default="development">
            <environment id="development">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <property name="driver" value="com.mysql.jdbc.Driver"/>
                    <property name="url" value="jdbc:mysql://localhost/jdbc"/>
                    <property name="username" value="root"/>
                    <property name="password" value="root"/>
                </dataSource>
            </environment>
        </environments>
        <mappers>
    <!--        <mapper resource="mybatis/dao/StudentMapper.xml"/>-->
            <mapper class="mybatis.dao.StudentMapper"></mapper>
            <mapper class="mybatis.dao.ScoreMapper"></mapper>
        </mappers>
    </configuration>
    
    
    <?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.dao.StudentMapper">
        <select id="selectUser" resultType="mybatis.bean.StudentBean">
            select * from stu where id = #{id}
        </select>
    </mapper>
    package mybatis.bean;
    
    import java.io.Serializable;
    
    public class StudentBean implements Serializable {
    
        private static final long serialVersionUID = 2193971369901198487L;
        private int id;
        private String name;
        
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
    
    
    
        @Override
        public String toString() {
            return "selectUser{" +
                    "id=" + id +
                    "name=" + name +
                    '}';
        }
    }
    package mybatis;
    
    import mybatis.bean.ScoreBean;
    import mybatis.bean.StudentBean;
    import mybatis.dao.ScoreMapper;
    import mybatis.dao.StudentMapper;
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    import org.junit.Test;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
    
    public class Test1 {
    
    
        @Test
        public void test() throws IOException {
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
            SqlSession session = sqlSessionFactory.openSession();
            StudentMapper mapper = session.getMapper(StudentMapper.class);
            StudentBean result = mapper.selectUser(1);
    
            System.out.println(result);
        }
    }

    这样我们查询到我们的学生信息,但是还未包含我们的分数。我们来改造一下。

    <?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.dao.StudentMapper">
        <resultMap id="studentMap" type="mybatis.bean.StudentBean">
            <id property="id" column="id"></id>
            <collection property="scoreBean" ofType="mybatis.bean.ScoreBean">
                <id property="id" column="sid"></id>
    <!--            <result property="subject" column="subject"></result>-->
                <result property="score" column="score"></result>
                <result property="studentId" column="studentId"></result>
            </collection>
    
        </resultMap>
    
        <select id="selectUser" resultMap="studentMap">
            select t.id,t.name,t.address,t.num,s.id as sid,s.subject,s.score,s.studentId as studentId from student t left join score s on s.studentId = t.id where t.id = #{id}
        </select>
    </mapper>

    这样就可以查询到对应关系了。需要注意的事子表如果和主表重名,一定给子表起一个别名,而且子表的每一项需要写result,不然没有结果的,但是还不是很好,本来是一个对象一个集合,现在直接变成集合了,我们再来改改。

    <?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.dao.StudentMapper">
        <resultMap id="studentMap" type="mybatis.bean.StudentBean">
            <id property="id" column="id"></id>
            <collection property="scoreBean" javaType="java.util.ArrayList" ofType="mybatis.bean.ScoreBean" select="mybatis.dao.ScoreMapper.selectScoreByStudentId" column="{studentId=id}">
            </collection>
        </resultMap>
    
        <select id="selectUser" resultMap="studentMap">
            select * from student t where t.id = #{id}
        </select>
    </mapper>

    这个比较好用,但是切记,不是懒加载,不是懒加载,需要注意的是collection的property指定我们实体类Bean类中集合的名字。ofType是指向我们一对多中多方的实体Bean,select指定我们对应的第二句sql语句,也就是我们的子查询语句。

    column="{studentId=id}" 中studentId是我们的子查询参数名,id是和我们主表的对应关系。就是说,我们要子表的什么参数等于我们的主表的哪个参数传递过去。

    接下来就是我们简单的一对一了(也可以当做一对多,但是没啥卵用的多对一,项目经理让从多往一查的时候,请你吐他。。。)我们来看我一下我的配置

    <?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.dao.ScoreMapper">
        <resultMap id="scoreMap" type="mybatis.bean.ScoreBean">
            <id property="id" column="id"></id>
            <result property="subject" column="subject"></result>
            <result property="score" column="score"></result>
    
            <association property="studentBean" javaType="mybatis.bean.StudentBean" column="studentId">
                <id property="id" column="id"></id>
                <result property="name" column="name"></result>
                <result property="address" column="address"></result>
                <result property="num" column="num"></result>
            </association>
        </resultMap>
    
        <select id="selectScoreByStudentId" resultMap="scoreMap">
            select * from score s left join student t on s.studentId = t.id where studentId = #{studentId}
        </select>
    </mapper>

    这个比较简单,就不说了,就是写了一个resultMap。我们来看一下两条sql的怎么来进行。

    <?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.dao.ScoreMapper">
        <resultMap id="scoreMap" type="mybatis.bean.ScoreBean">
            <id property="id" column="id"></id>
            <result property="subject" column="subject"></result>
            <result property="score" column="score"></result>
    
            <association property="studentBean" javaType="mybatis.bean.StudentBean" select="mybatis.dao.StudentMapper.selectUser" column="studentId">
                <id property="id" column="id"></id>
                <result property="name" column="name"></result>
                <result property="address" column="address"></result>
                <result property="num" column="num"></result>
            </association>
        </resultMap>
    
        <select id="selectScoreByStudentId" resultMap="scoreMap">
            select * from score where studentId = #{studentId}
        </select>
    </mapper>

    简单解释一下,其实和上面collection差不多的,select指定查询sql位置,column执行传递过去的参数。

    其余的insert,update,delete都差不多,我这里就放在一起说了。

    id 命名空间中的唯一标识符,可被用来代表这条语句。
    parameterType 将要传入语句的参数的完全限定类名或别名。这个属性是可选的,因为 MyBatis 可以通过类型处理器推断出具体传入语句的参数,默认值为未设置(unset)。
    parameterMap 这是引用外部 parameterMap 的已经被废弃的方法。请使用内联参数映射和 parameterType 属性。
    flushCache 将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认值:true(对于 insert、update 和 delete 语句)。
    timeout 这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为未设置(unset)(依赖驱动)。
    statementType STATEMENT,PREPARED 或 CALLABLE 的一个。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。
    useGeneratedKeys (仅对 insert 和 update 有用)这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键(比如:像 MySQL 和 SQL Server 这样的关系数据库管理系统的自动递增字段),默认值:false。
    keyProperty (仅对 insert 和 update 有用)唯一标记一个属性,MyBatis 会通过 getGeneratedKeys 的返回值或者通过 insert 语句的 selectKey 子元素设置它的键值,默认值:未设置(unset)。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。
    keyColumn (仅对 insert 和 update 有用)通过生成的键值设置表中的列名,这个设置仅在某些数据库(像 PostgreSQL)是必须的,当主键列不是表中的第一列的时候需要设置。如果希望使用多个生成的列,也可以设置为逗号分隔的属性名称列表。
    databaseId 如果配置了数据库厂商标识(databaseIdProvider),MyBatis 会加载所有的不带 databaseId 或匹配当前 databaseId 的语句;如果带或者不带的语句都有,则不带的会被忽略。

     useGeneratedKeys=”true”这个相当来说配置的还是比较多的,也就是我们新增成功后,我们的对象可以返回我们插入成功的主键ID。

    拼装sql:

      #{}:是预处理,也是一个占位符的方式来执行sql,${}是sql的拼接,我们其实可以这样来写。

       @Select("select * from ${}_sys_log where id=#{condition}")
        public SystemLog findSystemLog(String year,String condition);

    也就是说,我们对日志sys_log表做了分库分表,按照年份来区分的表,这时我们可以采用sql拼接的方式来做。

    但尽力不要用拼接的方式来做,后面我将动态sql会说具体怎么来实现。${}容易被sql注入。所以我们尽力还用占位符的方式来处理我们的SQL。

    然后就是我们的插件集成,还有缓存,下次博客我们来说说缓存吧。 

    忘记了,学mybatis的使用,推荐一个网站https://mybatis.org/mybatis-3/zh/index.html  上面挺全的(没有源码解析,源码还得回来看我博客)。

    最进弄了一个公众号,小菜技术,欢迎大家的加入

  • 相关阅读:
    Leetcode 191.位1的个数 By Python
    反向传播的推导
    Leetcode 268.缺失数字 By Python
    Leetcode 326.3的幂 By Python
    Leetcode 28.实现strStr() By Python
    Leetcode 7.反转整数 By Python
    Leetcode 125.验证回文串 By Python
    Leetcode 1.两数之和 By Python
    Hdoj 1008.Elevator 题解
    TZOJ 车辆拥挤相互往里走
  • 原文地址:https://www.cnblogs.com/cxiaocai/p/11520734.html
Copyright © 2011-2022 走看看