Mybatis入门案列

MyBatis入门与实战

Mybatis使用案例

JDBC的缺点

  1. 数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题。
  2. Sql语句在代码中硬编码,造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代码。
  3. 使用preparedStatement向占有位符号传参数存在硬编码,因为sql语句的where条件不一定,可能多也可能少,修改sql还要修改代码,系统不易维护。
  4. 对结果集解析存在硬编码(查询列名),sql变化导致解析代码变化,系统不易维护,如果能将数据库记录封装成pojo对象解析比较方便。

Mybatis入门案例

  1. 数据库配置文件(db.properties)

    jdbc.driver=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8
    jdbc.username=root
    jdbc.password=admin
  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="db.properties"></properties>
    <!--mybatis自带别名:
        别名  映射的类型
           _byte    byte 
           _long    long 
           _short   short 
           _int     int 
           _integer     int 
           _double  double 
           _float   float 
           _boolean     boolean 
           string   String 
           byte     Byte 
           long     Long 
           short    Short 
           int  Integer 
           integer  Integer 
           double   Double 
           float    Float 
           boolean  Boolean 
           date     Date 
           decimal  BigDecimal 
           bigdecimal   BigDecimal 
           map  Map
    -->
    <typeAliases> 
        <!-- 定义单个pojo类别名
        type:类的全路径名称
        alias:别名
         -->
    <!--         <typeAlias type="cn.xx.pojo.User" alias="user"/> -->
    
        <!-- 使用包扫描的方式批量定义别名 
        定以后别名等于类名,不区分大小写,但是建议按照java命名规则来,首字母小写,以后每个单词的首字母大写
        -->
        <package name="cn.xx.pojo"/>
    </typeAliases>
    
    <!-- 和spring整合后 environments配置将废除-->
    <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>
    
    <mappers>
        <mapper resource="User.xml"/>
    
        <!-- 
        使用class属性引入接口的全路径名称:
        使用规则:
            1. 接口的名称和映射文件名称除扩展名外要完全相同
            2. 接口和映射文件要放在同一个目录下
         -->
    <!--         <mapper class="cn.xx.mapper.UserMapper"/> -->
    
        <!-- 使用包扫描的方式批量引入Mapper接口 
                使用规则:
                1. 接口的名称和映射文件名称除扩展名外要完全相同
                2. 接口和映射文件要放在同一个目录下
        -->
        <package name="cn.xx.mapper"/>
    </mappers>
    </configuration>
  3. 配置mapper(User.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">
    <!-- namespace:命名空间,做sql隔离 -->
    <mapper namespace="test">
    
    <!-- 
    id:sql语句唯一标识
    parameterType:指定传入参数类型
    resultType:返回结果集类型
    
    #{}占位符:起到占位作用,如果传入的是基本类型(string,long,double,int,boolean,float等),那么#{}中的变量名称可以随意写.
    
     -->
    <select id="findUserById" parameterType="java.lang.Integer" resultType="cn.xx.pojo.User">
        select * from user where id=#{id}
    </select>
    
    <!-- 
    如果返回结果为集合,可以调用selectList方法,这个方法返回的结果就是一个集合,所以映射文件中应该配置成集合泛型的类型
    ${}拼接符:字符串原样拼接,如果传入的参数是基本类型(string,long,double,int,boolean,float等),那么${}中的变量名称必须是value
    注意:拼接符有sql注入的风险,所以慎重使用
     -->
    <select id="findUserByUserName" parameterType="java.lang.String" resultType="cn.xx.pojo.User">
        select * from user where username like '%${value}%'
    </select>
    
    <!-- 
    
    #{}:如果传入的是pojo类型,那么#{}中的变量名称必须是pojo中对应的属性.属性.属性.....
    
    如果要返回数据库自增主键:可以使用select LAST_INSERT_ID()
     -->
    <insert id="insertUser" parameterType="cn.xx.pojo.User" >
        <!-- 执行 select LAST_INSERT_ID()数据库函数,返回自增的主键
        keyProperty:将返回的主键放入传入参数的Id中保存.
        order:当前函数相对于insert语句的执行顺序,在insert前执行是before,在insert后执行是AFTER
        resultType:id的类型,也就是keyproperties中属性的类型
        -->
        <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
            select LAST_INSERT_ID()
        </selectKey>
        insert into user (username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})
    </insert>
    
    <delete id="delUserById" parameterType="int">
        delete from user where id=#{id}
    </delete>
    
    <update id="updateUserById" parameterType="cn.xx.pojo.User">
        update user set username=#{username} where id=#{id}
    </update>
    </mapper>
  4. test类

    package mybatis0523;
    
    import java.io.InputStream;
    import java.util.Date;
    import java.util.List;
    
    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 cn.xx.pojo.User;
    
    public class UserTest {
    
    @Test
    public void testFindUserById() throws Exception{
        String resource = "SqlMapConfig.xml";
        //通过流将核心配置文件读取进来
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //通过核心配置文件输入流来创建会话工厂
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
        //通过工厂创建会话
        SqlSession openSession = factory.openSession();
        //第一个参数:所调用的sql语句= namespace+.+sql的ID
        User user = openSession.selectOne("test.findUserById", 1);
        System.out.println(user);
        openSession.close();
    }
    
    @Test
    public void testFindUserbyUserName() throws Exception{
        String resource = "SqlMapConfig.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession openSession = factory.openSession();
    
        List<User> list = openSession.selectList("test.findUserByUserName", "王");
        System.out.println(list);
    }
    
    @Test
    public void testInsertUser() throws Exception{
        String resource = "SqlMapConfig.xml";
        //通过流将核心配置文件读取进来
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //通过核心配置文件输入流来创建会话工厂
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
        //通过工厂创建会话
        SqlSession openSession = factory.openSession();
    
        User user = new User();
        user.setUsername("赵四");
        user.setBirthday(new Date());
        user.setSex("1");
        user.setAddress("北京昌平");
        System.out.println("====" + user.getId());
    
        openSession.insert("test.insertUser", user);
        //提交事务(mybatis会自动开启事务,但是它不知道何时提交,所以需要手动提交事务)
        openSession.commit();
    
        System.out.println("====" + user.getId());
    }
    
    @Test
    public void testDelUserById()throws Exception{
        String resource = "SqlMapConfig.xml";
        //通过流将核心配置文件读取进来
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //通过核心配置文件输入流来创建会话工厂
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
        //通过工厂创建会话
        SqlSession openSession = factory.openSession();
    
        openSession.delete("test.delUserById", 29);
        //提交
        openSession.commit();
    }
    
    @Test
    public void testUpdateUserById() throws Exception{
        String resource = "SqlMapConfig.xml";
        //通过流将核心配置文件读取进来
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //通过核心配置文件输入流来创建会话工厂
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
        //通过工厂创建会话
        SqlSession openSession = factory.openSession();
    
        User user = new User();
        user.setId(28);
        user.setUsername("王麻子");
        openSession.update("test.updateUserById", user);
    
        //提交
        openSession.commit();
    }
    }
  5. 生成自增主键并返回的配置

    <insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">
     <!-- selectKey将主键返回,需要再返回 -->
     <selectKey keyProperty="id" order="BEFORE" resultType="java.lang.String">
     select uuid()
     </selectKey>
     insert into user(username,birthday,sex,address)
     values(#{username},#{birthday},#{sex},#{address});
    </insert>
    

    添加selectKey实现将主键返回

    keyProperty:返回的主键存储在pojo中的哪个属性

    order:selectKey的执行顺序,是相对与insert语句来说,由于mysql的自增原理执行完insert语句之后才将主键生成,所以这里selectKey的执行顺序为after

    resultType:返回的主键是什么类型

简单的Dao层写法

  1. 原生DAO的实现类(xml还是上面那个)

    public class UserDaoImpl implements UserDao {
    
    private SqlSess ionFactory sqlSessionFactory;
    
    //通过构造方法注入
    public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
        this.sqlSessionFactory = sqlSessionFactory;
    }
    
    @Override
    public User findUserById(Integer id) {
        //sqlSesion是线程不安全的,所以它的最佳使用范围在方法体内
        SqlSession openSession = sqlSessionFactory.openSession();
        User user = openSession.selectOne("test.findUserById", id);
        return user;
    }
    
    @Override
    public List<User> findUserByUserName(String userName) {
        SqlSession openSession = sqlSessionFactory.openSession();
        List<User> list = openSession.selectList("test.findUserByUserName", userName);
        return list;
    }
    
    
    }

    Test类:

    public class UserDaoTest {
    
    private SqlSessionFactory factory;
    
    //作用:在测试方法前执行这个方法
    @Before
    public void setUp() throws Exception{
        String resource = "SqlMapConfig.xml";
        //通过流将核心配置文件读取进来
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //通过核心配置文件输入流来创建会话工厂
        factory = new SqlSessionFactoryBuilder().build(inputStream);
    }
    
    @Test
    public void testFindUserById() throws Exception{
        //将初始化好的工厂注入到实现类中
        UserDao userDao = new UserDaoImpl(factory);
    
        User user = userDao.findUserById(1);
        System.out.println(user);
    }
    
    @Test
    public void testFindUserByUserName () throws Exception{
    
        UserDao userDao = new UserDaoImpl(factory);
    
        List<User> list = userDao.findUserByUserName("王");
        System.out.println(list);
    }
    }

  2. 动态代理方式

    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接口代理实现编写规则:
    1. 映射文件中namespace要等于接口的全路径名称
    2. 映射文件中sql语句id要等于接口的方法名称
    3. 映射文件中传入参数类型要等于接口方法的传入参数类型
    4. 映射文件中返回结果集类型要等于接口方法的返回值类型
    -->
    <mapper namespace="cn.xx.mapper.UserMapper">
    <select id="findUserById" parameterType="int" resultType="cn.xx.pojo.User">
        select * from user where id=#{id}
    </select>
    <select id="findUserByUserName" parameterType="string" resultType="user">
        select * from user where username like '%${value}%'
    </select>
    <insert id="insertUser" parameterType="cn.xx.pojo.User" >
        <!-- 执行 select LAST_INSERT_ID()数据库函数,返回自增的主键
        keyProperty:将返回的主键放入传入参数的Id中保存.
        order:当前函数相对于insert语句的执行顺序,在insert前执行是before,在insert后执行是AFTER
        resultType:id的类型,也就是keyproperties中属性的类型
        -->
        <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
            select LAST_INSERT_ID()
        </selectKey>
        insert into user (username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})
    </insert>
    </mapper>

    接口:

    package cn.xx.mapper;
    import java.util.List;
    import cn.xx.pojo.User;
    public interface UserMapper {
    
    public User findUserById(Integer id);
    //动态代理形势中,如果返回结果集问List,那么mybatis会在生成实现类的使用会自动调用selectList方法
    public List<User> findUserByUserName(String userName);
    public void insertUser(User user);
    }
    

    test类:

    public class UserMapperTest {
    private SqlSessionFactory factory;
    
    //作用:在测试方法前执行这个方法
    @Before
    public void setUp() throws Exception{
        String resource = "SqlMapConfig.xml";
        //通过流将核心配置文件读取进来
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //通过核心配置文件输入流来创建会话工厂
        factory = new SqlSessionFactoryBuilder().build(inputStream);
    }
    
    @Test
    public void testFindUserById() throws Exception{
        SqlSession openSession = factory.openSession();
        //通过getMapper方法来实例化接口
        UserMapper mapper = openSession.getMapper(UserMapper.class);
    
        User user = mapper.findUserById(1);
        System.out.println(user);
    }
    
    @Test
    public void testFindUserByUserName() throws Exception{
        SqlSession openSession = factory.openSession();
        //通过getMapper方法来实例化接口
        UserMapper mapper = openSession.getMapper(UserMapper.class);
    
        List<User> list = mapper.findUserByUserName("王");
    
        System.out.println(list);
    }
    
    @Test
    public void testInsertUser() throws Exception{
        SqlSession openSession = factory.openSession();
        //通过getMapper方法来实例化接口
        UserMapper mapper = openSession.getMapper(UserMapper.class);
    
        User user = new User();
        user.setUsername("老王");
        user.setSex("1");
        user.setBirthday(new Date());
        user.setAddress("北京昌平");
    
        mapper.insertUser(user);
    
        openSession.commit();
    }
    }

