Mybatis学习笔记 —— Mabatis相关基础、原始DAO操作及Mapper代理操作举例

一、原始JDBC的缺陷及Mybatis解决方式

  • JDBC每次操作数据库都会有与数据库连接和释放资源的操作,极大降低了效率——Mybatis采用JDBC连接池
  • 原始JDBC将sql语句硬编码到java文件中,不易维护——Mybatis将sql语句写在多个mapper.xml配置文件中,统一管理维护
  • 原始JDBC从resutSet中获取结果集数据时存在硬编码,不易维护——Mybatis将结果集映射为一个java对象

二、Mybatis大致工作原理

这里写图片描述

三、原始DAO开发实例

1、实现功能

这里写图片描述

  • 根据id准确查询学生信息
  • 根据姓名模糊查询学生信息
  • 增添学生信息
  • 修改学生信息
  • 根据id删除学生信息
2、创建web工程,引入mybatis基础包及依赖包

这里写图片描述

完整目录结构为
这里写图片描述

3、写数据库连接信息DataSource.properities及log4j配置文件log4j.properities
### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.err
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=c:\mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### set log levels - for more verbose logging change 'info' to 'debug' ###

log4j.rootLogger=debug, stdout
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/mybatis_test
jdbc.username=root
jdbc.password=root
4、创建全局配置文件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>


</configuration>
5、在SqlMapConfig.xml中配置数据库连接环境
<properties resource="DataSource.properties"></properties>
    <environments default="development">
        <environment id="development">
        <!-- 使用jdbc事务管理,事务控制由mybatis-->
            <transactionManager type="JDBC" />
        <!-- 数据库连接池,由mybatis管理-->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driverClassName}" />
                <property name="url" value="${jdbc.url}" />
                <property name="username" value="${jdbc.username}" />
                <property name="password" value="${jdbc.password}" />
            </dataSource>
        </environment>
    </environments>
6、创建与数据库结构相同对象的java类Student.java用来与数据库相互的映射
public class Student {
    private int id;
    private String name;
    private String sex;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }

}
7、创建dao接口
public interface StuDao {
    public Student findStuById(int id) throws Exception;

    public List<Student> findStuByName(String name) throws Exception;

    public void addStu(Student Stu) throws Exception;

    public void delStu(int id) throws Exception;

    public void upStu(Student Stu) throws Exception;
}
8、创建StuMapper.xml,配置statement(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="cn.csdn.mybatis.dao.StuDao">
   <select id="findStuById" parameterType="int" resultType="cn.csdn.mybatis.po.Student">
        SELECT * FROM Student WHERE id=#{value}
    </select>

    <select id="findStuByName" parameterType="String" resultType="cn.csdn.mybatis.po.Student">
         SELECT * FROM Student WHERE name LIKE '%${value}%'
    </select>

    <insert id="addStu" parameterType="cn.csdn.mybatis.po.Student" >
        INSERT INTO Student(name,sex) VALUE(#{name},#{sex})
    </insert>

    <delete id="delStu" parameterType="int">
        DELETE FROM Student WHERE id = #{value}
    </delete>

    <update id="upStu" parameterType="cn.csdn.mybatis.po.Student">
        UPDATE  Student SET name = #{name}, sex = #{sex} where id = #{id}
    </update>
</mapper>
9、在SqlMapConfig.xml中配置StuMapper.xml
<mappers>
        <mapper resource="mapper/StuMapper.xml"/>
</mappers>
10、写StuDao.java的实现类StuImp.java
public class StuImp implements StuDao{
    SqlSessionFactory sqlSessionFactory;
    public StuImp(SqlSessionFactory sqlSessionFactory) {
        this.sqlSessionFactory = sqlSessionFactory;
    }
    @Override
    public Student findStuById(int id) throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        Student Stu = sqlSession.selectOne("cn.csdn.mybatis.dao.StuDao.findStuById",id);
        sqlSession.close();
        return Stu;
    }
    @Override
    public List<Student> findStuByName(String name) throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        List<Student> Stus = sqlSession.selectList("cn.csdn.mybatis.dao.StuDao.findStuByName",name);
        sqlSession.close();
        return Stus;
    }
    @Override
    public void addStu(Student stu) throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        sqlSession.insert("cn.csdn.mybatis.dao.StuDao.addStu",stu);
        sqlSession.commit();
        sqlSession.close();
    }
    @Override
    public void delStu(int id) throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        sqlSession.delete("cn.csdn.mybatis.dao.StuDao.delStu",id);
        sqlSession.commit();
        sqlSession.close();
    }
    @Override
    public void upStu(Student stu) throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        sqlSession.update("cn.csdn.mybatis.dao.StuDao.upStu",stu);
        sqlSession.commit();
        sqlSession.close();
    }

}
11、采用JUnit单元测试一个操作:
class StuImpTest {
    private SqlSessionFactory sqlSessionFactory;
    @BeforeEach
    void setUp() throws Exception {
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("SqlMapConfig.xml")); 
    }

    @Test
    void testFindStuById() throws Exception {
        StuImp stuImp = new StuImp(sqlSessionFactory);
        Student stu = stuImp.findStuById(1);
        System.out.println(stu.toString());
    }
}

