Mybatis学习笔记(五)——DAO开发

本博客源码下载:戳我一下

Mybatis学习笔记汇总:戳我一下

一、原始Dao开发方式

1、这里配置文件仍然使用在Mybatis学习笔记(三)——入门程序中的配置文件。

2、写一个Dao接口

package com.jiayifan.dao;

import com.jiayifan.po.User;

/**
 * dao接口,用户管理
 * @author 贾一帆
 *
 */
public interface UserDao {
    //根据ID查询用户信息
    public User findUserById(int id) throws Exception;
    //添加用户信息
    public void insertUser(User user) throws Exception;
    //删除用户信息
    public void deleteUser(int id) throws Exception;
}

3、写一个Dao接口的实现类

package com.jiayifan.dao;

import java.util.Date;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

import com.jiayifan.po.User;

/**
 * dao接口实现类
 * @author 贾一帆
 *
 */
public class UserDaoImpl implements UserDao {
    //需要向dao实现类注入SQLSessionFactory
    //这里通过构造方法注入
    private SqlSessionFactory sqlSessionFactory = null;
    public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
        this.sqlSessionFactory = sqlSessionFactory;
    }
    @Override
    public User findUserById(int id) throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        User user = sqlSession.selectOne("test.findUserById",id);
        sqlSession.close();
        return user;
    }

    @Override
    public void insertUser(User user) throws Exception {
        // TODO Auto-generated method stub
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //执行插入操作
        sqlSession.insert("test.insertUser",user);
        System.out.println(user.getId());
        //提交事务
        sqlSession.commit();
        //释放资源
        sqlSession.close();
    }

    @Override
    public void deleteUser(int id) throws Exception {
        // TODO Auto-generated method stub
        SqlSession sqlSession = sqlSessionFactory.openSession();
        sqlSession.delete("test.deleteUser",id);
        sqlSession.commit();
        sqlSession.close();
    }

}

4、测试代码和运行情况

package com.jiayifan.dao;

import static org.junit.jupiter.api.Assertions.*;

import java.io.InputStream;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import com.jiayifan.po.User;

class UserDaoImplTest {
    private SqlSessionFactory sessionFactory;
    //此方法是在所有方法执行之前执行
    @BeforeEach
    void setUp() throws Exception {
        //创建SqlSessionFactory
        //Mybatis的配置文件
        String resource = "SqlMapConfig.xml";
        //得到配置文件流
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //创建会话工厂
        sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }

    @Test
    void testFindUserById() throws Exception {
        //创建一个UserDao对象
        UserDao userDao = new UserDaoImpl(sessionFactory);
        //调用UserDao方法
        User user = userDao.findUserById(1);
        System.out.println(user);
    }
}
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - Opening JDBC Connection
Sun Mar 18 16:50:11 CST 2018 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
DEBUG [main] - Created connection 1582028874.
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@5e4bd84a]
DEBUG [main] - ==>  Preparing: SELECT * FROM USER WHERE id=? 
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <==      Total: 1
DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@5e4bd84a]
DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@5e4bd84a]
DEBUG [main] - Returned connection 1582028874 to pool.
User [id=1, username=hahaha, sex=null, birthday=Sun Mar 18 00:00:00 CST 2018, address=null]

5、总结原始Dao开发中的问题

  • Dao方法体存在重复代码:通过SqlSessionFactory创建SqlSession,调用SqlSession的数据库操作方法
  • 调用sqlSession的数据库操作方法需要指定statementid,这里存在硬编码,不得于开发维护。

二、Mapper动态代理方式开发Dao

1、实现原理
Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法。

Mapper接口开发需要遵循以下规范:

  • Mapper.xml文件中的namespace与mapper接口的类路径相同。
  • Mapper接口方法名和Mapper.xml中定义的每个statement的id相同
  • Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同
  • Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同

2、写一个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">
<!-- namespace命名空间,作用是对sql进行分类化管理
注意:如果使用mapper代理方法开发,namespace有特殊的作用,namespace等于mapper接口地址
 -->
