博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
MyBtis(一)—— 初识MyBatis
阅读量:3673 次
发布时间:2019-05-21

本文共 9483 字,大约阅读时间需要 31 分钟。

文章目录

mybatis基础知识

MyBatis是一个实现了数据持久化的开源框架,其实它就像netty之于NIO一样,Mybatis是JDBC的封装,所以:

JDBC的缺点:

  1. 需要频繁的进行数据库的建立、连接、断开操作,浪费资源,影响数据库性能;

    解决:连接池

  2. 将SQL语句直接编码在Java代码中,需求改变时,需要修改Java代码;

    解决:将SQL语句和代码分开,SQL语句放在配置文件中

  3. JDBC编程中返回结果集存在硬编码的问题

    解决:将结果集映射成Java对象

MyBatis的优点:

  1. 与JDBC相比,减少了50%以上的代码量。

  2. MyBatis是最简单的持久化框架,小巧并且简单易学。

  3. MyBatis相当灵活,不会对应用程序或者数据库的现有设计强加任何影响,SQL写在XML里,从程序代码中彻底分离,降低耦合度,便于统一管理和优化,并可重用。

  4. 提供XML标签,支持编写动态SQL语句。

  5. 提供映射标签,支持对象与数据库的ORM字段关系映射,可以把对象映射成表的元组、也可以把表中的元组映射成对象;

MyBatis框架的缺点:

  1. SQL语句的编写工作量较大,尤其是字段多、关联表多时,更是如此,对开发人员编写SQL语句的功底有一定要求。

  2. SQL语句依赖于数据库,导致数据库移植性差,不能随意更换数据库。

MyBatis和Hibernate的区别:

对于映射层而言,Hibernate的配置不需要接口和SQL,相反MyBatis是需要的,对于Hibernate而言,不需要编写大量的SQL,就可以完全映射,同时提供了日志、缓存、级联(级联比MyBatis强大)等特性,使用十分方便,但同时,Hibernate也存在巨大的缺陷;

MyBatis可以自由的书写SQL、支持动态SQL、处理列表、动态生成表名、支持存储过程,这样就可以灵活的定义查询语句,满足各类需求和性能优化的需要,这些再互联网系统中是十分重要的;

但MyBatis也有缺陷,他要编写SQL和映射规则,其工作量大于Hibernate,其次,它支持的工具也很有限,不能像Hibernate那样有许多的插件可以帮助生成映射代码和关联关系,而即使使用生成工具,往往也需要开发者进行进一步的简化,MyBatis通过手工编码,工作量相对大一些,所以对于性能要求不太苛刻的系统,使用Hibernate较好,对于性能要求高、响应快、灵活的系统则推荐使用MyBatis;

MyBatis与Hibernate相比主要的优势:

MyBatis不屏蔽SQL,这样开发者可以定制自己的SQL,无须自动生成(同时缺点就是工作量大,需要一定的学习成本),这样能够更精确的定义SQL,从而优化性能,符合移动互联网的高并发、大数据、高性能、高响应的要求;

MyBatis框架适用场合:

MyBatis专注于SQL本身,是一个足够灵活的DAO层解决方案。对性能的要求很高,或者需求变化较多的项目,如互联网项目,MyBatis将是不错的选择。

Mybatis的使用

先来介绍一下mybatis里面的一些组件吧,由SqlSessionFactoryBuilder创建会话工厂SqlSessionFactory,然后由会话工厂创建会话SqlSession(与JDBC中的Statement类似),会话就是一个用户接口(他是不安全的,不能共用,所以一般都会在方法里面,作为一个局部变量),用户就可以那这个SqlSession使用他来操作数据库了;

上面介绍过,MyBatis能提供表元组和对象之间的映射,所以需要建立一张表,这里用Student:

create table Student(    SID int(10),    Sname varchar(20),    Ssex varchar(10),    Age int(10));

然后在这个表里面添加一些数据,以便后面用来测试,随便填写几个就可以了:

在这里插入图片描述

MyBatis开发有两种方式:

使用配置或使用注解;

配置实现

使用步骤:

  1. 导入依赖;
  2. 创建bean类、dao层接口;
  3. 创建Mapper的xml文件、创建mybatis的xml文件;
  4. 使用;

一、导入依赖

1、导入mybatis依赖:

org.mybatis
mybatis
3.4.5

2、还需要数据库的依赖:

mysql
mysql-connector-java
5.1.39

二、创建bean类、Mapper接口

bean类Student:

public class Student {    private int SID;    private String Sname;    private String Ssex;    private int Age;    public int getSID() {        return SID;    }    public void setSID(int SID) {        this.SID = SID;    }    public String getSname() {        return Sname;    }    public void setSname(String sname) {        Sname = sname;    }    public String getSsex() {        return Ssex;    }    public void setSsex(String ssex) {        Ssex = ssex;    }    public int getSage() {        return Age;    }    public void setSage(int sage) {        Age = sage;    }    @Override    public String toString() {        return "[id"+SID+" 名字"+Sname+" 性别"+Ssex+" 年龄"+Age+"]";    }}

