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

前言

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();
    }
}
}

未完待续.......

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,928评论 6 509
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,748评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,282评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,065评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,101评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,855评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,521评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,414评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,931评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,053评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,191评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,873评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,529评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,074评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,188评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,491评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,173评论 2 357

推荐阅读更多精彩内容

  • 1. 简介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的...
    笨鸟慢飞阅读 5,524评论 0 4
  • 1 引言# 本文主要讲解JDBC怎么演变到Mybatis的渐变过程,重点讲解了为什么要将JDBC封装成Mybait...
    七寸知架构阅读 76,480评论 36 980
  • Java数据持久化之mybatis 一. mybatis简介 1.1 原始的JDBC操作: Java 通过 Jav...
    小Q逛逛阅读 4,923评论 0 16
  • 自古清明行客少,吹笛只有牧牛郎。 添香何必非红袖,一曲离殇梦也长。 注:新韵
    幽小窗阅读 428评论 101 41
  • #玩卡不卡·每日一抽# 每一位都可以通过这张卡片觉察自己: 1、直觉他叫什么名字?铁蛋 2、他几岁了?8 3、他现...
    sui想阅读 161评论 0 0