Mybatis之旅(序)

序中序

    本系列旨在探讨mybatis底层逻辑,顺便以源码出发,探究Java语言的若干机制。

    同时,此系列采取工程代码开发中敏捷的原则,不会像以往一样动辄写数千字,而是以“小步快跑”的形式,快速对自己所学的知识作出反应,总结、分享出来。

    本文的第一、二节讲述一些网页应用,ORM和持久化的基本概念,第三节会讲一个最简单的mybatis使用的实例(正如网上大部分博客那样)。

一、网页应用

    以一个不知名博主的主页为例:https://www.jianshu.com/u/6d6837a8715a

    当我们在浏览器输入上面这个链接,按下回车的时候,浏览器就会根据这个链接向相关的服务器请求数据(详情可见《无线世界》系列)。服务器会返回html,js和css文件给我们的电脑,我们电脑上的浏览器会解析这些文件,并且将的页面展示给我们看。

    这种模式被成为浏览器/服务器模式(B/S Browser/Server)。另外一种常见的叫做客户端/服务器模式(C/S Client/Server),咱也不懂,咱也不去说。

    但是上的博主、用户这么多,不可能为每一个人都单独建立一套html/js/css文件,于是采取了比较讨巧的做法:只用一份html/js/css文件来用作页面的展示,而将用户名,文章,动态等信息存进数据库中,为每一个用户配置一个唯一id,用这个id来关联用户的数据。

    这就可以引申到MVC(Model-View-Control)模型的基本思想。M指业务模型,V指用户界面,C指控制器(用于业务模型和用户界面的同步等)。控制器处理用户的入参(比如上例中链接最后的id),控制器会根据入参到业务模型中存取数据(上例中就是取出用户“宫本花藏”的文章、评论等信息),最后在用户界面上予以展示(如上上图所示)。

二、持久化框架与ORM

    在面向对象中,有三层架构的思想。对于服务器来说,用户能够接触到的往往是最外的表现层,使用MVC模式来接收用户数据,或者向用户展示数据;服务层用户用户数据的逻辑处理;而最里面的持久层用于和数据库打交道,负责数据的增删改查。

    人们都说mybatis是持久层框架,就是说mybatis这个框架,是专门用来让Java程序和数据库交互的。

    如果说谁发明了一个服务层框架,就是说他设计的这个框架是专门用来处理业务逻辑的。emmm思考题:这么说来,那些算法的jar包看来都能算成服务层框架了???

    众所周知,服务器能正常运行是要靠代码部署在上面的。Java是常用的服务器逻辑代码。如果想要通过Java访问数据库,就必须使用到Java中的JDBC接口。传统的JDBC连接数据库方式很繁琐,要先注册数据库驱动类,确认url,账号密码,再通过DriverManager打开数据库连接,将拼接好的SQL语句以字符串的形式给Statement,得到执行结果后手动关闭数据库链接。

    为了解决该问题,ORM(Object Relation Mapping,对象-关系映射)框架应运而生。java代码可以根据映射配置文件,完成数据在对象模型(Java语言)与关系模型(SQL语言)之间的映射(比如java中的String类可以转换成SQL中的VARCHAR数据类型)。

    另外,频繁的新建、关闭数据库连接会极大的消耗资源,成为系统的性能瓶颈。ORM框架的另外一个特色功能就是建立数据库连接池:专门创建若干给数据库连接,当某进程有连接请求时就将连接分配给该进程,用完了也不释放连接,而是将连接对象再放进池子里面来,供别的进程使用。

    在书写代码的过程中,千千万万的程序员上演着可歌可泣的与bug斗智斗勇的故事,闻者流泪,听者伤心。代码既要处理用户输入,又要执行业务逻辑,存取数据;同时内要考虑负载均衡进程冲突资源抢占,外要预防非法输入网络攻击安全漏洞,忙不胜收。

    于是,伟大的程序员先贤们针对代码混乱的问题,建立了各种框架。这些框架划分不同功能的代码,让它们各司其职。这些代码大多可以不依赖其他服务独立运行,并且提供某些特定服务。随着时代的发展,不同功能的代码还会划分层次,分出哪些用于公共服务,哪些用于应用实现。

    比如上面这个,分成了基础支持层,核心处理层和接口层3层。每一层各个模块的功能目的都不相同。这个框架就是mybatis整体的框架,也是接下来我们的探索旅程的全景图。

    不过由于本文是序文,所以本文只是给了一个最简单的mybatis使用的示例。

