美文网首页面试问题SpringFrameworkJava学习笔记
SSM框架系列-从JDBC到Mybatis(一)

SSM框架系列-从JDBC到Mybatis(一)

作者: 爱德华的早餐 | 来源:发表于2016-08-31 12:04 被阅读1869次

    前言

    Java学到一定程度,框架终归是不可避免的,毕竟程序开发很多时候不是一个人的事儿。这两天学习了MyBatis框架,想着结合一下这几天学到的东西和实习的经验总结一下。大概的思路就是从JDBC的缺陷到MyBatis的介绍和运行流程,再就是Mybatis的一个增删改查小程序;然后是企业中MyBatis进行数据库开发时采用Dao方法和Mapper方法的一个介绍,最后是和Spring的一个整合。

    也希望大家提出宝贵的建议。

    JDBC

    JDBC小程序

    DBHelper(数据库连接类)

    /**
      * @param连接数据库
      * */
    public class DBHelper {
        //参数配置
    //public static final String url = "jdbc:mysql://127.0.0.1/test";
    public static final String url = "jdbc:mysql://localhost:3306/test?characterEncoding=utf-8";
    public static final String name = "com.mysql.jdbc.Driver";
    public static final String user = "root";
    public static final String password = "8888";
    
    public static Connection conn= null;
    
    public DBHelper() {
        // TODO Auto-generated constructor stub
        try{
            Class.forName(name);            //加载数据库驱动
            conn = DriverManager.getConnection(url, user, password);    //通过驱动管理类获取数据库链接
        }catch(Exception e){
            e.printStackTrace();
        }
    }
    
    public static void Close(){
        try {
            conn.close();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }   
    }
    

    testJdbc(测试SQL查询)

    public class testJdbc {
    
    private static String sql = null;
    private static DBHelper db = null;
    
    public static PreparedStatement pst = null;
    public static ResultSet ret = null;
    
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        db = new DBHelper();        //通过构造器连接到数据库
        System.out.println(db.conn);
        db.Close();
        /*
        //sql = "INSERT INTO `test`.`user` (`Username`, `Password`, `Age`, `Address`, `UserId`) VALUES"
        //      + " ('bb', '1234', '23', 'hubei', '4');";       //插入语句
        //sql = "UPDATE `test`.`user` SET `Username`='ouou' WHERE `UserId`='1';";   //更新语句
        sql = "DELETE * where `UserId` = '2'";                                  //删除语句  
        String sql1 = "select * from user";                                     //选择语句
        try {
            pst = db.conn.prepareStatement(sql);
            pst.execute();
            ret = pst.executeQuery(sql1);
            while(ret.next()){
                String name = ret.getString(1);
                String pass = ret.getString(2);
                String age = ret.getString(3);
                String addr = ret.getString(4);
                String id = ret.getString(5);
                System.out.println(id+" "+name+" "+pass+" "+age+" "+addr);
            }
        }catch(SQLException e){
            e.printStackTrace();
        }*/ 
      }
     }
    

    问题总结

    总结网上搜集到东西和自己实际遇到的归纳为以下几点:

    • 数据库频繁地连接开启和关闭,造成资源的浪费。(使用数据库连接池进行管理)
    • SQL语句、preparedStatement设置参数硬编码在Java代码中,不利于系统维护。(使用xml进行配置)
    • resultSet遍历结果集数据时,也存在硬编码。(将查询的结果集,自动映射成Java对象)

    MyBatis

    为什么选择MyBatis

      MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。MyBatis 避免了几乎所有的 JDBC 
    代码和手工设置参数以及抽取结果集。MyBatis 使用简单的 XML 或注解来配置和映射基本体,将接口和 Java的 
    POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。(选自官网)
    
    • 也就是说开发者只需要关注SQL本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc的过程代码。MyBatis通过xml或注解的方式将要执行的各种statement(statement,preparedStatement、CallableStatement)配置起来,并通过Java对象和statement中的SQL进行映射生成最终执行的SQL语句,最后又mybatis框架执行SQL并将结果映射成Java对象并返回。

    MyBatis是什么

    MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis,实质上Mybatis对ibatis进行一些改进。

    MyBatis框架图

    Paste_Image.png

    MyBatis的运行流程

    • 在SQLMapConfig.xml(mybati的全局配置文件)中配置mybatis的运行环境等信息。并在其中加载mapper.xml(sql映射文件,配置了操作数据库的SQL语句)文件。
    • 通过mybatis环境等配置信息构造SQLSessionFactory会话工厂。
    • 由会话工厂创建SQLSession来操作数据库。
    • mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有基本执行器和缓存执行器两个实现。
    • Mapped Statement也是mybatis一个底层封装对象,包装了mybatis配置信息及SQL映射信息等。mapper.xml文件中一个SQL对应一个Mapped Statement 对象,SQL的id即是Mapped Statement的id。
    • Mapped Statement对SQL执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行SQL前将输入的Java对象映射至SQL中,输入参数映射就是jdbc编程中对preparedStatement设置参数。
    • Mapped Statement对SQL执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行SQL后将输出结果映射至Java对象中,输出结果映射过程相当于jdbc编程中结果的解析处理过程。

    MyBatis的优缺点及Hibernate的简短比较

    Mybatis和hibernate的不同之处在于它不是一个完全的ORM框架,它需要开发者自己编写SQL语句,不过mybatis可以通过xml或注解方式灵活配置要运行的SQL语句,并将Java对象和SQL语句映射生成最终执行的SQL,最后将SQL执行的结果再映射生成Java对象。
    MyBatis相对于hibernate来说,学习门槛低,易于学习,灵活度也高,适合对关系数据模型要求不高的软件开发,以为其需求变化频繁。正是因为mybatis的高度灵活,所以它无法做到数据库无关性,需要实现支持多种数据库的软件则需要自定义多套SQL映射文件。
    Hibernate对象/关系映射能力强,数据库无关性好,对于关系模型要求高的软件(例如需求固定的定制化软件)如果用hibernate开发可以节省很多代码,提高效率。但是Hibernate的学习门槛高,要精通门槛更高,而且怎么设计O/R映射,在性能和对象模型之间如何权衡,以及怎样用好Hibernate需要具有很强的经验和能力才行。
    所以如是说:没有最好的框架,只有最适合的框架。

    简单的CRUD入门程序

    导入的包:


    Paste_Image.png

    项目工程结构:


    Paste_Image.png

    输出日志信息配置(log4j.properties):
    # Global logging configuration
    log4j.rootLogger = DEBUG,stdout
    log4j.appender.stdout = org.apache.log4j.ConsoleAppender
    log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
    log4j.appender.stdout.layout.ConversionPattern = %5p [%t] - %m%n
    全局配置文件(SqlMapConfig.xml):

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
    <!-- 加载属性文件 -->
    <properties resource="db.properties">
    </properties>
    <!-- 和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 = "sqlmap/User.xml"/>
    </mappers>
    
    </configuration>
    

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

    jdbc.driver=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/test?characterEncoding=utf-8
    jdbc.username=root
    jdbc.password=8888
    

    User po类:

    package com.howie.po;
    
    import java.io.Serializable;
    import java.util.Date;
    
    /**
     * @param User po类
     */
    public class User implements Serializable {
    
    private int id;
    private String username;// 用户名
    private String sex;//性别
    private Date birthday;// 生日
    private String address;// 地址
    
    public int getId() {
        return id;
    }
    public void setId(int 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;
    }
    }
    

    映射文件user.xml

    <?xml version="1.0" encoding="UTF-8" ?>  
    <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <!-- 对SQL进行分类话管理,理解SQL隔离
    注意:是用mapper代理方法开发,namespace有特殊重要的作用
     -->
    <mapper namespace = "test">
    
    <!-- 在映射文件中配置很多SQL语句 -->
    
    <!-- 查找 -->
    <select id = "findUserById" parameterType="int" resultType="com.howie.po.User">
        SELECT * FROM test.user where id = #{value}
    </select>
    
    <!-- 添加用户 -->
    <insert id="insertUser" parameterType="com.howie.po.User">
    <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="deleteUserById" parameterType="int">
        delete from user where id=#{id}
    </delete>
    
    <!-- 更新用户 -->
    <update id="updateUser" parameterType="com.howie.po.User">
        update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address}
        where id=#{id}
    </update>
    
    </mapper>
    

    测试文件MybatisTest类
    (避免麻烦,测试一个查找语句,读者感兴趣的可以自行实现其他功能)

    package com.howie.test;
    
    import java.io.IOException;
    import java.io.InputStream;
    
    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 com.howie.po.User;
    
    public class MybatisTest {
    
    public static void findUserByIdTest() throws IOException{
        //配置文件
        String resource = "SqlMapConfig.xml";
        
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //创建回话工厂
        SqlSessionFactory sf = new SqlSessionFactoryBuilder().build(inputStream);
        //通过工厂得到SQLSession
        SqlSession ss = sf.openSession();
        //通过SQLSession操作数据库
        //第一个参数:映射文件中statement的id,等于=namespace+statement的id
        //第二个参数:制定和映射文件中所匹配的parameterType得参数
        //ss.selectOne结果是与映射文件中所匹配的resultType类型的对象
        User user = ss.selectOne("test.findUserById", 1);
        System.out.println(user);
        System.out.print(user.getAddress()+" "+user.getId()+" "+user.getUsername()+
                " "+user.getSex());
        System.out.println();
        //释放资源
        ss.close();
    }
    
    
      public static void main(String[] args) {
        // TODO Auto-generated method stub
        try {
            findUserByIdTest();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    }
    

    未完待续.......

    相关文章

      网友评论

        本文标题:SSM框架系列-从JDBC到Mybatis(一)

        本文链接:https://www.haomeiwen.com/subject/kanfettx.html