传递复杂类型(输入映射,输出映射)

  1. 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="cn.xx.mapper.UserMapper">
    <!-- 封装sql条件,封装后可以重用. 
    id:是这个sql条件的唯一标识 -->
    <sql id="user_Where">
        <!-- where标签作用:
                会自动向sql语句中添加where关键字
                会去掉第一个条件的and关键字
             -->
        <where>
            <if test="username != null and username != ''">
                and username like '%${username}%'
            </if>
            <if test="sex != null and sex != ''">
                and sex=#{sex}
            </if>
        </where>
    </sql>
    
    <select id="findUserbyVo" parameterType="cn.xx.pojo.QueryVo" resultType="cn.xx.pojo.User">
        select * from user where username like '%${user.username}%' and sex=#{user.sex}
    </select>
    
    <!-- 只有返回结果为一行一列的时候,那么返回值类型才可以指定成基本类型 -->
    <select id="findUserCount" resultType="java.lang.Integer">
        select count(*) from user 
    </select>
    
    <select id="findUserByUserNameAndSex" parameterType="cn.xx.pojo.User" resultType="cn.xx.pojo.User">
        select * from user 
    
        <!-- 调用sql条件 -->
        <include refid="user_Where"></include>
    </select>
    
    <select id="findUserByIds" parameterType="cn.xx.pojo.QueryVo" resultType="cn.xx.pojo.User">
        select * from user
    
        select * from user
        <where>
            <if test="ids != null">
                <!-- 
                foreach:循环传入的集合参数
                collection:传入的集合的变量名称
                item:每次循环将循环出的数据放入这个变量中
                open:循环开始拼接的字符串
                close:循环结束拼接的字符串
                separator:循环中拼接的分隔符
                 -->
                <foreach collection="ids" item="id" open="id in (" close=")" separator=",">
                    #{id}
                </foreach>
            </if>
        </where>
    </select>
    
    
    <!-- 一对一:自动映射 -->
    <select id="findOrdersAndUser1" resultType="cn.xx.pojo.CustomOrders">
        select a.*, b.id uid, username, birthday, sex, address 
        from orders a, user b 
        where a.user_id = b.id
    </select>
    
    <!-- 一对一:手动映射 -->
    <!-- 
    id:resultMap的唯一标识
    type:将查询出的数据放入这个指定的对象中
    注意:手动映射需要指定数据库中表的字段名与java中pojo类的属性名称的对应关系
     -->
    <resultMap type="cn.xx.pojo.Orders" id="orderAndUserResultMap">
        <!-- id标签指定主键字段对应关系
        column:列,数据库中的字段名称
        property:属性,java中pojo中的属性名称
         -->
        <id column="id" property="id"/>
    
        <!-- result:标签指定非主键字段的对应关系 -->
        <result column="user_id" property="userId"/>
        <result column="number" property="number"/>
        <result column="createtime" property="createtime"/>
        <result column="note" property="note"/>
    
        <!-- 这个标签指定单个对象的对应关系 
        property:指定将数据放入Orders中的user属性中
        javaType:user属性的类型
        -->
        <association property="user" javaType="cn.xx.pojo.User">
            <id column="uid" property="id"/>
            <result column="username" property="username"/>
            <result column="birthday" property="birthday"/>
            <result column="sex" property="sex"/>
            <result column="address" property="address"/>
        </association>
    </resultMap>
    <select id="findOrdersAndUser2" resultMap="orderAndUserResultMap">
        select a.*, b.id uid, username, birthday, sex, address 
        from orders a, user b 
        where a.user_id = b.id
    </select>
    
    <resultMap type="cn.xx.pojo.User" id="userAndOrdersResultMap">
        <id column="id" property="id"/>
        <result column="username" property="username"/>
        <result column="birthday" property="birthday"/>
        <result column="sex" property="sex"/>
        <result column="address" property="address"/>
    
        <!-- 指定对应的集合对象关系映射
        property:将数据放入User对象中的ordersList属性中
        ofType:指定ordersList属性的泛型类型
         -->
        <collection property="ordersList" ofType="cn.xx.pojo.Orders">
            <id column="oid" property="id"/>
            <result column="user_id" property="userId"/>
            <result column="number" property="number"/>
            <result column="createtime" property="createtime"/>
        </collection>
    </resultMap>
    <select id="findUserAndOrders" resultMap="userAndOrdersResultMap">
        select a.*, b.id oid ,user_id, number, createtime 
        from user a, orders b where a.id = b.user_id
    </select>
    </mapper>
  2. UserMapper,对应的接口类

    public interface UserMapper {
    
    public User findUserById(Integer id);
    //动态代理形势中,如果返回结果集问List,那么mybatis会在生成实现类的使用会自动调用selectList方法
    public List<User> findUserByUserName(String userName);
    public void insertUser(User user);
    public List<User> findUserbyVo(QueryVo vo);
    public Integer findUserCount();
    public List<User> findUserByUserNameAndSex(User user);
    public List<User> findUserByIds(QueryVo vo);
    public List<CustomOrders> findOrdersAndUser1() ;
    public List<Orders> findOrdersAndUser2();
    public List<User> findUserAndOrders();
    }
  3. 实体类

    public class User {
    private int id;
    private String username;// 用户姓名
    private String sex;// 性别
    private Date birthday;// 生日
    private String address;// 地址
    ...
    }
    public class QueryVo {
    private User user;  
    private List<Integer> ids;
    ...
    }
    public class CustomOrders extends Orders{
    
    private int uid;
    private String username;// 用户姓名
    private String sex;// 性别
    private Date birthday;// 生日
    private String address;// 地址
    }
    public class Orders {
       private Integer id;
    
       private Integer userId;
    
       private String number;
    
       private Date createtime;
    
       private String note;
    
       private User user;
    }
  4. Test类

    public class UserMapperTest {
    private SqlSessionFactory factory;
    
    //作用:在测试方法前执行这个方法
    @Before
    public void setUp() throws Exception{
        String resource = "SqlMapConfig.xml";
        //通过流将核心配置文件读取进来
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //通过核心配置文件输入流来创建会话工厂
        factory = new SqlSessionFactoryBuilder().build(inputStream);
    }
    
    @Test
    public void testFindUserByVo() throws Exception{
        SqlSession openSession = factory.openSession();
        //通过getMapper方法来实例化接口
        UserMapper mapper = openSession.getMapper(UserMapper.class);
    
        QueryVo vo = new QueryVo();
        User user = new User();
        user.setUsername("王");
        user.setSex("1");
        vo.setUser(user);
    
        List<User> list = mapper.findUserbyVo(vo);
        System.out.println(list);
    
    }
    
    @Test
    public void testFindUserCount() throws Exception{
        SqlSession openSession = factory.openSession();
        //通过getMapper方法来实例化接口
        UserMapper mapper = openSession.getMapper(UserMapper.class);
    
        Integer count = mapper.findUserCount();
        System.out.println("=====" + count);
    }
    
    @Test
    public void testFindUserbyUserNameAndSex() throws Exception{
        SqlSession openSession = factory.openSession();
        //通过getMapper方法来实例化接口
        UserMapper mapper = openSession.getMapper(UserMapper.class);
    
        User user = new User();
        user.setUsername("王");
        user.setSex("1");
    
        List<User> list = mapper.findUserByUserNameAndSex(user);
    
        System.out.println(list);
    }
    
    @Test
    public void testFindUserbyIds() throws Exception{
        SqlSession openSession = factory.openSession();
        //通过getMapper方法来实例化接口
        UserMapper mapper = openSession.getMapper(UserMapper.class);
    
        QueryVo vo = new QueryVo();
        List<Integer> ids = new ArrayList<Integer>();
        ids.add(1);
        ids.add(16);
        ids.add(28);
        ids.add(22);
        vo.setIds(ids);
    
        List<User> list = mapper.findUserByIds(vo);
        System.out.println(list);
    }
    
    @Test
    public void testFindOrdersAndUser() throws Exception{
        SqlSession openSession = factory.openSession();
        //通过getMapper方法来实例化接口
        UserMapper mapper = openSession.getMapper(UserMapper.class);
    
        List<CustomOrders> list = mapper.findOrdersAndUser1();
        System.out.println(list);
    }
    
    @Test
    public void testFindOrdersAnduUser2() throws Exception{
        SqlSession openSession = factory.openSession();
        //通过getMapper方法来实例化接口
        UserMapper mapper = openSession.getMapper(UserMapper.class);
    
        List<Orders> list = mapper.findOrdersAndUser2();
        System.out.println(list);
    }
    
    @Test
    public void testFindUserAndOrders() throws Exception{
        SqlSession openSession = factory.openSession();
        //通过getMapper方法来实例化接口
        UserMapper mapper = openSession.getMapper(UserMapper.class);
    
        List<User> list = mapper.findUserAndOrders();
        System.out.println(list);
    }
    }