需要先创建自定义接口,但是不需要实现该接口,通过Mapper代理来实现:

如下,创建StudentMapper接口:

public interface StudentMapper {    public Student getStudentById(int id);  //根据给定id查找并返回对象}

三、创建两个xml文件

创建StudentMapper.xml文件,也放在resources下面,如上图所示,文件内容如下:

先说明:

  • select标签,和数据库的sql语句类似,这个表示查询,对应的还有update、delete、insert;
  • id:除过使用id还可以使用name,name里面可以含有特殊字符,而id里面不能,表示一个代号或者说标识吧;
  • parameter:入参类型,包括parameterType和parameterMap,参数类型可以是基本数据类型、自定义数据类型、Map类型;
  • result:返回参数的类型,包括resultType和resultMap,参数类型和和上面一样;

在这里插入图片描述

statement标签根据SQL执行的业务可选择insert,delete,update,select。

MyBatis会根据规则自动创建UserDAO接口实现类的代理对象。

规则如下:

  1. Mapper.xml 中 namespace 为Mapper.java接口的全路径名。
  2. Mapper.xml中 statement 的 id 为Mapper.java接口中对应的方法名。
  3. Mapper.xml中 statement 的 parameter和Mapper.java接口中对应方法的参数类型一致。
  4. Mapper.xml中 statement 的 result 和Mapper.java接口中对应方法的返回值类型一致。

补充:

  1. 不管是单个对象还是列表,在mapper.xml中的result的类型是一样的(但是他们的底层调用的方法不同,由mabatis处理,单个对象调用的是selectOne()方法,而列表调用的是selectList()),在对应的mapper.java接口中的返回值不一样;
  2. resultType适用于自定义类型属性和数据库表字段一样,而resultMap一般适用于不一样的情况,包括多表联合查询(即返回新的数据类型的时候);

添加MyBatis全局配置文件config.xml(文件名可自定义,这里用的mybatis-config.xml)

注意使用自己的数据库名字、自己的root用户、密码:

注意,这个xml文件放在与Java文件同级的resources(名字可以自己起,但必须是配置文件,就是文件夹图标下面有4个黄色的横岗)文件下面:

在这里插入图片描述
下面是一个mybatis的配置文件(没用他,只是认识一些常用标签):

四、使用

测试代码:

我用的junit,所以需要这个jar包:

junit
junit
4.12
test
public class TestDemo1 {    @Test    public void test() throws IOException {        String resource = "配置使用mybatis/mybatis-config.xml";        //读取配置文件        InputStream asStream = Resources.getResourceAsStream(resource);        //创建sqlSessionFactory        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(asStream);        //创建sqlSession        SqlSession sqlSession = sqlSessionFactory.openSession();        //通过动态代理产生StudentMapper对象        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);        Student student = mapper.getStudentById(2);  //获取id为2的数据的对象        System.out.println(student);    }}

在这里插入图片描述

注解实现

使用步骤:

