Mybatis适用于初学者
Posted 一切随缘~~~
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mybatis适用于初学者相关的知识,希望对你有一定的参考价值。
MyBatis
什么是MyBatis框架
MyBatis 是一个优秀的基于 java 的持久层框架,内部封装了 JDBC,开发者只需要关注 sql 语句本身,
而不需要处理加载驱动、创建连接、创建 statement、关闭连接,资源等繁杂的过程。
MyBatis 通过 xml 或注解两种方式将要执行的各种 sql 语句配置起来,
并通过 java 对象和 sql 的动态参数进行映射生成最终执行的 sql 语句,
最后由 mybatis 框架执行 sql 并将结果映射为 java 对象并返回。
框架是什么
框架(Framework)是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法;
另一种认为,框架是可被应用开发者定制的应用骨架、模板。
简单的说,框架其实是半成品软件,就是一组组件,供你使用完成你自己的系统。
从另一个角度来说框架是一个舞台,你在舞台上做表演。在框架基础上加入你要完成的功能。
框架安全的,可复用的,不断升级的软件。
框架解决的问题
框架要解决的最重要的一个问题是技术整合。
框架把相关的技术融合在一起,企业开发可以集中在业务领
域方面。
另一个方面可以提供开发的效率。
JDBC编程的回顾
可以看之前总结的这篇博客。
使用JDBC编程的缺点
- 代码比较多,开发效率低
- 需要关注 Connection ,Statement, ResultSet 对象的创建和销毁
- 对 ResultSet 查询的结果,需要自己封装为 List
- 重复的代码比较多
- 业务代码和数据库的操作混在一起
MyBatis解决的主要问题
减轻使用 JDBC 的复杂性,不用编写重复的代码创建 Connetion , Statement ;
不用编写关闭资源代码。
直接使用 java 对象,表示结果数据。让开发者专注 SQL 的处理。 其他分心的工作由 MyBatis 代劳。
MyBatis 可以完成:
- 注册数据库的驱动,例如
Class.forName(“com.mysql.jdbc.Driver”))
-
创建 JDBC 中必须使用的 Connection , Statement, ResultSet 对象
-
从 xml 中获取 sql,并执行 sql 语句,把 ResultSet 结果转换 java 对象
List<Student> list = new ArrayLsit<>();
ResultSet rs = state.executeQuery(“select * from student”);
while(rs.next)
Student student = new Student();
student.setName(rs.getString(“name”));
student.setAge(rs.getInt(“age”));
list.add(student);
- 关闭资源
ResultSet.close() , Statement.close() , Conenection.close()
搭建MyBatis开发环境
-
建表
-
引入依赖【MyBatis依赖,Mysql驱动】
-
创建实体类【类的属性名要与表的列名一致】【表的每一行,都可以封装为一个对象】【面向对象的思想】
-
创建持久层的DAO接口
-
创建sql映射文件【写sql语句的,MyBatis会执行这些sql语句】,是一个xml文件。
一般一个表一个sql映射文件。
-
创建MyBatis主配置文件,主配置文件提供了数据库的连接信息和slq映射文件的位置信息。
一个项目就一个主配置文件。
具体搭建过程
-
CREATE TABLE `student` ( `id` int(11) NOT NULL , `name` varchar(255) DEFAULT NULL, `email` varchar(255) DEFAULT NULL, `age` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.1</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.9</version> </dependency> </dependencies> <build> <resources> <resource> <directory>src/main/java</directory><!--所在的目录--> <includes><!--包括目录下的.properties,.xml 文件都会扫描到--> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>false</filtering> </resource> </resources> </build>
-
public class Student //属性名和列名一样 private Integer id; private String name; private String email; private Integer age; // set , get , toString
-
public interface StudentDao /*查询所有数据*/ List<Student> selectStudents();
-
<?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:必须有值,自定义的唯一字符串 推荐使用:dao 接口的全限定名称 --> <mapper namespace="com.xxx.dao.StudentDao"> <!-- <select>: 查询数据, 标签中必须是 select 语句 id: sql 语句的自定义名称,推荐使用 dao 接口中方法名称, 使用名称表示要执行的 sql 语句 resultType: 查询语句的返回结果数据类型,使用全限定类名 --> <select id="selectStudents" resultType="com.xxx.entity.Student"> <!--要执行的 sql 语句--> select id,name,email,age from student </select> </mapper>
-
<?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> <!--配置 mybatis 环境--> <environments default="mysql"> <!--id:数据源的名称--> <environment id="mysql"> <!--配置事务类型:使用 JDBC 事务(使用 Connection 的提交和回滚)--> <transactionManager type="JDBC"/> <!--数据源 dataSource:创建数据库 Connection 对象 type: POOLED 使用数据库的连接池 --> <dataSource type="POOLED"> <!--连接数据库的四个要素--> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/student"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> <mappers> <!--告诉 mybatis 要执行的 sql 语句的位置--> <mapper resource="com/xxx/dao/StudentDao.xml"/> </mappers> </configuration>
-
@Test public void testMyBatis() throws IOException //1.mybatis 主配置文件 String config = "mybatis-config.xml"; //2.读取配置文件 InputStream in = Resources.getResourceAsStream(config); //3.创建 SqlSessionFactory 对象,目的是获取 SqlSession SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in); //4.获取 SqlSession,SqlSession 能执行 sql 语句 SqlSession session = factory.openSession(); //5.执行 SqlSession 的 selectList() List<Student> studentList = session.selectList("com.xxx.dao.StudentDao.selectStudents");//namespace + id //6.循环输出查询结果 studentList.forEach( student -> System.out.println(student)); //7.关闭 SqlSession,释放资源 session.close();
MyBatis配置文件
-
dataSource 标签
-
dataSource 类型
- UNPOOLED: 不使用连接池的数据源
- POOLED: 使用连接池的数据源
- JNDI: 使用 JNDI 实现的数据源
其中 UNPOOLED ,POOLED 数据源实现了 javax.sq.DataSource 接口,
JNDI 和前面两个实现方式不同,了解就可以。
-
dataSource 配置
<dataSource type="POOLED"> <!--连接数据库的四个要素--> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/ssm?charset=utf-8"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource>
-
-
事务
-
默认需要手动提交事务
-
Mybatis 框架是对 JDBC 的封装,所以 Mybatis 框架的事务控制方式,本身也是用 JDBC 的 Connection对象的 commit(), rollback()
Connection 对象的 setAutoCommit()方法来设置事务提交方式的。自动提交和手工提交。 -
-
<transactionManager type="JDBC"/>
-
JDBC:使用 JDBC 的事务管理机制。即通过 Connection 的 commit()方法提交,通过 rollback()方法回滚。
但默认情况下,MyBatis 将自动提交功能关闭了,改为了手动提交。即程序中需要显式的对事务进行提交或回滚。
-
MANAGED:由容器来管理事务的整个生命周期(如 Spring 容器)
-
-
自动提交事务
-
设置自动提交的方式,factory 的 openSession() 分为有参数和无参数的。
有参数为 true,使用自动提交 session = factory.openSession(true)
-
-
-
使用数据库属性配置文件【properties文件】(解耦合)
-
为了方便对数据库连接的管理,DB 连接四要素数据一般都是存放在一个专门的属性文件中的。MyBatis主配置文件需要从这个属性文件中读取这些数据。
-
在 classpath 路径下,创建 properties 文件
-
在 resources 目录创建 jdbc.properties 文件,文件名称自定义。
-
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/ssm?charset=utf-8 jdbc.username=root jdbc.password=root
-
-
使用 properties 标签
-
<?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标签--/> <properties resource="jdbc.properties" />
-
-
使用 key 指定值
-
<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>
-
-
-
-
mappers【映射器】
-
< mapper resource=" " />
-
使用相对于类路径的资源,从 classpath 路径查找文件
-
-
< package name=""/>
-
指定包下的所有 Dao 接口
-
注意:此种方法要求 Dao 接口名称和 mapper 映射文件名称相同,且在同一个目录中。
-
-
MyBatis 使用传统 Dao 开发方式
创建工具类
public class MyBatisUtil
//定义 SqlSessionFactory
private static SqlSessionFactory factory = null;
static
//使用 静态块 创建一次 SqlSessionFactory
try
String config = "mybatis-config.xml";
//读取配置文件
InputStream in = Resources.getResourceAsStream(config);
//创建 SqlSessionFactory 对象
factory = new SqlSessionFactoryBuilder().build(in);
catch (Exception e)
factory = null;
e.printStackTrace();
/* 获取 SqlSession 对象 */
public static SqlSession getSqlSession()
SqlSession session = null;
if( factory != null)
session = factory.openSession();
return session;
DAO开发
(1)创建 Dao 接口实现类
public class StudentDaoImpl implements StudentDao
(2)实现接口中 select 方法
public List<Student> selectStudents()
SqlSession session = MyBatisUtil.getSqlSession();
List<Student> studentList = session.selectList(
"com.xxx.dao.StudentDao.selectStudents");
session.close();
return studentList;
测试查询操作:
// MyBatisTest 类中创建 StudentDaoImpl 对象
public class MyBatisTest
@Test
public void testSelect() throws IOException
StudentDao studentDao = new StudentDaoImpl();
List<Student> studentList = studentDao.selectStudents();
studentList.forEach( stu -> System.out.println(stu));
传统 Dao 开发方式的分析
在前面例子中自定义 Dao 接口实现类时发现一个问题:
Dao 的实现类其实并没有干什么实质性的工作,
它仅仅就是通过 SqlSession 的相关 API 定位到映射文件 mapper 中相应 id 的 SQL 语句,
真正对 DB 进行操作的工作其实是由框架通过 mapper 中的 SQL 完成的。
所以,MyBatis 框架就抛开了 Dao 的实现类,直接定位到映射文件 mapper 中的相应 SQL 语句,
对DB 进行操作。
这种对 Dao 的实现方式称为 Mapper 的动态代理方式。Mapper 动态代理方式无需程序员实现 Dao 接口。
接口是由 MyBatis 结合映射文件自动生成的动态代理实现的。
MyBatis动态代理
我们不再需要编写DAO接口的实现类,只需调用 SqlSession 的 getMapper()方法,即可获取指定接口的实现类对象。该方法的参数为指定 Dao接口类的 class 值。
StudentDao studentDao = MyBatisUtil.getSqlSession().getMapper(StudentDao.class);
使用DAO代理对象执行sql语句
select 方法:
@Test
public void testSelect() throws IOException
List<Student> studentList = studentDao.selectStudents();
studentList.forEach( stu -> System.out.println(stu));
insert 方法:
@Test
public void testInsert() throws IOException
Student student = new Student();
student.setId(1006);
student.setName("林浩");
student.setEmail("linhao@163.com");
student.setAge(26);
int nums = studentDao.insertStudent(student);
System.out.println("使用 Dao 添加数据:"+nums);
update 方法
@Test
public void testUpdate() throws IOException
Student student = new Student();
student.setId(1006);
student.setAge(28);
int nums = studentDao.updateStudent(student);
System.out.println("使用 Dao 修改数据:"+nums);
delete 方法
@Test
public void testDelete() throws IOException
int nums = studentDao.deleteStudent(1006);
System.out.println("使用 Dao 修改数据:"+nums);
原理
这里解释了上面为什么要推荐namespace的值写为: dao接口的全限定名称
id的值写为:dao 接口中方法名称
只有这样MyBatis才能准确的知道你要执行的sql语句是什么
JDK的动态代理
深入理解参数
parameterType:
接口中的方法参数的类型, Java的数据类型的全限定名称或MyBatis定义的别名。
这个属性是可选的,因为 MyBatis通过反射机制能够发现接口方法参数的类型。
MyBatis 传递参数
一个简单类型的参数:
简单类型:MyBatis把基本数据类型和String都叫做简单类型。
使用:#任意字符,和方法的参数无关。
使用#之后,MyBatis执行sql语句使用的是PreparedStatement对象。
关于PreparedStatement对象的使用,可以看这篇博客
多个参数:
- 使用@param
在方法形参前面加入@Param(“自定义参数名”),mapper 文件使用#自定义参数名。
接口方法:
List<Student> selectMultiParam(@Param("personName") String name,
@Param("personAge") int age);
mapper 文件:
<select id="selectMultiParam" resultType="com.xxx.domain.Student">
select id,name,email,age from student where name= #personName or
age= #personAge
</select>
- 使用对象
使用 java 对象传递参数, java 的属性值就是 sql 需要的参数值。 每一个属性就是一个参数。
语法格式: # property, javaType=java 中数据类型名, jdbcType=数据类型名称
javaType, jdbcType 的类型 MyBatis 可以检测出来,一般不需要设置。常用格式 # property 【对象的属性名】
- 按位置(了解)
参数位置从 0 开始, 引用参数语法 # arg 位置 , 第一个参数是#arg0, 第二个是#arg1
注意:mybatis-3.3 版本和之前的版本使用#0,#1方式, 从 mybatis3.4 开始使用#arg0方式。
- 使用Map(了解)
Map 集合可以存储多个值,使用Map向 mapper 文件一次传入多个参数。Map 集合使用 String的 key,
Object 类型的值存储参数。 mapper 文件使用 # key 引用参数值。
例如:
Map<String,Object> data = new HashMap<String,Object>();
data.put(“myname”,”xxx");
data.put(“myage”,20);
接口方法:
List<Student> selectMultiMap(Map<String,Object> map);
mapper 文件:
<select id="selectMultiMap" resultType="com.xxx.domain.Student">
select id,name,email,age from student where name=#myname or age =#myage
</select>
**#**和$
#:占位符,告诉 mybatis 使用实际的参数值代替。并使用PrepareStatement对象执行 sql 语句,
#…代替sql 语句的“?”。这样做更安全【能避免sql注入】,更迅速,效率高,通常也是首选做法。
** ∗ ∗ 【 ∗ ∗ 字 符 串 替 换 ∗ ∗ 】 : 告 诉 m y b a t i s 使 用 ** 【**字符串替换**】:告诉 mybatis 使用 ∗∗【∗∗字符串替换∗∗】:告以上是关于Mybatis适用于初学者的主要内容,如果未能解决你的问题,请参考以下文章