Spring整合

  1. Spring配置

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
    
    <!-- 加载配置文件 -->
    <context:property-placeholder location="classpath:db.properties" />
    <!-- 数据库连接池 -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close">
        <property name="driverClassName" value="${jdbc.driver}" />
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
        <property name="maxActive" value="10" />
        <property name="maxIdle" value="5" />
    </bean>
    
    <!-- 整合Sql会话工厂归spring管理 -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 指定mybatis核心配置文件 -->
        <property name="configLocation" value="classpath:SqlMapConfig.xml"></property>
        <!-- 指定会话工厂使用的数据源 -->
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    
    <!-- 
        配置原生Dao实现   
        注意:class必须指定Dao实现类的全路径名称
    -->
    <bean id="userDao" class="cn.xx.dao.UserDaoImpl">
        <property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
    </bean>
    
    <!-- Mapper接口代理实现 -->
    <!--     <bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean"> -->
        <!-- 配置mapper接口的全路径名称 -->
    <!--         <property name="mapperInterface" value="cn.xx.mapper.UserMapper"></property> -->
    <!--         <property name="sqlSessionFactory" ref="sqlSessionFactory"></property> -->
    <!--     </bean> -->
    
    <!-- 使用包扫描的方式批量引入Mapper
    扫描后引用的时候可以使用类名,首字母小写.
     -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!-- 指定要扫描的包的全路径名称,如果有多个包用英文状态下的逗号分隔 -->
        <property name="basePackage" value="cn.xx.mapper"></property>
    </bean>
    </beans>
  2. SqlMapConfig.xml

    <configuration>
    
    
    <typeAliases> 
        <!-- 定义单个pojo类别名
        type:类的全路劲名称
        alias:别名
         -->
    <!--         <typeAlias type="cn.xx.pojo.User" alias="user"/> -->
    
        <!-- 使用包扫描的方式批量定义别名 
        定以后别名等于类名,不区分大小写,但是建议按照java命名规则来,首字母小写,以后每个单词的首字母大写
        -->
        <package name="cn.xx.pojo"/>
    </typeAliases>
    
    <mappers>
        <mapper resource="User.xml"/>
    
        <!-- 
        使用class属性引入接口的全路径名称:
        使用规则:
            1. 接口的名称和映射文件名称除扩展名外要完全相同
            2. 接口和映射文件要放在同一个目录下
         -->
    <!--         <mapper class="cn.xx.mapper.UserMapper"/> -->
    
        <!-- 使用包扫描的方式批量引入Mapper接口 
                使用规则:
                1. 接口的名称和映射文件名称除扩展名外要完全相同
                2. 接口和映射文件要放在同一个目录下
        -->
    <!--         <package name="cn.xx.mapper"/> -->
    </mappers>
    </configuration>
  3. User.xml

    <mapper namespace="test">
    
    <select id="findUserById" parameterType="java.lang.Integer" resultType="cn.xx.pojo.User">
        select * from user where id=#{id}
    </select>
    
    <select id="findUserByUserName" parameterType="java.lang.String" resultType="cn.xx.pojo.User">
        select * from user where username like '%${value}%'
    </select>
    
    <insert id="insertUser" parameterType="cn.xx.pojo.User" >
        <!-- 执行 select LAST_INSERT_ID()数据库函数,返回自增的主键
        keyProperty:将返回的主键放入传入参数的Id中保存.
        order:当前函数相对于insert语句的执行顺序,在insert前执行是before,在insert后执行是AFTER
        resultType:id的类型,也就是keyproperties中属性的类型
        -->
        <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
            select LAST_INSERT_ID()
        </selectKey>
        insert into user (username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})
    </insert>
    
    <delete id="delUserById" parameterType="int">
        delete from user where id=#{id}
    </delete>
    
    <update id="updateUserById" parameterType="cn.xx.pojo.User">
        update user set username=#{username} where id=#{id}
    </update>
    </mapper>

    实现类:

    public class UserDaoImpl extends SqlSessionDaoSupport implements UserDao {
    
    @Override
    public User findUserById(Integer id) {
        //sqlSesion是线程不安全的,所以它的最佳使用范围在方法体内
        SqlSession openSession = this.getSqlSession();
        User user = openSession.selectOne("test.findUserById", id);
        //整合后会话归spring管理,所以不需要手动关闭.
        //openSession.close();
        return user;
    }
    
    @Override
    public List<User> findUserByUserName(String userName) {
        SqlSession openSession = this.getSqlSession();
        List<User> list = openSession.selectList("test.findUserByUserName", userName);
        return list;
    }
    }

    Test类:

    public class UserDaoTest {
    
    private ApplicationContext applicatonContext;
    
    @Before
    public void setUp() throws Exception{
        String configLocation = "classpath:ApplicationContext.xml";
        applicatonContext = new ClassPathXmlApplicationContext(configLocation);
    }
    
    @Test
    public void testFindUserById() throws Exception{
        //获取UserDao对象, getBean中的字符串是在ApplicationContext.xml中声明的
        UserDao userDao = (UserDao)applicatonContext.getBean("userDao");
    
        User user = userDao.findUserById(1);
        System.out.println(user);
    }
    }