三、mybatis示例

    所需:mysql数据库,集成开发环境IDEA(社区版即可),maven,预先装好的JDK1.8,一个能联网的环境

3.1 MySQL

    既然mybatis是与数据库打交道的框架,就必须安装数据库。以免费的mysql为例,需要先注册ORACLE账户,登录进行下载。没有ORACLE账户的需要注册一个,是免费的。

    mysql向导链接:https://www.mysql.com/cn/why-mysql/white-papers/visual-guide-to-installing-mysql-windows-zh/

    安装的时候需要配置用户名和密码,按它给的pdf文档来即可。安装完成后,打开的界面如下所示:

    点击 Local instance 字样的方框,就可以进入到页面中

    进入数据库后,需要先创建schema。schema可以理解为是一个用户,一个用户可以拥有多张数据表。不同用户之间的数据表不同,并且有访问权限控制。输入以下语句创建用户:

    create schema sjjdata default character set utf8 collate utf8_general_ci;

    选择该用户,创建一个包含id,姓名,年龄3个字段的表,表的名字叫做student(是不是很俗)

use sjjdata;

    create table student

    (id int(11),

    name varchar(25),

    age int(11));

    最终我们在mysql数据库中,创建了一个名为sjjdata的用户,在这个用户下新建了一张名为student的表。

3.2 Maven

    程序语言发展至今,我们编程的时候再也不可能从零开始写。我们会依靠前人的编程成果,即调用代码库的形式,提升我们的编程效率。在Java中,我们通常以使用jar包的形式,调用前人写好的方法,而忽略实现该方法的细节(这种行为也被成为引用依赖)。jar包是一群java文件和配置文件的集合。除了jar包以外,随着规模的不同,还有tar包,war包。一个jar包举例:

    发布jar包的团队或个人通常会每隔一段时间更新这个包, 修复一些bug或者新增一些功能。为了便于区分,他们为每一次发布的jar包取了一个版本号,比如上图中的mybatis包的版本是3.2.7。

    其他程序员在编写程序引用jar包的时候,常常因为jar包的版本不对而引发bug。为了解决此类问题,有很多专门解决依赖的工具,maven就是其中一个。它通过xml文件(往往这个文件的名字叫做pom.xml)确定具体引用哪个版本的哪个包,就可以从它的maven仓库中取出此包,供程序员调用。这么做的好处是在程序移植的时候,只要把对应的xml文件也移植过去,其他机器上就算没有这个jar包,或者没有特定版本的jar包,也可以通过xml文件到maven仓库中找到它。

    maven是apache的开源项目,可以在官网下载。https://maven.apache.org

    下载过来的是一个zip文件,解压,随便放在某个目录就可以。为了避免不必要的字符编码问题,建议放在英文路径下。

    当然,有时候IDEA自己在安装的时候可能已经自带了maven了……

3.3 Java

    IDEA也有官网,也有免费使用的版本,奉上链接:

https://www.jetbrains.com/products.html#type=ide

    笔者下载的是2019.3版本,打开界面如下所示:

    进入后,点击file-->new-->project,选择maven

  点击next,确定工程名,直接finish

    在工程的出生地,就可以发现布局的很有规律的目录,以及一个pom.xml文件,这些都是maven规范自动生成的。

    在xml文件中,贴入如下代码。其含义将在之后逐渐解释。

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0http://maven.apache.org/xsd/maven-4.0.0.xsd">

4.0.0

org.example

SecondMybatis

1.0-SNAPSHOT

org.mybatis

mybatis

3.2.7

mysql

mysql-connector-java

5.1.47

junit

junit

4.12