<mapper namespace="com.jiayifan.mapper.UserMapper">
    <!-- 在映射文件中配置很多sql语句 -->
    <!-- 通过select执行查询数据库操作
    id:标识映射文件中的sql。称为statement的id
    #{}表示一个占位符
    parameterType:指定输入参数的类型,这里指定int型,与数据库中类型对应
    #{id}:其中id表示接收输入的参数,参数名称就是id,如果输入的参数是简单类型
    #{}中的参数名可以任意。
    resultType:指定sql输出结果所映射的java对象类型
     -->
    <select id="findUserById" parameterType="int"
     resultType="com.jiayifan.po.User">
        SELECT * FROM USER WHERE id=#{id}
    </select>
    <!-- 
        根据用户名称模糊查询,可能返回多条记录
        resultType:不管返回单条还是多条,都是一条记录锁映射的java对象类型
        ${}:表示拼接sql串,将接受到的参数的内容不加任何修饰的拼接到sql中
        使用该符号拼接sql语句可能引起sql注入
        ${value}:接收输入参数的内容,如果传入的参数是简单类型,那么${}中只能使用value
     -->
    <select id="findUserByName" parameterType="java.lang.String" resultType="com.jiayifan.po.User">
        SELECT * FROM USER WHERE username LIKE '%${value}%'
    </select>
    <!-- 
        添加用户
        parameterType:指定的输入参数类型是pojo(用户信息)
        #{}中指定pojo的属性名,接收到pojo的属性值
     -->
    <insert id="insertUser" parameterType="com.jiayifan.po.User">
        <!-- 
            将插入的主键返回,返回到User对象中
            select last_insert_id():得到刚插入进的记录的主键值,只适用于自增长
            keyProperty:将查询的主键值设置到parameterType指定对象的那个属性
            order:select last_insert_id()相对于insert语句来说执行顺序
            resultType:指定select last_insert_id()的结果类型
         -->
        <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
            select last_insert_id()
        </selectKey>
        INSERT INTO user(username,birthday,sex,address)VALUE(
            #{username},#{birthday},#{sex},#{address})
    </insert>
    <!-- 删除用户
        根据id删除用户,需要输入id值
     -->
    <delete id="deleteUser" parameterType="java.lang.Integer" >
        delete from user where id=#{id}
    </delete>
    <!-- 
        更新用户,根据id更新,需要输入用户id,以及更新信息
     -->
    <update id="updateUser" parameterType="com.jiayifan.po.User">
        update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id}
    </update>
</mapper>

3、在SqlMapConfig.xml配置Mapper.xml

<mappers>
        <mapper resource="sqlmap/User.xml"/>
        <mapper resource="mapper/UserMapper.xml"/>
</mappers>

4、写一个Mapper.java(接口文件)
接口定义有如下特点:

  • Mapper接口方法名和Mapper.xml中定义的statement的id相同
  • Mapper接口方法的输入参数类型和mapper.xml中定义的statement的parameterType的类型相同
  • Mapper接口方法的输出参数类型和mapper.xml中定义的statement的resultType的类型相同
package com.jiayifan.mapper;

import java.util.List;

import com.jiayifan.po.User;

/**
 * mapper接口
 * @author 贾一帆
 *
 */
public interface UserMapper {
    //根据ID查询用户信息
    public User findUserById(int id) throws Exception;
    //根据name查询用户信息
    public List<User> findUserByName(String name) throws Exception;
    //添加用户信息
    public void insertUser(User user) throws Exception;
    //删除用户信息
    public void deleteUser(Integer id) throws Exception;
}

5、测试代码和运行结果

package com.jiayifan.mapper;

import static org.junit.jupiter.api.Assertions.*;

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.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import com.jiayifan.po.User;

class UserMapperTest {
    private SqlSessionFactory sessionFactory;
    @BeforeEach
    void setUp() throws Exception {
        //创建SqlSessionFactory
        //Mybatis的配置文件
        String resource = "SqlMapConfig.xml";
        //得到配置文件流
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //创建会话工厂
        sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }

    @Test
    void testFindUserById() throws Exception {
        SqlSession sqlSession = sessionFactory.openSession();
        //得到UserMapper对象,Mybatis自动生成mapper代理对象
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        //调用userMapper方法
        User user = userMapper.findUserById(28);
        System.out.println(user);
        sqlSession.close();
    }

    @Test
    void testFindUserByName() throws Exception {
        SqlSession sqlSession = sessionFactory.openSession();
        //得到UserMapper对象,Mybatis自动生成mapper代理对象
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        //调用userMapper方法
        List<User> list = userMapper.findUserByName("%小明%");
        System.out.println(list);
        sqlSession.close();
    }

    @Test
    void testInsertUser() throws Exception {
        SqlSession sqlSession = sessionFactory.openSession();
        //得到UserMapper对象,Mybatis自动生成mapper代理对象
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        //调用userMapper方法
        User user = new User();
        user.setUsername("朱奇瑞");
        user.setAddress("河南");
        user.setBirthday(new Date());
        user.setSex("1");
        userMapper.insertUser(user);
        sqlSession.commit();
        System.out.println(user.getId());
        sqlSession.close();
    }

    @Test
    void testDeleteUser() throws Exception {
        SqlSession sqlSession = sessionFactory.openSession();
        //得到UserMapper对象,Mybatis自动生成mapper代理对象
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        //调用userMapper方法
        userMapper.deleteUser(27);
        sqlSession.commit();
        sqlSession.close();
    }
}
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - Opening JDBC Connection
Sun Mar 18 16:59:32 CST 2018 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
DEBUG [main] - Created connection 2117173674.
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@7e3181aa]
DEBUG [main] - ==>  Preparing: SELECT * FROM USER WHERE username LIKE '%%小明%%' 
DEBUG [main] - ==> Parameters: 
DEBUG [main] - <==      Total: 3
[User [id=16, username=张小明, sex=1, birthday=null, address=河南郑州], User [id=22, username=陈小明, sex=1, birthday=null, address=河南郑州], User [id=25, username=陈小明, sex=1, birthday=null, address=河南郑州]]
DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@7e3181aa]
DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@7e3181aa]
DEBUG [main] - Returned connection 2117173674 to pool.

6、总结

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

  • namespace
    mybatis官方推荐使用mapper代理方法开发mapper接口,程序员不用编写mapper接口实现类,使用mapper代理方法时,输入参数可以使用pojo包装对象或map对象,保证dao的通用性。

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页