• MyBatis学习笔记


    1、MyBatis介绍

    2、MyBatis架构

    3、MyBatis简单入门实例

    4、传统Dao开发与MyBatis的Mapper动态代理开发

    5、sqlMapConfig.xml配置文件

    6、输入映射和输出映射

      6.1 parameterType

      6.2 resultType

      6.3 resultMap

    7、动态sql

      7.1 if标签

       7.2 where标签

      7.3 sql片段

      7.4 foreach标签

    8、关联查询

      8.1 一对一查询

      8.2 一对多查询

    9、MyBatis整合Spring

      9.1 整合思路

      9.2 整合所需的jar包

      9.3 创建配置文件

      9.4 创建pojo

      9.5 Dao开发方式简单使用

      9.6 Mapper代理形式 

    结尾

    1、MyBatis介绍

    MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。

    MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。

    Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。

    2、MyBatis架构

    1、mybatis配置的sqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息。

    mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在sqlMapConfig.xml中加载。

    2、通过mybatis环境等配置信息构造SqlSessionFactory即会话工厂

    3、由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession进行。

    4、mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。

    5、Mapped Statement也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中一个sql对应一个Mapped Statement对象,sql的id即是Mapped statement的id。

    6、Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。

    7、Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程。

    3、MyBatis简单入门实例

     1)基本开发环境搭建:基于maven搭建MyBatis开发环境,然后进行测试数据库创建以及相关jar包的引入

    <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.13</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.4.6</version>
    </dependency>

    2)创建配置文件:根据架构图,首先创建sqlMapConfig.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"/>
        <environments default="development">
            <environment id="development">
                <!-- 使用jdbc事务管理 -->
                <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>
        
    </configuration>

    这里我们使用了jdbc.properties将数据库的相关信息单独提取出来

    3)创建pojo:与数据库中的表进行匹配,这里以user表举例

    import java.io.Serializable;
    import java.util.Date;
    
    public class User implements Serializable {
    
        private static final long serialVersionUID = 1L;
        private Integer id;
        private String username;// 用户姓名
        private String sex;// 性别
        private Date birthday;// 生日
        private String address;// 地址
    
    
        public Integer getId() {
            return id;
        }
        public void setId(Integer id) {
            this.id = id;
        }
        public String getUsername() {
            return username;
        }
        public void setUsername(String username) {
            this.username = username;
        }
        public String getSex() {
            return sex;
        }
        public void setSex(String sex) {
            this.sex = sex;
        }
        public Date getBirthday() {
            return birthday;
        }
        public void setBirthday(Date birthday) {
            this.birthday = birthday;
        }
        public String getAddress() {
            return address;
        }
        public void setAddress(String address) {
            this.address = address;
        }
        @Override
        public String toString() {
            return "User [id=" + id + ", username=" + username + ", sex=" + sex
                    + ", birthday=" + birthday + ", address=" + address + "]";
        }
    }

    4)创建映射文件并集中到sqlMapConfig.xml:为User.java创建映射文件User.xml,该文件中主要进行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">
    <!-- 写Sql语句   -->
    <mapper namespace="user">
        <select id="findUserById" parameterType="Integer" resultType="com.panlei.pojo.User">
            select * from user where id = #{v}
        </select>
    </mapper>

    这里的不同的声明用不同的id进行区别,parameterType是传参的类型,resultType是返回值类型,要与后面讲到的方法调用进行匹配。namespace是为了区分不同的映射mapper文件集中到sqlMapConfig.xml中可能id冲突的问题,后面还会具体讲解。

    5)具体测试1:根据id查询用户信息,还是创建SqlSessionFactory,然后获取SqlSession,再调用selectOne(..)方法,根据传递的"user.findUserById"定位到具体的映射文件的具体sql语句,这里传递的参数便是前面定义的所需参数

    import com.panlei.pojo.User;
    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;
    
    public class TestMyBatis {
        @Test
        public void test1() {
            try {
                String resource = "sqlMapConfig.xml";
                InputStream inputStream = Resources.getResourceAsStream(resource);
                SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
                SqlSession sqlSession = sqlSessionFactory.openSession();
                User o = sqlSession.selectOne("user.findUserById", 10);
                System.out.println(o);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    6)具体测试2:根据用户名模糊匹配查询

    具体的sql语句格式:select * from user where username like '%五%'

    这里传递的参数就是String类型,然后返回值可能是一个用户列表,这里用的是${value},不是前面的#{},后面具体讲解区别

    <select id="findUserByUsername" parameterType="String" resultType="com.panlei.pojo.User">
            select * from user where username like '%${value}%'
    </select>
        // 根据用户名模糊匹配
        @Test
        public void test2() {
            try {
                String resource = "sqlMapConfig.xml";
                InputStream inputStream = Resources.getResourceAsStream(resource);
                SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
                SqlSession sqlSession = sqlSessionFactory.openSession();
                List<User> users = sqlSession.selectList("user.findUserByUsername", "五");
                for(User u:users) {
                    System.out.println(u);
                }
    
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    7)#{}与${}的区别

    #{}表示一个占位符号,通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换。#{}可以有效防止sql注入。 #{}可以接收简单类型值或pojo属性值。 如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。

    ${}表示拼接sql串,通过${}可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换, ${}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,${}括号中只能是value。

    8)具体实例3:添加用户,这里直接传递的参数是自定义的User对象实例,直接进行映射,其属性要与pojo中的属性名一致

    <!-- 保存用户 -->
    <insert id="saveUser" parameterType="com.panlei.pojo.User">
      INSERT INTO `user` (username,birthday,sex,address) VALUES (#{username},#{birthday},#{sex},#{address})
    </insert>

    这里在实际应用中可能需要立即获取新添加用户的id来进行后续操作,下面演示如何编码:

    <insert id="saveUser" parameterType="com.panlei.pojo.User">
    <!-- selectKey 标签实现主键返回 -->
    <!-- keyColumn:主键对应的表中的哪一列 -->
    <!-- keyProperty:主键对应的pojo中的哪一个属性 -->
    <!-- order:设置在执行insert语句前执行查询id的sql,还是在执行insert语句之后执行查询id的sql -->
    <!-- resultType:设置返回的id的类型 -->
    <selectKey keyColumn="id" keyProperty="id" order="AFTER"
        resultType="int">
        SELECT LAST_INSERT_ID()
    </selectKey>
        INSERT INTO `user` (username,birthday,sex,address) VALUES (#{username},#{birthday},#{sex},#{address})
    </insert>

    LAST_INSERT_ID():是mysql的函数,返回auto_increment自增列新记录id值。

    然后在测试代码中可以直接打印插入用户的id,发现是最新的自增id。不需要额外的代码。

    Mybatis解决jdbc编程的问题

    1、数据库连接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库连接池可解决此问题。

    解决:在SqlMapConfig.xml中配置数据连接池,使用连接池管理数据库链接。

    2、Sql语句写在代码中造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代码。

    解决:将Sql语句配置在XXXXmapper.xml文件中与java代码分离。

    3、向sql语句传参数麻烦,因为sql语句的where条件不一定,可能多也可能少,占位符需要和参数一一对应。

    解决:Mybatis自动将java对象映射至sql语句,通过statement中的parameterType定义输入参数的类型。

    4、对结果集解析麻烦,sql变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成pojo对象解析比较方便。

    解决:Mybatis自动将sql执行结果映射至java对象,通过statement中的resultType定义输出结果的类型。

    4、传统Dao开发与MyBatis的Mapper动态代理开发

    传统的Dao开发,就是创建Dao,然后创建Dao的实现类,然后在Service中使用即可,还是需要针对具体的pojo,创建具体的mapper.xml文件。具体实现就不再详述。

    MyBatis中官方推荐使用编写Mapper接口(相当于Dao接口),然后交给Mybatis进行处理,根据该接口自动创建该接口的动态代理对象。为实现这一目标,事先定义了Mapper接口的开发规范:

    1.Mapper.xml文件中的namespace与mapper接口的类路径相同;

    2.Mapper接口方法名和Mapper.xml中定义的每个statement的id相同;

    3.Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同;

    4.Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同。

    下面结合具体实例解释上述规范:

     

     

    这样我们在具体执行时,会自动生成接口的代理类对象,然后执行接口的具体方法时,会根据规范找到对应mapper文件下的相应方法

    package com.panlei.mybatisdemo;
    
    import com.panlei.mapper.UserMapper;
    import com.panlei.pojo.User;
    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.Before;
    import org.junit.Test;
    
    import java.io.InputStream;
    import java.util.Date;
    
    public class TestMapper {
        private SqlSessionFactory sqlSessionFactory;
    
        @Before
        public void init() throws Exception {
            // 创建SqlSessionFactoryBuilder
            SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
            // 加载SqlMapConfig.xml配置文件
            InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
            // 创建SqlsessionFactory
            this.sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
        }
    
        @Test
        public void testSaveUser() {
            // 获取sqlSession,和spring整合后由spring管理
            SqlSession sqlSession = this.sqlSessionFactory.openSession();
    
            // 从sqlSession中获取Mapper接口的代理对象
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            User user = new User();
            user.setUsername("萨其马");
            user.setSex("2");
            user.setBirthday(new Date());
            user.setAddress("北京");
            // 执行查询方法
          userMapper.saveUser(user);    // 相当于 sqlSession.insert("namespace.saveUser", user)
    //        System.out.println(user);
    
            sqlSession.commit();
            // 和spring整合后由spring管理
            sqlSession.close();
        }
    
    
    }

    关于selectOne还是selectList

    动态代理对象调用sqlSession.selectOne()和sqlSession.selectList()是根据mapper接口方法的返回值决定,如果返回list则调用selectList方法,如果返回单个对象则调用selectOne方法。

    5、sqlMapConfig.xml配置文件

    SqlMapConfig.xml中配置的内容和顺序如下:

       properties(属性)

       settings(全局配置参数)

       typeAliases(类型别名)

       typeHandlers(类型处理器)

       objectFactory(对象工厂)

       plugins(插件)

       environments(环境集合属性对象)

       environment(环境子属性对象)

       transactionManager(事务管理)

       dataSource(数据源)

       mappers(映射器)

    1) properties(属性)

    可以引用java属性文件中的配置信息,比如前面用到的jdbc.properties

    2) typeAliases(类型别名)

    我们前面在传递参数,设置类型的时候,都是使用的 包名+类名,这样比较费劲,那么能不能像配置基本数据类型或者String一样来进行配置呢?答案是可以的,需要利用类型别名。

    <typeAliases>
       <!-- 单个别名定义 -->
       <typeAlias alias="user" type="com.panlei.pojo.User" />
       <!-- 批量别名定义,扫描整个包下的类,别名为类名(大小写不敏感) -->
      <package name="com.panlei.pojo" />
    </typeAliases>

    sqlMapConfig.xml中利用<typeAliases>的<typeAlias>进行单个别名的定义。当有特别多的类需要定义的时候,一个一个的定义同样很繁琐,这就可以利用<package>来进行统一的配置。

    3) mappers(映射器)

    <mapper resource=" " />

    使用相对于类路径的资源(现在的使用方式),如:<mapper resource="sqlmap/User.xml" />

    <mapper class=" " />

    使用mapper接口类路径,如:<mapper class="com.panlei.mybatis.mapper.UserMapper"/>

    注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。

    <package name=""/>  

    注册指定包下的所有mapper接口,如:<package name="com.panlei.mybatis.mapper"/>。注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。

    6、输入映射和输出映射

     6.1 parameterType(输入类型)

    在配置文件的编写具体语句时,我们需要传入一些参数,前面的例子,我们已经使用了简单的类型,例如Integer,还有自己定义的POJO的类型,比如我们自定义的User类型。

    还有另外一种情况,就是自定义的类型中有另一个自定义类型的属性,比如User中有一个自定义Order类型的属性,这时我们需要传递POJO包装对象。下面以一个例子来具体讲解:

    1)根据用户名模糊查询用户信息,这里虚设一个只有一个User属性的包装类,然后传递该包装类,利用其User属性的username模糊查询用户信息

    包装类

    在UserMapper.java中编写查询接口方法:

    在UserMapper.xml中编写具体的数据库查询代码,注意四条对应规则(namespace,id,传参,返回类型):这里我们看到传递参数的名称并未使用,而是直接使用了TestUser中的user属性中的username属性

     

    编写测试代码:

     

     6.2 resultType(输出类型)

    1)输出简单类型

    测试例子:SELECT COUNT(*) FROM ‘user’

    先是在UserMapper接口中定义查询方法

    然后在UserMapper.xml文件中具体编写查询语句

     

    测试输出

    2)此外还可以输出POJO对象以及POJO的对象列表,这我们前面已经使用了,不再详述

     6.3  resultMap(输出映射)

    resultType可以指定将查询结果映射为pojo,但需要pojo的属性名和sql查询的列名一致方可映射成功。

    如果sql查询字段名和pojo的属性名不一致,可以通过resultMap将字段名和属性名作一个对应关系 ,resultMap实质上还需要将查询结果映射到pojo对象中。

    resultMap可以实现将查询结果映射为复杂类型的pojo,比如在查询结果映射对象中包括pojo和list实现一对一查询和一对多查询。

    下面我们以具体的例子演示:

    1) 查询order表的所有数据

    order表的字段及数据如下:这里的user_id不为空

    然后我们定义相应的POJO类型,这里我们将表中的user_id定义为userId属性,模拟字段与属性不一致的情况。

       

    为更好的演示,我们第一次查询仍然使用resultType,看一下运行结果,然后再使用resultMap

    具体的步骤仍然是创建OrderMapper接口,定义查询方法,然后在OrderMapper.xml中编写具体的查询语句,并设置resultType类型

    最终查询结果输出如下:可以看到userId为null

     

    上面的结果产生原因就是因为字段与属性没有一一对应的原因。下面我们使用resultMap进行演示:

    只需要修改OrderMapper.xml即可,为其添加<resultMap>,然后在具体的语句中利用resultMap属性进行关联即可,注意里面的各个属性的含义。

    这里因为只需要进行user_id与userId的映射,所以其他属性可以不用处理。

     

    然后我们运行测试,发现userId已经有值了。

     

     7、动态sql

     通过mybatis提供的各种标签方法实现动态拼接sql。

     7.1 if 标签 

     需求:根据性别和名字查询用户,有时候条件可能为空,需要进行判断,为空就不再作为条件

    <select id="queryUserByWhere" parameterType="user" resultType="user">
        SELECT id, username, birthday, sex, address FROM `user`
        WHERE 1=1
        <if test="sex != null and sex != ''">
            AND sex = #{sex}
        </if>
        <if test="username != null and username != ''">
            AND username LIKE
            '%${username}%'
        </if>
    </select>

     7.2 where 标签

    上面的sql还有where 1=1 这样的语句,很麻烦

    可以使用where标签进行改造

    <select id="queryUserByWhere" parameterType="user" resultType="user">
        SELECT id, username, birthday, sex, address FROM `user`
        <!-- where标签可以自动添加where,同时处理sql语句中第一个and关键字,也就是删除 -->
        <where>
            <if test="sex != null">
                AND sex = #{sex}
            </if>
            <if test="username != null and username != ''">
                AND username LIKE
                '%${username}%'
            </if>
        </where>
    </select>

     7.3 sql片段

    Sql中可将重复的sql提取出来,使用时用include引用即可,最终达到sql重用的目的。

    把上面例子中的id, username, birthday, sex, address提取出来,作为sql片段,如下:

    <!-- 声明sql片段 -->
    <sql id="userFields">
        id, username, birthday, sex, address
    </sql>
    
    <select id="queryUserByWhere" parameterType="user" resultType="user">
        <!-- SELECT id, username, birthday, sex, address FROM `user` -->
        <!-- 使用include标签加载sql片段;refid是sql片段id -->
        SELECT <include refid="userFields" /> FROM `user`
        <!-- where标签可以自动添加where关键字,同时处理sql语句中第一个and关键字 -->
        <where>
            <if test="sex != null">
                AND sex = #{sex}
            </if>
            <if test="username != null and username != ''">
                AND username LIKE
                '%${username}%'
            </if>
        </where>
    </select>

    如果要使用别的Mapper.xml配置的sql片段,可以在refid前面加上对应的Mapper.xml的namespace

    <select id="queryUserByWhere" parameterType="user" resultType="user">    
        SELECT <include refid="com.panlei.mapper.OrderMapper.userFields" /> FROM `user`
        <!-- where标签可以自动添加where关键字,同时处理sql语句中第一个and关键字 -->
        <where>
            <if test="sex != null">
                AND sex = #{sex}
            </if>
            <if test="username != null and username != ''">
                AND username LIKE
                '%${username}%'
            </if>
        </where>
    </select>

     7.4 foreach标签

    向sql传递数组或List,mybatis使用foreach解析,如下:

     根据多个id查询用户信息

    查询sql:

    SELECT * FROM user WHERE id IN (1,10,24)

    对上面用到包装类添加一个 List<Integer> ids 属性

    UserMapper.xml如下

    <!-- 根据ids查询用户 -->
    <select id="queryUserByIds" parameterType="queryVo" resultType="user">
        SELECT * FROM `user`
        <where>
            <!-- foreach标签,进行遍历 -->
            <!-- collection:遍历的集合,这里是QueryVo的ids属性 -->
            <!-- item:遍历的项目,可以随便写,,但是和后面的#{}里面要一致 -->
            <!-- open:在前面添加的sql片段 -->
            <!-- close:在结尾处添加的sql片段 -->
            <!-- separator:指定遍历的元素之间使用的分隔符 -->
            <foreach collection="ids" item="item" open="id IN (" close=")"
                separator=",">
                #{item}
            </foreach>
        </where>
    </select>

    测试代码如下:

    @Test
    public void testQueryUserByIds() {
        // mybatis和spring整合,整合之后,交给spring管理
        SqlSession sqlSession = this.sqlSessionFactory.openSession();
        // 创建Mapper接口的动态代理对象,整合之后,交给spring管理
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    
        // 使用userMapper执行根据条件查询用户
        QueryVo queryVo = new QueryVo();
        List<Integer> ids = new ArrayList<>();
        ids.add(1);
        ids.add(10);
        ids.add(24);
        queryVo.setIds(ids);
    
        List<User> list = userMapper.queryUserByIds(queryVo);
    
        for (User u : list) {
            System.out.println(u);
        }
    
        // mybatis和spring整合,整合之后,交给spring管理
        sqlSession.close();
    }

    8、关联查询

     8.1 一对一查询

    需求:查询所有订单信息,关联查询下单用户信息。

    sql语句:

    SELECT o.id, o.user_id userId, o.number, o.createtime, u.username, u.address  FROM `order` o LEFT JOIN `user` u ON o.user_id = u.id

    方法一:使用resultType

    这里我们,继承Order类编写Order2User类作为新的pojo类,此pojo类中新增加了订单信息和用户信息。这样返回对象的时候,mybatis自动把用户信息也注入进来了。

    使用OrderMapper接口,并在OrderMapper.xml中添加对应的查询语句,最后测试。

    这里我们在sql语句中对数据库字段的uer_id使用了别名userId,这样就不需要使用resultMap来进行映射了。

    方法二:使用resultMap

    这里直接对Oeder.java进行修改,添加一个User属性,然后在OrderMapper.xml中建立对应的映射。

     

      8.2 一对多查询

     需求:查询所有用户信息及用户关联的订单信息

    sql语句:

    SELECT u.id, u.username, u.birthday, u.sex, u.address, o.id oid, o.number, o.createtime, o.note FROM `user` u LEFT JOIN `order` o ON u.id = o.user_id

    这里类似于上面的方法二。修改User类,在UserMapper.xml的配置文件中添加<resultMap>,然后编写相应查询语句,最后测试。

    9、MyBatis整合Spring

     9.1 整合思路

    1、SqlSessionFactory对象应该放到spring容器中作为单例存在;

    2、传统dao的开发方式中,应该从spring容器中获得sqlsession对象;

    3、Mapper代理形式中,应该从spring容器中直接获得mapper的代理对象;

    4、数据库的连接以及数据库连接池事务管理都交给spring容器来完成。

     9.2 整合所需的jar包

    Spring相关jar包:

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>4.3.1.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>4.3.1.RELEASE</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <version>5.1.4.RELEASE</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aspects</artifactId>
      <version>5.1.4.RELEASE</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-beans</artifactId>
      <version>5.1.4.RELEASE</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.1.4.RELEASE</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-context-support -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context-support</artifactId>
      <version>5.1.4.RELEASE</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>5.1.4.RELEASE</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-expression -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-expression</artifactId>
      <version>5.1.4.RELEASE</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>5.1.4.RELEASE</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-jms -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jms</artifactId>
      <version>5.1.4.RELEASE</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-messaging -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-messaging</artifactId>
      <version>5.1.4.RELEASE</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-tx -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <version>5.1.4.RELEASE</version>
    </dependency>
    Spring

    MyBatis相关jar包:

    <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
    <dependency>
       <groupId>org.mybatis</groupId>
       <artifactId>mybatis</artifactId>
      <version>3.4.6</version>
    </dependency>

    Spring+mybatis的整合包:

    <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
    <dependency>
      <groupId>org.mybatis</groupId>
       <artifactId>mybatis-spring</artifactId>
       <version>1.3.2</version>
    </dependency>

    Mysql的数据库驱动jar包:

    <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.13</version>
    </dependency>

    数据库连接池的jar包:

    <!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
    <dependency>
      <groupId>com.mchange</groupId>
      <artifactId>c3p0</artifactId>
      <version>0.9.5.2</version>
    </dependency>

     9.3 创建配置文件

     1) applicationContext.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xmlns:tx="http://www.springframework.org/schema/tx"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context.xsd
           http://www.springframework.org/schema/aop
           http://www.springframework.org/schema/aop/spring-aop.xsd
           http://www.springframework.org/schema/tx
           http://www.springframework.org/schema/tx/spring-tx.xsd">
    
        <!-- 引入JDBC配置文件 -->
        <context:property-placeholder location="jdbc.properties"/>
    
        <!-- 配置数据库连接池 -->
        <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
            <property name="driverClass" value="${jdbc.driverClass}"/>
            <property name="jdbcUrl" value="${jdbc.url}"/>
            <property name="user" value="${jdbc.user}"/>
            <property name="password" value="${jdbc.password}"/>
        </bean>
    
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <!-- 配置数据源 -->
            <property name="dataSource" ref="dataSource"/>
            <!-- 配置mybatis核心配置文件 -->
            <property name="configLocation" value="sqlMapConfig.xml"/>
        </bean>
    
    </beans>
    View Code

    2) sqlMapConfig.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>
        <!-- 设置别名 -->
        <typeAliases>
            <!-- 2. 指定扫描包,会把包内所有的类都设置别名,别名的名称就是类名,大小写不敏感 -->
            <package name="com.panlei.pojo" />
        </typeAliases>
    
    </configuration>
    View Code

    3) jdbc.properties 

    jdbc.driverClass=com.mysql.cj.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost/webuser?serverTimezone=GMT%2B8
    jdbc.user=root
    jdbc.password=panlei
    View Code

    4) log4j.properties

    # Global logging configuration
    log4j.rootLogger=DEBUG, stdout
    # Console output...
    log4j.appender.stdout=org.apache.log4j.ConsoleAppender
    log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
    log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
    View Code 

     9.4 创建pojo

     

     9.5 Dao开发方式简单使用

    这里的内容前面有所涉及,本次只讲解关键的内容。

    Dao接口与实现类具体代码不再展示,注意一点,在dao实现类中因为需要调用对应mapper.xml中的具体sql语句,也就需要SqlSession对象,因为我们是MyBatis与Spring整合,所以我们不需要自己去new一个对象了,前面我们已经在applicationContext.xml中对 SqlSessionFactoryBean 进行了配置,而且在spring与mybaits整合的jar包中对这种必然会使用的操作抽象为一个类:SqlSessionDaoSupport,我们需要在具体的Dao实现类中继承该类,然后使用其中的方法即可,具体如下图:

    还有就是编写对应的mapper.xml文件,并在sqlMapConfig.xml中加载该文件,最后在applicationContext.xml配置Dao

    然后运行测试

     9.6 Mapper代理形式

     这一部分的基础知识在第4节也有讲解,本次也只是讲解重要的部分或者没有涉及的部分。

    首先还是UserMapper接口与UserMapper.xml按规则对应,然后还是讲解一下applicationContext.xml中的配置。

    第一种方式是为每一个Mapper接口配置一个<bean>

      用到的MapperFactoryBean也是属于mybatis-spring整合jar包

    运行测试

    第二种方式是用扫描包的形式配置。第一种方式需要为每一个mapper配置一个<bean>,当数量太多时,显得太麻烦。这里可以不注入SqlSessionFactoryBean,可以自动注入

     

  • 相关阅读:
    面向目标的场景设置--Goal-Oriented Scenario
    第二十二课 打造专业的编译环境(下)
    第二十一课 打造专业的编译环境(中)
    第二十课 打造专业的编译环境(上)
    第十九篇 路径搜索的综合示例
    第八十课 最长不下降序列
    第七十九课 最短路径(Floyd)
    第七十八课 最短路径(Dijkstra)
    第七十七课 最小生成树(Kruskal)
    第76课 最小生成树(Prim)
  • 原文地址:https://www.cnblogs.com/panlei3707/p/10478252.html
Copyright © 2020-2023  润新知