MyBatis 框架概述 mybatis 是一个优秀的基于 java 的持久层框架,它内部封装了 jdbc,使开发者只需要关注 sql 语句本身, 而不需要花费精力去处理加载驱动、创建连接、创建 statement 等繁杂的过程。 mybatis 通过 xml 或注解的方式将要执行的各种 statement 配置起来,并通过 java 对象和 statement 中 sql 的动态参数进行映射生成最终执行的 sql 语句,最后由 mybatis 框架执行 sql 并将结果映射为 java 对象并 返回。 采用 ORM 思想解决了实体和数据库映射的问题,对 jdbc 进行了封装,屏蔽了 jdbc api 底层访问细节,使我 们不用与 jdbc api 打交道,就可以完成对数据库的持久化操作。
jdbc 程序的回顾 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 public static void main (String[] args) { Connection connection = null ; PreparedStatement preparedStatement = null ; ResultSet resultSet = null ; try { Class.forName("com.mysql.jdbc.Driver" ); connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" ,"root" , "root" ); String sql = "select * from user where username = ?" ; preparedStatement = connection.prepareStatement(sql); preparedStatement.setString(1 , "王五" ); resultSet = preparedStatement.executeQuery(); while (resultSet.next()){ System.out.println(resultSet.getString("id" ) + resultSet.getString("username" )); } } catch (Exception e) { e.printStackTrace(); }finally { if (resultSet!=null ){ try { resultSet.close(); } catch (SQLException e) { e.printStackTrace(); } } if (preparedStatement!=null ){ try { preparedStatement.close(); } catch (SQLException e) { e.printStackTrace(); } } if (connection!=null ){ try { connection.close(); } catch (SQLException e) { e.printStackTrace(); } } }
我的第一个Mybatis项目 maven项目配置文件:pox.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 <?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" > <?xml version="1.0" encoding="UTF-8" ?> <project xmlns ="http://maven.apache.org/POM/4.0.0" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" > <modelVersion > 4.0.0</modelVersion > <groupId > pers.mrLiu.mybatisTest</groupId > <artifactId > myBatisTest</artifactId > <version > 1.0-SNAPSHOT</version > <properties > <project.build.sourceEncoding > UTF-8</project.build.sourceEncoding > <maven.compiler.source > 1.8</maven.compiler.source > <maven.compiler.target > 1.8</maven.compiler.target > </properties > <dependencies > <dependency > <groupId > org.mybatis</groupId > <artifactId > mybatis</artifactId > <version > 3.5.4</version > </dependency > <dependency > <groupId > log4j</groupId > <artifactId > log4j</artifactId > <version > 1.2.12</version > </dependency > <dependency > <groupId > mysql</groupId > <artifactId > mysql-connector-java</artifactId > <version > 5.1.6</version > </dependency > <dependency > <groupId > junit</groupId > <artifactId > junit</artifactId > <version > 4.11</version > </dependency > </dependencies > </project >
Mybatis配置文件:SqlMapConfig.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 <?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 > <properties Resource ="jdbcConfig.properties" > </properties > <typeAliases > <package name ="pers.mrLiu.mybatisTest.domain" > </package > </typeAliases > <environments default ="mysql" > <environment id ="mysql" > <transactionManager type ="JDBC" /> <dataSource type ="POOLED" > <property name ="driver" value ="com.mysql.jdbc.Driver" /> <property name ="url" value ="jdbc:mysql://47.100.77.53/jvtcGroupOfRobot" /> <property name ="username" value ="jvtcGroupOfRobot" /> <property name ="password" value ="aA2428933105." /> </dataSource > {配置中的属性名} {driver} {url} {username} {password} </environment > </environments > <mappers > <package name ="com.itheima.dao" > </package > </mappers > </configuration >
Mybatis映射配置(不使用xml配置映射则不需要此文件):对应着每个dao接口文件,例如:UserDao.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <?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 ="pers.mrLiu.mybatisTest.dao.UserDao" > <select id ="findAll" resultType ="pers.mrLiu.mybatisTest.domain.User" > select * from user; </select > </mapper >
jdbcConfig.Properties配置(不使用外部JDBC配置文件则不需要) 1 2 3 4 driver =com.mysql.jdbc.Driverurl =jdbc:mysql://localhost:3306 /eesy_mybatisusername =rootpassword =1234
log4j日志配置文件:log4j.properties 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 log4j.rootCategory =debug, CONSOLE, LOGFILElog4j.logger.org.apache.axis.enterprise =FATAL, CONSOLElog4j.appender.CONSOLE =org.apache.log4j.ConsoleAppenderlog4j.appender.CONSOLE.layout =org.apache.log4j.PatternLayoutlog4j.appender.CONSOLE.layout.ConversionPattern =%d{ISO8601} %-6 r [%15.15 t] %-5 p %30.30 c %x - %m\nlog4j.appender.LOGFILE =org.apache.log4j.FileAppenderlog4j.appender.LOGFILE.File =d:\axis.loglog4j.appender.LOGFILE.Append =true log4j.appender.LOGFILE.layout =org.apache.log4j.PatternLayoutlog4j.appender.LOGFILE.layout.ConversionPattern =%d{ISO8601} %-6 r [%15.15 t] %-5 p %30.30 c %x - %m\n
UserDao接口 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 package pers.mrLiu.mybatisTest.dao;import pers.mrLiu.mybatisTest.domain.User;import java.util.List;public interface UserDao { List<User> findAll () ; }
调用Mybatis框架DAO层实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 InputStream resourceAsStream = Resources . getResourceAsStream("SqlMapConfig.xml" ) ; SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder() ; SqlSessionFactory build = sqlSessionFactoryBuilder.build(resourceAsStream); SqlSession sqlSession = build.open Session() ; UserDao userDao = sqlSession.getMapper(UserDao.class ) ; List<User> users = userDao.findAll() ; users.for Each(System.out ::println ) ;
Mybatis框架的执行流程
Mybatis框架执行原理
1.读取核心配置文件并返回InputStream流对象。 2.根据InputStream流对象解析出Configuration对象,然后创建SqlSessionFactory工厂对象 3.根据一系列属性从SqlSessionFactory工厂中创建SqlSession 4.从SqlSession中调用Executor执行数据库操作&&生成具体SQL指令 5.对执行结果进行二次封装 6.提交与事务
Mybatis映射配置中SQL语句#{}
与 ${}
的使用(面试) 例1:根据ID查用户信息 1 2 3 4 <select id ="findById" resultType ="com.itheima.domain.User" parameterType ="int" > select * from user where id = # {uid} </select >
resultType 属性:结果集的类型
parameterType 属性:传入参数的类型
sql 语句中使用#{}
字符:它代表占位符,相当于原来 jdbc 部分所学的?,都是用于执行语句时替换实际的数据。具体的数据是由#{}里面的内容决定的。
#{}中内容的写法:由于数据类型是基本类型(int),所以此处可以随意写
例2:保存用户 1 2 3 4 5 <insert id ="saveUser" parameterType ="com.itheima.domain.User" > insert into user(username,birthday,sex,address) values(# {username} ,# {birthday} ,# {sex} ,# {address} ) </insert >
parameterType 属性:代表参数的类型,因为我们要传入的是一个类的对象,所以类型就写类的全名称。
sql 语句中使用#{}
字符:它代表占位符,相当于原来 jdbc 部分所学的?,都是用于执行语句时替换实际的数据
#{}中内容的写法:由于我们保存方法的参数是 一个 User 对象,此处要写 User 对象中的属性名称(它用的是 ognl
表达式)
ognl 表达式:
它是 apache 提供的一种表达式语言,全称是:Object Graphic Navigation Language 对象图导航语言 它是按照一定的语法格式来获取数据的。 语法格式就是使用 #{对象.对象}
的方式
#{user.username}
它会先去找 user 对象,然后在 user 对象中找到 username 属性,并调用getUsername()
方法把值取出来。但是我们在 parameterType 属性上指定了实体类名称 ,所以可以省略 user.
而直接写 username
例3:新增用户后获取自增id的返回值
新增用户后,同时还要返回当前新增用户的 id 值,因为 id 是由数据库的自动增长来实现的,所以就相当于我们要在新增后将自动增长 auto_increment 的值返回
1 2 3 4 5 6 7 8 9 10 11 <insert id ="saveUser" parameterType ="USER" > <selectKey keyColumn ="id" keyProperty ="id" resultType ="int" order ="AFTER" > select last_insert_id(); </selectKey > insert into user(username,birthday,sex,address) values(# {username} ,# {birthday} ,# {sex} ,# {address} ) </insert >
keyColumn:数据库中列名
keyProperty:数据模型JavaBean对象的属性名
order:执行SQL语句之前还是之后再执行此标签内容,AFTE:之后, BEFORE:之前
#{}
与${}
的区别#{}表示一个占位符号
通过#{}可以实现 preparedStatement 向占位符
中设置值,自动进行 java 类型和 jdbc 类型转换,#{}可以有效防止 sql 注入 。 #{}可以接收简单类型值或 pojo 属性值。 如果 parameterType 传输单个简单类型值(基本数据类型:String、int等),#{}括号中可以是 value 或其它名称(随便输入)。
${}表示拼接 sql 串
通过${}可以将 parameterType 传入的内容拼接 在 sql 中且不进行 jdbc 类型转换 ${}可以接收简单类型值或 pojo 属性值 如果 parameterType 传输单个简单类型值,${}括号中只能是 value 。
resultMap 结果类型 resultMap 标签可以建立查询的列名和实体类的属性名称不一致时建立对应关系。从而实现封装。 在 select 标签中使用 resultMap 属性指定引用即可。同时 resultMap 可以实现将查询结果映射为复杂类 型的 pojo,比如在查询结果映射对象中包括 pojo 和 list 实现一对一查询和一对多查询。
示例: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <resultMap type ="com.itheima.domain.User" id ="userMap" > <id column ="id" property ="userId" /> <result column ="username" property ="userName" /> <result column ="sex" property ="userSex" /> <result column ="address" property ="userAddress" /> <result column ="birthday" property ="userBirthday" /> </resultMap > <select id ="findById" resultMap ="userMap" parameterType ="int" > select * from user where id = # {uid} </select >
id 标签:用于指定主键字段
result 标签:用于指定非主键字段
column 属性:用于指定数据库列名
property 属性:用于指定实体类属性名称
扩展(面试题):为什么实体类(user类)要实现Serializable 接口呢?
网上查了一下资料,如下:
Serializable接口是一个里面什么都没有的接口 它的源代码是public interface Serializable{},即什么都没有。
如果一个接口里面什么内容都没有,那么这个接口是一个标识接口 比如,一个学生遇到一个问题,排错排了几天也没解决,此时,她举手了(示意我去帮他解决),然后我过去,帮他解决了,那么这个举手其实就是一个标识,自己不能解决的问题标示我去帮他解决
在Java中的这个Serializable接口是给JVM看的,告诉JVM,我不做这个类的序列化了,你(JVM)给我序列化,序列化就是变成二进制流,比如云计算、Hadoop,特别是Hadoop完全就是分布式环境,那么就要涉及到对象要在网络中传输,里面的全是二进制流,当然你来做这个序列化操作也可以,但是这个类里面可能还有一个类,如果你把外面的类对象Person变成二进制,那么里面也要序列化(这要用到深度遍历,很麻烦),干脆告诉JVM,让他来帮你做。