org.apache.logging.log4j

log4j-api

2.11.1

org.apache.logging.log4j

log4j-core

2.11.1

   

    复制完之后,程序右下角会弹出这样的对话框:

     点击Import Changes,就可以加载pom.xml指定的jar包

    按照如下格式建立目录(直接右键文件夹,new,选择java或者package,这里不再赘述):

  在UserBeanMapper中,写入如下代码:

package com.sjj.dao;

import com.sjj.entity.UserBeanVO;

import java.util.List;

public interface UserBeanMapper {

UserBeanVO queryUserByName(String name);

List queryAll();

int insertUser(UserBeanVO userBean);

int deleteUserByName(String name);

int updateUserById(UserBeanVO userBean,int id);

}

  在UserBeanVO中,写入如下代码:

package com.sjj.entity;

/**

* @author jun

* @date 2019/1/31

*/

public class UserBeanVO {

private int id;

private String name;

private int age;

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 int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

@Override

public String toString() {

return "User{" +

"id=" + id +

", name='" + name + '\'' +

", age=" + age +

'}';

}

}

  在UserBeanService中,写入如下代码:

package com.sjj.service;

public class UserBeanService {

}

  在DBTools中,写入如下代码:

package com.sjj;

import org.apache.ibatis.io.Resources;

import org.apache.ibatis.session.SqlSessionFactory;

import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;

import java.io.Reader;

/**

* @author jun

* @date 2019/1/31

*/

public class DBtools {

private static SqlSessionFactory sqlSessionFactory;

static {

try {

Reader reader = Resources.getResourceAsReader("config/SqlMapConfig.xml");

sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);

} catch (IOException e) {

e.printStackTrace();

}

}

public static SqlSessionFactory getSqlSessionFactory(){

return sqlSessionFactory;

}

}

  在mysql.properties中,写入如下代码(注意,这里需要根据没人配置的不同有所更改):

jdbc.driver=com.mysql.jdbc.Driver

jdbc.url=jdbc:mysql://localhost:3306/sjjdata?useSSL=false

jdbc.username=你的账号,一般是root

jdbc.password=你的密码,安装的时候你自己配的

  在SqlMapperConfig.xml中,写入如下代码:

PUBLIC "-//mybatis.org//DTD Config 3.0//EN"

"http://mybatis.org/dtd/mybatis-3-config.dtd">

  在log4j2.xml中,写入如下代码:

filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz">

%d{MM-dd-yyyy} %p %c{1.} [%t] -%M-%L- %m%n

  在appTest中,写入如下代码:

package com.sjj.test;

import com.sjj.DBtools;

import com.sjj.dao.UserBeanMapper;

import com.sjj.entity.UserBeanVO;

import org.apache.ibatis.session.SqlSession;

import org.apache.ibatis.session.SqlSessionFactory;

public class appTest {

public static void main(String[] args){

//1.创建sqlsessionFactory

SqlSessionFactory sqlSessionFactory = DBtools.getSqlSessionFactory();

//2.创建SqlSession

SqlSession session = sqlSessionFactory.openSession();

//3.session 中创建相应的接口代理类,即mapper对象

UserBeanMapper userBeanMapper = session.getMapper(UserBeanMapper.class);

System.out.println(userBeanMapper.queryAll());

try {

System.out.println(userBeanMapper.deleteUserByName("jun"));

UserBeanVO u1 = new UserBeanVO();

u1.setAge(16);

u1.setName("Nausicaa");

u1.setId(1);

System.out.println(userBeanMapper.insertUser(u1));

session.commit();//一定要提交,不然所有增删改操作不会生效的

System.out.println(userBeanMapper.queryAll());

}catch (Exception e){

session.rollback();//回滚

}

}

}

  最终运行程序,跑出的结果如下所示:

    去MySQL里面查,可以发现,上一篇推送《读书笔记6:<风之谷>》中的主角,娜乌西卡的信息,已经被登记到了数据库之中。

四、总结

    谢特,怎么又有这么多字……

你可能感兴趣的:(Mybatis之旅(序))