这里写图片描述

原始DAO操作数据库功能实现!

四、原始DAO方式总结

StuMapper.xml中

  • namespace理论上可以写任何值,但为了与mapper代理的方式对应,此处写dao接口的完整地址
  • parameterType:指定输入参数的类型
  • resultType:指定输出参数的类型
  • #{}:占位符,类似于?,参数为简单类型时括号里的值可任意,一般写#{value}
  • ${}:无视格式的字符串拼接符,但会有sql注入的风险,所以不推荐使用,参数为简单类型时,括号里的值必须为value

StuImp.java中

  • selectOne:表示查询出一条记录进行映射。如果使用selectOne可以实现使用selectList也可以实现(list中只有一个对象)。
  • selectList:表示查询出一个列表(多条记录)进行映射。如果使用selectList查询多条记录,不能使用selectOne。

SqlSession使用范围

  • SqlSessionFactoryBuilder:当做一个工具类,创建SqlSessionFactory
  • SqlSessionFactory:通过SqlSessionFactory创建SqlSession,使用单例模式管理sqlSessionFactory(工厂一旦创建,使用一个实例)。(上例采用构造的方法注入同一个sqlSessionFactory)
  • SqlSession:
    • SqlSession是一个面向用户(程序员)的接口。
    • SqlSession中提供了很多操作数据库的方法:如:selectOne(返回单个对象)、selectList(返回单个或多个对象)。
    • SqlSession是线程不安全的,在SqlSesion实现类中除了有接口中的方法(操作数据库的方法)还有数据域属性。
    • SqlSession最佳应用场合在方法体内,定义成局部变量使用。

五、原始DAO操作中存在的问题

  • 问题主要存在于dao的实现类中
  • 在每一条sql语句的执行中,StuImp.java存在了大量的重传代码,如sqlSession的获得、释放等等。
  • 在执行SqlSession.insert()、SqlSession.delete()、SqlSession.update()、SqlSession.select()时,对statement的id硬编码,不易维护;参数的输入使用泛型,不利于在编译阶段发现输入参数不对的问题
    ——由此,更好的使用Mybatis的方法为Mapper代理方式,满足一定的编写规范,把dao接口的实现(下称为mapper接口)丢给Mybatis**自动处理**。

六、mapper代理方式实例

1、Mybatis使用mapper代理的方式要遵循的规则
  • 在mapper.xml中namespace为mapper接口地址。上例已经提过
  • mapper接口中的方法名和mapper.xml中statement的id一致
  • mapper接口中的方法输入参数类型和mapper.xml中statement的parameterType指定的类型一致。
  • mapper接口中的方法返回值类型和mapper.xml中statement的resultType指定的类型一致。
2、上例原始DAO模式的编写中已经符合的上述四点规范,所以不再重新复制代码,1-9步完全一致,不需要第10步创建实现类
3、直接用JUnit测试添加学生:
class StuDaoTest {
    private SqlSessionFactory sqlSessionFactory;
    @BeforeEach
    void setUp() throws Exception {
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("SqlMapConfig.xml")); 
    }

    @Test
    void testAddStu() throws Exception{
        SqlSession sqlSession = sqlSessionFactory.openSession();
        StuDao stuDao =  sqlSession.getMapper(StuDao.class);//获得代理对象
        Student stu = new Student();
        stu.setName("小红");
        stu.setSex("女");
        stuDao.addStu(stu);//需要手动提交
        sqlSession.commit();

    }
}

mapper代理方式完成,简单高效!

猜你喜欢

转载自blog.csdn.net/qq_37969433/article/details/80647809