什么是Mybatis?
mybatis是一款优秀的持久层框架,她支持定制化SQL、存储过程以及高级映射。MyBatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果集。Mybatis可以使用简单的XML或注解来配置和映射原生信息,将接口和java的POJOs(Plain Old Java Objects,普通的java对象)映射成数据库中的记录。
一、 对原生态jdbc程序中问题总结
JDBC:java database connectivity 是SUN公司提供的一套操作数据库的标准规范。
JDBC与数据库驱动的关系:接口与实现的关系
1.开发一个JDBC程序流程
实现查询数据库中的数据显示在java的控制台上
1、创建数据库表,并向表中添加测试数据
2、创建java project项目,添加数据库驱动(*.jar)
3、实现JDBC操作
- 加载数据库驱动
- 创建数据库链接
- 获取操作数据库sql语句的PreparedStatement对象
- 执行sql语句,并返回结果集ResultSet对象
- 处理结果
- 关闭资源
2.JDBC常用的类和接口详解
1、java.sql.Drivermanager类 : 创建连接
a.与数据库建立连接
getConnection(String url, String user, String password) : 建立到给定数据库 URL 的连接
jdbc:mysql://localhost:3306/day06
协议 子协议 IP :端口号 数据库
2、java.sql.Connection接口:一个连接
接口的实现在数据库驱动中。所有与数据库交互都是基于连接对象的。
prepareStatement()//创建操作sql语句的对象
说明:
PreparedStatement:预编译对象, 是Statement对象的子类。
特点:性能要高,会把sql语句先编译,sql语句中的参数会发生变化,过滤掉用户输入的关键字。
3、java.sql.Statement接口: 操作sql语句,并返回相应结果的对象(小货车)
接口的实现在数据库驱动中。用于执行静态 SQL 语句并返回它所生成结果的对象。
4、java.sql.ResultSet接口: 结果集(客户端存表数据的对象)
提供一个游标,默认游标指向结果集第一行之前。
调用一次next(),游标向下移动一行。
提供一些get方法。
封装数据的方法
Object getObject(int columnIndex); 根据序号取值,索引从1开始
Object getObject(String ColomnName); 根据列名取值。
将结果集中的数据封装到javaBean中
java的数据类型与数据库中的类型的关系(自己查询)
3.jdbc程序中问题总结
- 数据库连接,使用就创建,不适用就立即释放,对数据库进行频繁连接开启和关闭,造成数据库资源浪费,影响数据库性能
解决方法:在SqlMapConfig.xml中使用数据库连接池管理数据库连接 - 将sql语句硬编码到java代码中,如果sql语句修改,需要重新编译java代码,不利于系统维护;
解决方法:将sql语句配置在xml文件,与java代码分离,从而避免sql变化时对java代码的重新编译 - 向preparedStatement中设置参数,对占位符号位置和设置参数值,硬编码在java代码中,不利于系统维护。
解决方法:将sql语句及占位符号和参数全部配置在xml中。 - 从resutSet中遍历结果集数据时,存在硬编码,将获取表的字段进行硬编码,,不利于系统维护。
解决方法: MyBatis将结果集自动映射成java对象,通过statement中的resultType定义输出结果的类型。
二、 Mybatis框架原理
下面作简要概述:
1) SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息。mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句,此文件需要在SqlMapConfig.xml中加载。
2) 通过mybatis环境等配置信息构造SqlSessionFactory(即会话工厂)。
3)由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession进行。
4) mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。
5) MappedStatement也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中一个sql对应一个MappedStatement对象,sql的id即是MappedStatement的id。
6) MappedStatement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过MappedStatement在执行sql前将输入的java对象映射至sql中,输入参数映射就是JDBC编程中对preparedStatement设置参数。
7) MappedStatement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过MappedStatement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于JDBC编程中对结果的解析处理过程。
三、 Mybatis入门程序
3.0 mybatis下载
mybaits的代码由github.com管理,地址:https://github.com/mybatis/mybatis-3/releases
大家可从该地址下载mybatis最新框架。 本人下载的是mybatis-3.2.7,其目录结构为:
3.1 开发需求
- 根据用户id(主键)查询用户信息
- 根据用户名称模糊查询用户信息
- 添加用户
- 删除 用户
- 更新用户
3.2 配置环境
lib下加入的jar包:依赖包,mybatis核心包,mysql的驱动包
3.3 创建日志记录文件 log4j.properties
可在mybatis1222工程下新建一个config源码包,并在该源码包下创建一个日志记录文件——log4j.properties
# Global logging configuration
#在开发环境下日志级别设置成DEBUG,生产环境设置成Info或者error
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
3.4 创建 SqlMapConfig.xml 文件
我们同样可在config源码包下创建该文件
<?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>
<!-- 和spring整合后environments配置将废除 -->
<environments default="development">
<environment id="development">
<!-- 使用jdbc事务管理 -->
<transactionManager type="JDBC" />
<!-- 数据库连接池 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" />
<property name="username" value="root" />
<property name="password" value="123" />
</dataSource>
</environment>
</environments>
</configuration>
SqlMapConfig.xml是mybatis的核心配置文件,以上文件的配置内容为数据源、事务管理。
注意:等后面mybatis和Spring两个框架整合之后,environments的配置将被废除。
3.5 工程结构
3.6 根据用户id(主键)查询用户信息
3.6.1 创建pojo类( User.java )
我们可在src目录下新建一个名为cn.itheima.mybatis.pojo的包,并在该包下创建一个pojo类——User.java
//User.java
package cn.itcast.mybatis.pojo;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
public class User implements Serializable{
//属性名和数据库表的字段对应
private int id;
private String username;
private String sex;
private Date birthday;
private String address;
//用户创建的订单信息
private List<Orders>orderList;
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;
}
public List<Orders> getOrderList() {
return orderList;
}
public void setOrderList(List<Orders> orderList) {
this.orderList = orderList;
}
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", sex=" + sex + ", birthday=" + birthday + ", address="
+ address + "]";
}
}
3.6.2 映射文件( User.xml )
User.xml (原始ibatis命名)
mapper代理开发映射文件名称叫XXXMapper.xml,比如:UserMapper.xml、ItemsMapper.xml
在classpath下的sqlmap目录下创建sql映射文件user.xml ,在映射文件中配置sql语句。
//根据用户id(主键)查询用户信息 代码如下
完整代码如下:
<!--User.xml -->
<?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">
<!-- 通过namespace命名空间,对sql进行分类化管理,理解sql隔离 -->
<!-- 在映射文件中配置sql语句 -->
<mapper namespace="test">
<!--1、根据用户id(主键)查询用户信息
id:标识映射文件中的sql,将sql语句封装到preparedStatement对象中,所以将id成为statement的id
#{}:表示占位符
#{id}:id表示输入参数,参数名称就是id,如果输入参数是简单类型,则#{}中参数名可以任意,可以value或者其他名称
resultType:指定sql输出结果所映射的java对象类型,select指定resultType表示单条记录映射的java对象
-->
<select id="findUserById" parameterType="int" resultType="cn.itcast.mybatis.pojo.User">
SELECT*FROM USER WHERE id=#{id}
</select>
<!--2、 根据用户名称模糊查询用户信息 -->
<!--${value}:拼接符号,不建议使用,接收输入参数的内容,如果传入类型是简单类型,${}中只能使用value-->
<select id="findUserByName" parameterType="java.lang.String" resultType="cn.itcast.mybatis.pojo.User">
<!-- SELECT * FROM USER WHERE USERNAME LIKE'%张三%' -->
SELECT * FROM USER WHERE USERNAME LIKE '%${value}%'
</select>
<!-- 3、添加用户 -->
<!-- 自增主键返回
keyProperty:将查询到主键值设置到parameterType指定的对象的哪个属性
order:相对于insert来说,它的执行顺序
resultType:指定的结果类型 -->
<insert id="insertUser" parameterType="cn.itcast.mybatis.pojo.User">
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
SELECT LAST_INSERT_ID()
</selectKey>
insert into user(username,birthday,sex,address) value(#{username},#{birthday},#{sex},#{address})
<!--
使用mysql的uuid()生成主键
执行过程:
首先通过uuid()得到主键,将主键设置到user对象的id属性中
其次在insert执行时,从user对象中取出id属性值
-->
<!--
<selectKey keyProperty="id" order="BEFORE" resultType="java.lang.String">
SELECT uuid()
</selectKey>
insert into user(id,username,birthday,sex,address) value(#{id},#{username},#{birthday},#{sex},#{address})
-->
</insert>
<!-- 4、删除用户 -->
<delete id="deleteUser" parameterType="java.lang.Integer">
delete from user where id=#{id}
</delete>
<!-- 5、更新用户 -->
<update id="updateUser" parameterType="cn.itcast.mybatis.pojo.User">
update user set
username = #{username},birthday=#{birthday},sex=#{sex},address=#{address}
where id=#{id}
</update>
</mapper>
3.6.3 在SqlMapConfig.xml加载映射文件.xml
在sqlMapConfig.xml中加载User.xml:
完整代码如下:
<?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>
<settings>
<!-- 开启延迟加载,注意必须写在前面 -->
<!-- 打开延迟加载开关 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 将积极加载改为消极加载即是按需加载 -->
<setting name="aggressiveLazyLoading" value="false"/>
<!-- 开启二级缓存 -->
<setting name="cacheEnabled" value="true"/>
</settings>
<!-- 和spring整合后 environments配置将废除-->
<environments default="development">
<environment id="development">
<!-- 使用jdbc事务管理,事务控制由mybatis管理-->
<transactionManager type="JDBC" />
<!-- 数据库连接池,由mybatis管理-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" />
<property name="username" value="root" />
<property name="password" value="123" />
</dataSource>
</environment>
</environments>
<!-- 加载映射文件 -->
<mappers>
<!-- 1、通过resource方法一次加载一个映射文件 -->
<mapper resource="sqlmap/User.xml" />
<!-- 2、通过mapper接口加载单个 映射文件
遵循一些规范:需要将mapper接口类名和mapper.xml映射文件名称保持一致,且在一个目录 中
上边规范的前提是:使用的是mapper代理方法 -->
<!-- <mapper resource="mapper/UserMapper.xml" /> (很重要!!!) -->
<!--3、批量加载mapper
指定mapper接口的包名,mybatis自动扫描包下边所有mapper接口进行加载
遵循一些规范:需要将mapper接口类名和mapper.xml映射文件名称保持一致,且在一个目录 中
上边规范的前提是:使用的是mapper代理方法-->
<package name="cn.itcast.mybatis.mapper"/>
</mappers>
</configuration>
说明:
在sqlmap文件目录里面User.xml中写入sql查询语句(以及输入参数,输出参数信息),然后将User.xml配置文件加载进SqlMapConfig.xml文件中。然后在源文件中导入SqlMapConfig.xml。
数据库里面加载.sql语句,是右键->运行SQL文件,添加进去即可
3.6.4程序测试
在src目录下新建一个名为cn.itheima.mybatis.first的包,并在该包下创建一个MybatisFirst 单元测试类,紧接着在该类中编写如下单元测试方法:
完整代码如下:
package cn.itcast.mybatis.first;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import javax.annotation.Resource;
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 org.junit.Test;
import cn.itcast.mybatis.pojo.User;
public class MybatisFirst {
//1、根据id查询用户信息,得到一条记录结果
@Test
public void findUserByIdTest() throws Exception{
//导入mybatis配置文件
String resource="SqlMapConfig.xml";
//得到配置文件流
InputStream inputStream= Resources.getResourceAsStream(resource);
//1、创建会话工厂
SqlSessionFactory sqlSessionFactory=
new SqlSessionFactoryBuilder().build(inputStream);
//2、根据工厂得到sqlSession
SqlSession sqlSession=sqlSessionFactory.openSession();
//3、通过sqlSession操作数据库
//(control键然后attach mybatis-3.2.7-source.zip )
//statement=namespace.id
//parameter:指定和映射文件中所匹配的parameterType类型的参数
//sqlSession。selectOne结果是与映射文件中所匹配的resultType类型的参数
User user=sqlSession.selectOne("test.findUserById", 1);
System.out.println(user);
//4、关闭会话
sqlSession.close();
}
//2、根据用户名字模糊查询
@Test
public void findUserByNameTest() throws Exception{
//导入mybatis配置文件
String resource="SqlMapConfig.xml";
//得到配置文件流
InputStream inputStream= Resources.getResourceAsStream(resource);
//1、创建会话工厂
SqlSessionFactory sqlSessionFactory=
new SqlSessionFactoryBuilder().build(inputStream);
//2、根据工厂得到sqlSession
SqlSession sqlSession=sqlSessionFactory.openSession();
//3、通过sqlSession操作数据库
//(control键然后attach mybatis-3.2.7-source.zip )
//statement=namespace.id
//parameter:指定和映射文件中所匹配的parameterType类型的参数
//sqlSession.selectOne结果是与映射文件中所匹配的resultType类型的参数
//selectList:表示查询出一个列表
List<User>list=sqlSession.selectList("test.findUserByName", "张三");
System.out.println(list);
//4、关闭会话
sqlSession.close();
}
//3、插入用户信息
@Test
public void insertUserTest() throws Exception{
//导入mybatis配置文件
String resource="SqlMapConfig.xml";
//得到配置文件流
InputStream inputStream= Resources.getResourceAsStream(resource);
//1、创建会话工厂
SqlSessionFactory sqlSessionFactory=
new SqlSessionFactoryBuilder().build(inputStream);
//2、根据工厂得到sqlSession
SqlSession sqlSession=sqlSessionFactory.openSession();
//3、通过sqlSession操作数据库
//插入用户对象
User user=new User();
user.setUsername("王小军");
user.setBirthday(new Date());
user.setSex("男");
user.setAddress("河南郸城");
sqlSession.insert("test.insertUser",user);
//提交事务
sqlSession.commit();
//获取用户信息主键
System.out.println(user.getId());
//4、关闭会话
sqlSession.close();
}
//4、删除用户信息
@Test
public void deleteUserTest() throws Exception{
//导入mybatis配置文件
String resource="SqlMapConfig.xml";
//得到配置文件流
InputStream inputStream= Resources.getResourceAsStream(resource);
//1、创建会话工厂
SqlSessionFactory sqlSessionFactory=
new SqlSessionFactoryBuilder().build(inputStream);
//2、根据工厂得到sqlSession
SqlSession sqlSession=sqlSessionFactory.openSession();
//3、通过sqlSession操作数据库
//根据id 删除用户
sqlSession.delete("test.deleteUser",27);
//提交事务
sqlSession.commit();
//4、关闭会话
sqlSession.close();
}
//5、更新用户信息
@Test
public void updateUserTest() throws Exception{
//导入mybatis配置文件
String resource="SqlMapConfig.xml";
//得到配置文件流
InputStream inputStream= Resources.getResourceAsStream(resource);
//1、创建会话工厂
SqlSessionFactory sqlSessionFactory=
new SqlSessionFactoryBuilder().build(inputStream);
//2、根据工厂得到sqlSession
SqlSession sqlSession=sqlSessionFactory.openSession();
//3、通过sqlSession操作数据库
//更新用户对象
User user=new User();
//必须设置id
user.setId(29);
user.setUsername("王大军");
user.setBirthday(new Date());
user.setSex("2");
user.setAddress("河南洛阳");
sqlSession.insert("test.updateUser",user);
//提交事务
sqlSession.commit();
//4、关闭会话
sqlSession.close();
}
}
3.7 总结
- parameterType:在映射文件中通过parameterType指定输入 参数的类型
resultType:在映射文件中通过resultType指定输出结果的类型。
selectOne 和 selectList
selectOne表示查询出一条记录进行映射。如果使用selectOne可以实现,使用selectList也可以实现(list中只有一个对象)。
selectList表示查询出一个列表(多条记录)进行映射。如果使用selectList查询多条记录,不能使用selectOne。- #{} 和 ${}区别
#{}表示一个占位符号;而 ${}表示一个拼接符号,会引用sql注入,所以不建议使用${}。
#{}和${}均是接收输入参数,类型可以是简单类型,pojo、hashmap。
如果接收简单类型,#{}中可以写成value或其它名称,而${}中只能写成value。
如果接收pojo对象值,#{}和${}均是通过OGNL读取对象中的属性值,通过属性.属性.属性...的方式获取对象属性值。
四、mybatis 和 hibernate 本质区别和应用场景
hibernate:是一个标准ORM框架(对象关系映射)。
入门门槛较高的,不需要程序写sql,sql语句自动生成了。
对sql语句进行优化、修改比较困难的。
应用场景:适用与需求变化不多的中小型项目,比如:后台管理系统,erp、orm、oa。。
mybatis:mybatis是一个不完全 的ORM框架,
虽然程序员自己写sql,mybatis 也可以实现映射(输入映射、输出映射)。
专注是sql本身,需要程序员自己编写sql语句,sql修改、优化比较方便。
应用场景:适用与需求变化较多的项目,比如:互联网项目。