  1. 导入依赖;
  2. 创建对应的bean类、dao层接口;
  3. 创建Mapper的xml文件、mybatis的全局配置xml文件;
  4. 使用;

一、导入依赖

和上面一样,略;

二、创建对应的bean类、dao层接口

bean类和上面一样,略,dao层接口需要添加注解,如下(对应的增删该查方法我都写了):

public interface StudentMapper {    @Select("select * from student where SID = #{id}")    public Student getStudentById(int id);    @Select("select * from student where Sname = #{name} and Age = #{age}")    public Student getSnameAndSage(@Param("name") String name, @Param("age") int age);    @Select("select * from student")    public Student[] getAllStudent();    @Insert("insert into student (SID,Sname) values(#{SID},#{Sname})")    public void addStudent(Student student);    @Delete("delete from student where Sid = #{id}")    public void delete(int id);    @Update("update student set Sname = #{name} where id=#{id}")    public void setValue(@Param("id") int id,@Param("name") String name);}

注意:在参数比较多的时候,需要在接口参数类型前面添加@Param(参数名称),否者它就不知道哪个参数放在sql语句的哪个地方了,这样可以指定这个参数是给哪的

三、创建两个xml文件

上面基本一样,只不过SQL语句不用写到StudentMapper.xml里面,在StudentMapper.xml里面只需要这样就可以了:

mybatis的xml文件也不需要修改,略;

测试代码:

public class TestDemo1 {    @Test    public void test() throws IOException {        String resource = "注解使用mybatis/mybatis-config.xml";        //读取配置文件        InputStream asStream = Resources.getResourceAsStream(resource);        //创建sqlSessionFactory        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(asStream);        //创建sqlSession        SqlSession sqlSession = sqlSessionFactory.openSession();        //通过动态代理产生StudentMapper对象        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);        //查询id为2的元组        Student student = mapper.getStudentById(2);        System.out.println("=============查询id=2的记录======================");        System.out.println(student);        //往数据库添加新的元组        Student student1 = new Student();        student1.setSID(4);        student1.setSname("xxx");        mapper.addStudent(student1);        sqlSession.commit();        Student student2 = new Student();        student1.setSID(9);        student1.setSname("xxx");        mapper.addStudent(student2);        sqlSession.commit();        //返回列表所以元素        System.out.println("=============添加两条记录后所有的记录======================");        Student[] students1 = mapper.getAllStudent();        for (Student s : students1) {            System.out.println(s);        }        //删除        mapper.delete(4);        mapper.delete(9);        sqlSession.commit();        System.out.println("=============删除两条记录后所有的记录======================");        Student[] students2 = mapper.getAllStudent();        for (Student s : students2) {            System.out.println(s);        }    }}

在这里插入图片描述

气人,不知道为什么多出一条0的记录!!!

#{}和${}的区别

顺便说一下,在配置文件里面,SQL语句的参数可以是#{} 还可以是${},这两者有什么区呢?

要看区别(后面几节也会用到),需要导入如下三个日志相关的依赖:

log4j
log4j
1.2.17
org.slf4j
slf4j-log4j12
1.7.21
org.slf4j
slf4j-api
1.7.21

然后需要一个 log4j 的配置文件 log4j.properties:

## debug 级别log4j.rootLogger=DEBUG,Consolelog4j.appender.Console=org.apache.log4j.ConsoleAppenderlog4j.appender.Console.Target=System.outlog4j.appender.Console.layout = org.apache.log4j.PatternLayoutlog4j.appender.Console.layout.ConversionPattern=%d{yyyy-MM-dd-HH\:mm\:ss,SSS} [%t]  [%c] [%p] - %m%nlog4j.logger.com.mybatis=DEBUG  /##输出sql 语句log4j.logger.java.sql.Connection=DEBUGlog4j.logger.java.sql.Statement=DEBUGlog4j.logger.java.sql.PreparedStatement=DEBUG

把它配置文件的根目录下面:

在这里插入图片描述
最后就是在我们要用的mybatis的配置文件里面添加:

就是上面我们用的mybatis.xml文件里面添加:

在这里插入图片描述
#{}
相当于JDBC里面的PreparedStatement ;先编译,编译没问题再拿这个编译的结果去执行:

再次运行上面的代码:

在这里插入图片描述

${}

相当于JDBC里面的Statement;直接拿,然后编译执行;

所以相比之下,#{}效率更高,并且不存在,比较安全;

转载地址:http://dxtbn.baihongyu.com/

你可能感兴趣的文章
循环结构,while,do...while,do...while具体实例
查看>>
for循环打印99乘法表,for循环寻找100以内的偶数个数并求和,程序中空格\t
查看>>
设置用户登陆,用户有3次机会输入账号密码,账号密码输入正确则打印输出99乘法表,流程控制语句关键字break和continue,结束方法体return,continue
查看>>
打印三角形,字符串比较,Math.pow,水仙花数,菱形,while对折达到珠穆朗马蜂高度,输出乘数列,scanner,input,输入条件判断是否循环,do...while,顺序分支循环
查看>>
数组,数组越界异常,增强for循环,数组索引,循环遍历数组,利用数组动态输入学生成绩,循环遍历输出数组内容
查看>>
操作数组元素,数组赋值,卫语句,==,Array.equals(数组1,数组2),equals,循环遍历输出数组元素,增强for遍历输出元素,switch,if..else..,比较数组元素是否一致
查看>>
动态录入学生个数,录入每个数组元素,并求出数组元素的最值以及平均值
查看>>
复制数组元素,合并两个已知数组,String数组类型,增强for循环,native,Array.copyof()扩容数组创建新数组,合并数组,Array类的方法对数组进行截断或者扩容
查看>>
Array类,Array.copyof截断和扩容创建新数组,数组引用,copyof其实也是new出了一个新的内存空间
查看>>
删除数组元素,空指针问题
查看>>
冒泡排序,选择排序,插入排序
查看>>
包装类,integer对象,数值型字符串转int类型,装箱,gui查看编译后的class文件,valueof,Integer整数缓存池,比较两个包装类对象
查看>>
字符串转int整型,parseInt底层实现,String类下的charAt()方法,字符串转换成指定类型的一个数值parseXXX(),XXXvalue,valueof,character常用类
查看>>
Character类中的静态方法,Character
查看>>
int整型转字符串,字符串转整型valueof,
查看>>
+=和=,自动类型转换,java基本数据类型,/和%,近似存储,字符串的拼接,i++,++i,四舍五入,default,局部变量
查看>>
docker下载后安装失败:This computer doesn’t have VT-X/AMD-v enabled. Enabling it in the BIOS is mandatory.
查看>>
windeployqt打包显示缺少libgcc_s_seh-1.dll,手动添加后又显示应用程序无法正常启动(0xc000007b)
查看>>
新买的 apple pencil 不灵敏的原因其一
查看>>
GitHub上传大于100MB的文件全流程
查看>>