整合Mapper代理接口

  1. Spring配置在上面的配置文件中

  2. 测试类:

    public class UserMapperTest {
    private ApplicationContext applicatonContext;
    
    @Before
    public void setUp() throws Exception{
        String configLocation = "classpath:ApplicationContext.xml";
        applicatonContext = new ClassPathXmlApplicationContext(configLocation);
    }
    
    //   @Test
    //   public void  testFindUserById() throws Exception{
    //       UserMapper userMapper = (UserMapper)applicatonContext.getBean("userMapper");
    //       
    //       User user = userMapper.findUserById(1);
    //       System.out.println(user);
    //   }
    
    @Test
    public void testFindUserById() throws Exception{
        UserMapper userMapper = (UserMapper)applicatonContext.getBean("userMapper");
    
        User user = userMapper.selectByPrimaryKey(1);
        System.out.println(user);
    }
    
    @Test
    public void testFindUserAndSex() throws Exception{
        UserMapper userMapper = (UserMapper)applicatonContext.getBean("userMapper");
    
        //创建UserExample对象
        UserExample userExample = new UserExample();
        //通过UserExample对象创建查询条件封装对象(Criteria中是封装的查询条件)
        Criteria createCriteria = userExample.createCriteria();
    
        //加入查询条件
        createCriteria.andUsernameLike("%王%");
        createCriteria.andSexEqualTo("1");
    
        List<User> list = userMapper.selectByExample(userExample);
        System.out.println(list);
    }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值