MyBatis
MyBatis
author:あさひ
小煦
软件下载地址:https://github.com/mybatis/mybatis-3/releases
GitHub地址:https://github.com/mybatis/mybatis-3
官方文档参考地址:https://mybatis.org/mybatis-3/zh/getting-started.html
一、框架概述
三层架构
界面层(User Interface layer): 和用户打交道的, 接收用户的请求参数, 显示处理结果的。(jsp ,html ,servlet)
controller包 (servlet)
业务逻辑层(Business Logic Layer): 接收了界面层传递的数据,计算逻辑,调用数据库,获取数据
service 包(XXXService类)
数据访问层(Data access layer): 就是访问数据库, 执行对数据的查询,修改,删除等等的。
dao包(XXXDao类)
三层交互顺序为: 用户使用界面层--> 业务逻辑层--->数据访问层(持久层)-->数据库(mysql)
三层架构对应的处理框架
- 界面层---servlet---springmvc(框架)
- 业务逻辑层---service类--spring(框架)
- 数据访问层---dao类--mybatis(框架)
框架
框架是一个舞台, 一个模版。 框架是一个软件,半成品的软件,定义好了一些基础功能, 需要加入你的功能就是完整的。
基础功能是可重复使用的,可升级的。
模版:
- 规定了好一些条款,内容。
- 加入自己的东西
框架是一个模块
- 框架中定义好了一些功能。这些功能是可用的。
- 可以加入项目中自己的功能, 这些功能可以利用框架中写好的功能。
框架特点
- 框架一般不是全能的, 不能做所有事情
- 框架是针对某一个领域有效。 特长在某一个方面,比如mybatis做数据库操作强,但是他不能做其它的。
- 框架是一个软件
JDBC的缺陷
- 代码比较多,开发效率低
- 需要关注Connection ,Statement, ResultSet对象创建和销毁
- 对ResultSet查询的结果,需要自己封装为List
- 重复的代码比较多些
- 业务代码和数据库的操作混在一起
二、MyBatis框架入门
MyBatis SQL Mapper Framework for Java
SQL Mapper:可以把数据库表中的一行数据 映射为 一个java对象。一行数据可以看做是一个java对象。操作这个对象,就相当于操作表中的数据
Data Access Objects(DAOs) : 数据访问 , 对数据库执行增删改查。
MyBatis是一个优秀的基于java的持久层框架,内部封装了jdbc,开发者只需要关注sql语句本身,而不需要处理加载驱动、创建连接、创建statement、关闭连接,资源等繁杂的过程。MyBatis通过xml或注解两种方式将要执行的各种sql语句配置起来,并通过java对象和sql 的动态参数进行映射生成最终执行的sql 语句,最后由mybatis 框架执行sql 并将结果映射为java 对象并返回。
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAOs)
当前,最新版本是MyBatis 3.5.6,发布时间:2020年7月10日,上午4:57。
GitHub地址:https://github.com/mybatis/mybatis-3
官方文档参考地址:https://mybatis.org/mybatis-3/zh/getting-started.html
mybatis提供的功能
- 提供了创建Connection ,Statement, ResultSet的能力 ,不用开发人员创建这些对象了
- 提供了执行sql语句的能力, 不用你执行sql
- 提供了循环sql, 把sql的结果转为java对象, List集合的能力
while (rs.next()) {
Student stu = new Student();
stu.setId(rs.getInt("id"));
stu.setName(rs.getString("name"));
stu.setAge(rs.getInt("age"));
//从数据库取出数据转为 Student 对象,封装到 List 集合
stuList.add(stu);
}
- 提供了关闭资源的能力,不用你关闭Connection, Statement, ResultSet
开发人员做的是: 提供sql语句
最后是: 开发人员提供sql语句--mybatis处理sql---开发人员得到List集合或java对象(表中的数据)
mybatis是一个sql映射框架,提供的数据库的操作能力。增强的JDBC,
使用mybatis让开发人员集中精神写sql就可以了,不必关心Connection,Statement,ResultSet的创建,销毁,sql的执行。
入门第一个示例
要求:
1、新建student表
2、创建一个maven项目,加入maven的mybatis坐标,mysql驱动的坐标
3、创建实体类,Student--保存表中的一行数据
4、创建持久层的DAO接口,定义操作数据库的方法
5、创建一个mybatis使用的配置文件
叫做sql映射文件,写SQL语句的一般一个表一个sql映射文件。这个文件是XML文件。
文件在接口所在的目录中。
文件名称和接口保持一致。
6、创建一个mybatis的主配置文件:
一个项目中就一个主配置文件
主配置文件提供了数据库连接信息和sql映射文件的位置信息
7、创建使用mybatis类,通过mybatis访问数据库
代码实现
- 按照要求在Navicat中测试数据库新建一个student表。

- 加入maven的mybatis坐标,mysql驱动的坐标
<!--mybatis依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.1</version>
</dependency>
<!--mysql的驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.48</version>
</dependency>
- 创建实体类,Student--保存表中的一行数据
实体类
package org.hanxu.domain;
//推荐和表名一致。容易记忆。
public class Student {
//定义属性,目前要求属性名和列名保持一致
private Integer id;
private String name;
private String email;
private Integer age;
public Student(Integer id, String name, String email, Integer age) {
this.id = id;
this.name = name;
this.email = email;
this.age = age;
}
public Student() {
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", email='" + email + '\'' +
", age=" + age +
'}';
}
}
编写DAO接口类
package org.hanxu.dao;
import org.hanxu.domain.Student;
import java.util.List;
//接口操作student表
public interface StudentDao {
//查询student表中所有数据
public List<Student> selectStudents();
}
接口类同目录的XML文件(SQL映射)
StudentDao.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!--sql映射文件(sql mapper),写sql语句的,mybatis会执行这些sql
指定约束文件
mybatis-3-mapper.dtd是约束文件的名称,扩展名是dtd的。
约束文件的作用
限制、检查当前文件中出现的标签和属性,必须符合mybatis的要求
-->
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--
mapper 是当前文件的根标签,必须的
namespace 叫做命名空间,唯一值,可以是自定义的字符串
要求你使用dao接口的全限定名称。
在当前文件中,可以使用特定的标签,表示数据库的特定操作
<select>:表示执行查询
<update>:表示更新数据库的操作,就是在<update>标签中写的是update sql语句
<insert>:表示插入,放的是insert语句
<delete>:表示删除,执行delete语句
-->
<mapper namespace="org.hanxu.dao.StudentDao">
<select id="selectBlog" resultType="Blog">
select * from blog where id = #{id}
</select>
<!--
select 表示查询操作
id 你要执行sql语句的唯一标识,mybatis会使用这个id的值,来找到要执行的sql语句
可以自定义,但是要求你使用接口中的方法名
resultType 表示结果类型的,是sql语句执行后得到的ResultSet,遍历这个ResultSet得到的java对象的类型
值写的是类型的全限定名称
-->
<select id="selectStudents" resultType="org.hanxu.domain.Student">
select id,name,email,age from student order by id;
</select>
<!--
sql映射文件:写sql语句的,mybatis会执行这些sql语句
-->
</mapper>
mybatis主配置文件链接数据库
文件位置resource根目录下,文件名称自定义如:mybatis.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>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="org/mybatis/example/BlogMapper.xml"/>
</mappers>
</configuration>
我自己的配置
<?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>
<environments default="mydev">
<environment id="mydev">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test?useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="hanxu"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="org/hanxu/dao/StudentDao.xml"/>
</mappers>
</configuration>
在pom.xml中加上maven指定资源位置
<build>
<resources>
<resource>
<directory>src/main/java</directory><!--所在的目录-->
<includes><!--包括目录下的.properties,.xml 文件都会扫描到-->
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<!--filtering 选项 false 不启用过滤器, *.property 已经起到过滤的作用了 -->
<filtering>false</filtering>
</resource>
</resources>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
主程序测试
package org.hanxu;
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.hanxu.domain.Student;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class MyApp {
public static void main(String[] args) throws IOException {
//访问mybatis,读取student数据
//1、定义mybatis主配置文件的名称,从类路径的根开始(target/class)
String config = "mybatis.xml";
//2、读config这个文件
InputStream in = Resources.getResourceAsStream(config);
//3、创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//4、创建SqlSessionFactory对象
SqlSessionFactory factory = builder.build(in);
//5、获取SqlSession对象,从SqlSessionFactory中获取SqlSession
SqlSession sqlSession = factory.openSession();
//6、指定要执行的sql语句标识。sql映射文件的namespace+"."+标签的的id值
String sqlId = "org.hanxu.dao.StudentDao" + "." + "selectStudents";
//7、执行sql语句,通过sqlId找到语句
List<Student> studentList = sqlSession.selectList(sqlId);
//8、输出结果
// studentList.forEach(stu -> System.out.println(stu));
for(Student stu : studentList){
System.out.println("查询的学生="+stu);
}
//9、关闭SqlSession对象
sqlSession.close();
}
}
/*执行结果:
查询的学生=Student{id=1001, name='李四', email='lisi@qq.com', age=20}
查询的学生=Student{id=1002, name='张三', email='zhangsan@qq.com', age=28}
*/
插入功能测试
DAO接口加入插入方法
package org.hanxu.dao;
import org.hanxu.domain.Student;
import java.util.List;
//接口操作student表
public interface StudentDao {
//查询student表中所有数据
public List<Student> selectStudents();
//插入方法
//参数:
// student 表示要插入的数据
// int 表示执行insert操作后的影响数据库的行数
public int insertStudents(Student student);
}
mapper映射添加插入sql语句
<insert id="insertStudents">
insert into student value(#{id},#{name},#{email},#{age})
</insert>
测试代码
package org.hanxu;
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.hanxu.domain.Student;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
public class TestMyBatis {
//测试方法,测试功能
@Test
public void testInsert() throws IOException {
//访问mybatis,读取student数据
//1、定义mybatis主配置文件的名称,从类路径根开始(target/classes)
String config = "mybatis.xml";
//2、读config这个文件
InputStream in = Resources.getResourceAsStream(config);
//3、创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//4、创建SqlSessionFactory对象
SqlSessionFactory factory = builder.build(in);
//5、获取SqlSession对象,从SqlSessionFactory中获取SqlSession
SqlSession sqlSession = factory.openSession();
//6、指定要执行的sql语句标识。sql映射文件的namespace+"."+标签的的id值
String sqlId = "org.hanxu.dao.StudentDao.insertStudents";
//7、执行sql语句,通过sqlId找到语句
Student student = new Student(1004,"李飞","lifei@163.com",23);
int num = sqlSession.insert(sqlId,student);
//mybatis默认不是自动提交事务的,所以在insert,update,delete后要手动提交事务
sqlSession.commit();
//8、输出结果
System.out.println("执行操作行数:" +num+"行");
sqlSession.close();
}
}
设置日志
mybatis.xml文件加入日志配置,可以在控制台输出执行的sql语句和参数
<!--settings:控制mybatis全局行为-->
<settings>
<!--设置mybatis输出日志-->
<setting name="logImpl" value="STDOUT_LOGGING" />
</settings>
总结步骤
-
作用
- 增强的jdbc,访问数据库,执行增删改查
-
基本步骤
-
加入maven依赖
-
<!--mybatis依赖--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.1</version> </dependency> <!--mysql的驱动--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.9</version> </dependency>
-
-
创建Dao接口
- 定义了你操作数据的方法
-
创建mapper文件,也叫做sql映射文件:写sql语句的,和接口中方法对应的sqly语句
-
创建mybatis的一个主配置文件
- 链接数据库
- 指定mapper文件的位置
-
使用mybatis对象SqlSession,通过他的方法执行sql语句
-
避免踩坑
在测试时发现,maven编译的时候资源文件不一定会拷贝到target\classes目录下,首先检查pom.xml中是否添加了资源位置
<resources>
<resource>
<directory>src/main/java</directory><!--所在的目录-->
<includes><!--包括目录下的.properties,.xml 文件都会扫描到-->
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<!--filtering 选项 false 不启用过滤器, *.property 已经起到过滤的作用了 -->
<filtering>false</filtering>
</resource>
</resources>
资源目录下的文件,默认idea会拷贝到target\classe,如果没有拷贝,需要检查资源文件夹是否make as resource,如果还是不能拷贝,点击菜单栏
---Build--Rebuild Project
然后再重新编译执行,一般都可以解决。或者直接清除idea缓存:--File--Invilidate caches/Restart.
我的暴力解决办法就是再次添加资源位置!!!如果还不行,那就再暴力一点,勤快一点,直接手动拷贝吧~哎
<resource>
<directory>src/main/resources</directory><!--所在的目录-->
<includes><!--包括目录下的.properties,.xml 文件都会扫描到-->
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<!--filtering 选项 false 不启用过滤器, *.property 已经起到过滤的作用了 -->
<filtering>false</filtering>
</resource>
三、主要类的介绍
Resources: mybatis中的一个类, 负责读取主配置文件
InputStream in = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactoryBuilder : 创建SqlSessionFactory对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//创建SqlSessionFactory对象
SqlSessionFactory factory = builder.build(in);
SqlSessionFactory: 重量级对象, 程序创建一个对象耗时比较长,使用资源比较多。在整个项目中,有一个就够用了。
SqlSessionFactory:接口 , 接口实现类: DefaultSqlSessionFactory
SqlSessionFactory作用: 获取SqlSession对象。SqlSession sqlSession = factory.openSession();
openSession()方法说明
- openSession() :无参数的, 获取是非自动提交事务的SqlSession对象
- openSession(boolean)
- openSession(true) 获取自动提交事务的SqlSession对象
- openSession(false) 非自动提交事务的SqlSession对象
SqlSession
- SqlSession接口 :定义了操作数据的方法
- selectOne() ,selectList() ,insert(),update(), delete(), commit(), rollback()
- SqlSession接口的实现类DefaultSqlSession。
注意:
使用要求: SqlSession对象不是线程安全的,需要在方法内部使用, 在执行sql语句之前,使用openSession()获取SqlSession对象。
在执行完sql语句后,需要关闭它,执行SqlSession.close(). 这样能保证他的使用是线程安全的。
工具类代码
package org.hanxu.util;
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 java.io.IOException;
import java.io.InputStream;
public class MyBatisUtils {
private static SqlSessionFactory factory = null;
static {
//主配置文件是什么名字就写啥,根据实际情况填写
String config = "mybatis.xml";
try {
InputStream in = Resources.getResourceAsStream(config);
//创建SqlSessionFactory对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
factory = builder.build(in);
} catch (IOException e) {
e.printStackTrace();
}
}
//获取SqlSession的方法
public static SqlSession getSqlSession(){
SqlSession sqlSession = null;
if (factory != null){
sqlSession = factory.openSession();//非自动提交事务
}
return sqlSession;
}
}
工具类验证
有没有顿感 减少了很多代码量
package org.hanxu;
import org.apache.ibatis.session.SqlSession;
import org.hanxu.domain.Student;
import org.hanxu.util.MyBatisUtils;
import java.io.IOException;
import java.util.List;
public class MyApp_bak {
public static void main(String[] args) throws IOException {
//获取SqlSession对象,从SqlSessionFactory中获取SqlSession
SqlSession sqlSession = MyBatisUtils.getSqlSession();
//【重要】指定要执行的sql语句标识。sql映射文件的namespace+"."+标签的的id值
String sqlId = "org.hanxu.dao.StudentDao" + "." + "selectStudents";
//【重要】执行sql语句,通过sqlId找到语句
List<Student> studentList = sqlSession.selectList(sqlId);
//输出结果
studentList.forEach(stu -> System.out.println(stu));
// for(Student stu : studentList){
// System.out.println("查询的学生="+stu);
//
// }
//9、关闭SqlSession对象
sqlSession.close();
}
}
IDEA创建常用文本模板
操作方法:
菜单栏File ——>Setting——>Eeditor——>File and Code Templates
在右边Files下面点击加号
Name:mybatis-mapper
Extension: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">
<mapper namespace="">
<select id="" resultType="">
</select>
</mapper>
点击应用和ok
同理添加主配置文件模板
Name:mybatis-config
Extension: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>
<environments default="mydev">
<environment id="mydev">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test?useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="hanxu"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="org/hanxu/dao/StudentDao.xml"/>
</mappers>
</configuration>
编写Dao功能实现类
package org.hanxu.impl;
import org.apache.ibatis.session.SqlSession;
import org.hanxu.dao.StudentDao;
import org.hanxu.domain.Student;
import org.hanxu.util.MyBatisUtil;
import java.util.List;
public class StudentDaoImpl implements StudentDao {
@Override
public List<Student> selectStudents() {
SqlSession sqlSession = MyBatisUtil.getSqlSession();
String sql = "org.hanxu.dao.StudentDao.selectStudents";
List<Student> list = sqlSession.selectList(sql);
sqlSession.close();
return list;
}
}
测试程序
import org.hanxu.domain.Student;
import org.hanxu.impl.StudentDaoImpl;
import java.util.List;
public class APP {
public static void main(String[] args) {
StudentDaoImpl v = new StudentDaoImpl();
List<Student> list = v.selectStudents();
for (Student s: list) {
System.out.println(s);
}
}
}
四、mybatis动态代理
mybatis的动态代理:mybatis根据dao接口的方法调用,获取执行sql语句的信息。mybatis根据你的dao接口的实现类,并创建这个类的对象。完成sqlsession调用方法,访问数据库。
我们删除掉之前自己创建的实现类,使用JDK的动态代理获取dao接口的实现类,来调用方法。
使用动态代理查询操作
@Test
public void selectTest(){
/**
*使用动态代理机制,使用SqlSession.getMapper(dao接口)
* getMapper可以获取dao接口的实现类对象
*/
SqlSession sqlSession = MyBatisUtil.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
List<Student> list = dao.selectStudents();
for (Student stu:list
) {
System.out.println(stu);
}
}
使用动态代理插入操作
public void insertTest(){
SqlSession sqlSession = MyBatisUtil.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
Student student = new Student();
student.setId(1102);
student.setAge(30);
student.setName("铁锤");
student.setEmail("asahi@qq.com");
int num = dao.insertStudents(student);
sqlSession.commit();
System.out.println("添加成功"+num);
}
在控制台打印输出动态代理
//com.sun.proxy.$Proxy2 JDK的动态代理
System.out.println(dao.getClass().getName());
五、深入理解参数
parameterType
接口中方法参数的类型,类型的完全限定名或别名。这个属性是可选的,因为MyBatis可以推断出具体传入语句的参数,默认值为未设置(unset)。接口中方法的参数从java代码传入到mapper文件的sql语句。
mybatis参数别名
| Alias | Mapped Type |
|---|---|
| _byte | byte |
| _long | long |
| _short | short |
| _int | int |
| _integer | int |
| _double | double |
| _float | float |
| _boolean | boolean |
| string | String |
| byte | Byte |
| long | Long |
| short | Short |
| int | Integer |
| integer | Integer |
| double | Double |
| float | Float |
| boolean | Boolean |
| date | Date |
| decimal | BigDecimal |
| bigdecimal | BigDecimal |
| object | Object |
| map | Map |
| hashmap | HashMap |
| list | List |
| arraylist | ArrayList |
| collection | Collection |
| iterator | Iterator |
parameterType
写在mapper文件中的 一个属性。 表示dao接口中方法的参数的数据类型。
例如StudentDao接口
public Student selectStudentById(Integer id)
mapper文件
<select id="selectIdenById" parameterType="int" resultType="org.hanxu.domain.Student">
select id,name,email,age from student where id = #{id}
</select>
<select id="selectIdenById" parameterType="java.lang.Integer" resultType="org.hanxu.domain.Student">
select id,name,email,age from student where id = #{id}
</select>
MyBatis传递参数
从java代码中把参数传递到mapper.xml文件。
一个简单参数
mybatis把java的基本数据类型和String都叫简单类型。在mapper文件获取简单类型的一个参数的值,使用 #{任意字符}
//接口
public Student selectStudentById(Integer id)
<!--mapper-->
select id,name, email,age from student where id=#{studentId}
测试方法:
@Test
public void selectTest(){
/**
*使用动态代理机制,使用SqlSession.getMapper(dao接口)
* getMapper可以获取dao接口的实现类对象
*/
SqlSession sqlSession = MyBatisUtil.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
Student stu = dao.selectIdenById(1102);
System.out.println(stu);
}
多个参数
(必会)使用@Param传参
接口
// @Param("参数名") String name
/**
*多个参数,命名参数,在形参定义前面加入@Param("自定义参数名称")
*/
public List<Student> selectMulitParam(@Param("myname") String name,
@Param("myage") Integer age);
mapper文件
<!--多个参数命名-->
<select id="selectMulitParam" resultType="org.hanxu.domain.Student">
select * from student where name=#{myname} or age=#{myage}
</select>
测试程序
@Test
public void selectMulitParamTest(){
SqlSession sqlSession = MyBatisUtil.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
List<Student> studentList = dao.selectMulitParam("铁锤", 30);
for (Student stu:
studentList
) {
System.out.println(stu);
}
sqlSession.close();
}
(必会)使用对象传参
Supported JDBC Types
| BIT | FLOAT | CHAR | TIMESTAMP | OTHER | UNDEFINED |
| TINYINT | REAL | VARCHAR | BINARY | BLOB | NVARCHAR |
| SMALLINT | DOUBLE | LONGVARCHAR | VARBINARY | CLOB | NCHAR |
| INTEGER | NUMERIC | DATE | LONGVARBINARY | BOOLEAN | NCLOB |
| BIGINT | DECIMAL | TIME | NULL | CURSOR | ARRAY |
接口
/**
* 多个参数,使用java对象作为接口中方法的参数
*/
List<Student> selectMulitObjectParam(QueryParam param);
mapper文件
<!--
多个参数命名,使用java对象的属性值,作为参数实际值
使用对象语法:#{属性名,javaType=类型名称,jdbcType=数据类型}
javaType:只java中的属性数据类型
jdbcType:在数据库中的数据类型
例如:#{paramName,javaType=java.lang.String,jdbcType=VARCHAR}
简化方式:
#{属性名} ,javaType,jdbcType的值mybatis反射机制能获取。不用提供
-->
<!-- <select id="selectMulitObjectParam" resultType="org.hanxu.domain.Student">-->
<!-- select * from student where-->
<!-- name=#{paramName,javaType=java.lang.String,jdbcType=VARCHAR}-->
<!-- or age=#{paramAge,javaType=java.lang.integer,jdbcType=INTEGER}-->
<!-- </select>-->
<select id="selectMulitObjectParam" resultType="org.hanxu.domain.Student">
select * from student where
name=#{paramName} or age=#{paramAge}
</select>
参数类
package org.hanxu.vo;
public class QueryParam {
private String paramName;
private int paramAge;
public String getParamName() {
return paramName;
}
public void setParamName(String paramName) {
this.paramName = paramName;
}
public int getParamAge() {
return paramAge;
}
public void setParamAge(int paramAge) {
this.paramAge = paramAge;
}
}
测试程序
@Test
public void selectMulitObjectParamTest(){
SqlSession sqlSession = MyBatisUtil.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
QueryParam param = new QueryParam();
param.setParamAge(30);
param.setParamName("铁锤");
List<Student> students = dao.selectMulitObjectParam(param);
for (Student stu:
students
) {
System.out.println(stu);
}
sqlSession.close();
}
(了解)按位置传参
参数位置从0开始,引用参数语法#{arg位置},第一个参数是#{arg0}, 第二个是#{arg1}注意:mybatis-3.3版本和之前的版本使用#{0},#{1}方式,从mybatis3.4开始使用#{arg0}方式。
接口方法
List<Student> selectByNameAndAge(String name,int age);
mapper文件
<select id="selectByNameAndAge" resultType="com.bjpowernode.domain.Student">
select id,name,email,age from student where name=#{arg0} or age =#{arg1}
</select>
测试方法
@Testpublic void testSelectByNameAndAge(){
//按位置参数
SqlSession sqlSession = MyBatisUtil.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
List<Student> stuList = dao.selectByNameAndAge("李力",20);
stuList.forEach( stu -> System.out.println(stu));
}
(了解)使用Map传参
Map集合可以存储多个值,使用Map向mapper文件一次传入多个参数。Map集合使用String的key,Object类型的值存储参数。mapper文件使用#{key}引用参数值。
接口方法
List<Student> selectMultiMap(Map<String,Object> map);
mapper文件
<select id="selectMultiMap" resultType="com.bjpowernode.domain.Student">
select id,name,email,age from student where name=#{myname} or age =#{myage}
</select>
测试方法
@Testpublic void testSelectMultiMap(){
SqlSession sqlSession = MyBatisUtil.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
Map<String,Object> data = new HashMap<>();
data.put("myname","李力");// #{myname}
data.put("myage",20); // #{myage}
List<Student> stuList = dao.selectMultiMap(data);
stuList.forEach( stu -> System.out.println(stu));}
(必知)#和$
#:占位符
告诉mybatis使用实际的参数值代替。并使用PrepareStatement对象执行sql语句,#{...}代替sql语句的“?”。这样做更安全,更迅速,通常也是首选做法。
<select id="selectIdenById" parameterType="int" resultType="org.hanxu.domain.Student">
select id,name,email,age from student where id = #{id}
</select>
mybatis执行的是
String sql=”select id,name,email,age from student where id=?”;
PreparedStatement ps = conn.prepareStatement(sql);
ps.setInt(1,1102);
解释
where id=? 就是where id=#{id}
ps.setInt(1,1102) , 1102会替换掉#{id}
$:字符串替换
告诉mybatis使用$包含的“字符串”替换所在位置。使用Statement把sql语句和${}的内容连接起来。主要用在替换表名,列名,不同列排序等操作。
例如:
<select id="selectIdenById" parameterType="int" resultType="org.hanxu.domain.Student">
select id,name,email,age from student where id = ${id}
</select>
接口方法
Student findByDiffField(@Param("col") String colunName,@Param("cval") Object value);
mapper文件
<select id="findByDiffField" resultType="com.bjpowernode.domain.Student">
select * from student where ${col}=#{cval}
</select>
测试方法
@Test
public void testFindDiffField(){
Student student1 = studentDao.findByDiffField("id",1002);
System.out.println("按id列查询:"+student1);
Student student2 = studentDao.findByDiffField("email","zhou@126.net");
System.out.println("按email列查询:"+student2);
}
注意:$:可以替换表名或者列名, 你能确定数据是安全的。可以使用$
总结
- mybatis的传递参数
- 从java程序把数据传入到mapper文件的sql语句
- dao方法有一个简单类型的参数,在mapper文件夹中,使用#
- 使用@Param注解给参数命名,在mapper文件中,使用#
- 使用java对象传参,在mapper文件中,使用#
- 使用参数的位置,在mapper文件中,#
- 使用map,#
- \#和 $区别)
- \#是占位符,使用?做占位符,mybatis内部使用PreparedStatement执行sql,效率高
- \#表示列的值,一般是放在等号的右侧使用
- \#能够避免sql注入,更安全。
- $是字符串代理连接,把sql语句和${}位置的值连接在一起
- $表示的内容时原样替换的
- $有sql注入的风险,缺乏安全性。
- $不使用占位符,是字符串连接方式,mybatis使用Statement对象执行sql的,效率低
- $一般是替换列名、表名、部分sql语句的
六、封装MyBatis输出结果
resultType
执行sql得到ResultSet转换的类型,使用类型的完全限定名或别名。注意如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身。resultType 和resultMap,不能同时使用。
结果类型,指sql语句执行完毕之后,数据转为的java对象。
- mybatis执行sql语句,然后mybatis调用的无参构造方法,创建对象。
- 返回对象不一定是实体类,也可以是自己自定义的类
- mybatis把ResultSet指定列值赋给同名的属性。
<select id="selectIdenById" parameterType="int" resultType="org.hanxu.domain.Student">
select id,name,email,age from student
</select>
对等的JDBC
ResultSet rs= sta.executeQuery(" select id,name,email,age from student ");
while(rs.next()){
Student student = new Student();
student.setId(rs.getInt("id"));
student.setName(rs.getString("name"))
}
对象类型
接口方法
ViewStudent selectViewStudent(@Param("sid") Integer id);
mapper文件
<select id="selectViewStudent" resultType="org.hanxu.domain.ViewStudent">
select * from student where id = #{sid}
</select>
自定义视图类
package org.hanxu.domain;
public class ViewStudent {
private Integer id;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "ViewStudent{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
测试程序
@Test
public void selectViewStudentTest(){
SqlSession sqlSession = MyBatisUtil.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
ViewStudent stu = dao.selectViewStudent(1106);
System.out.println(stu);
sqlSession.close();
}
简单类型
接口方法
int selectCount();
mapper文件
<select id="selectCount" resultType="int">
select count(*) from student
</select>
测试程序
@Test
public void selectCountTest(){
SqlSession sqlSession = MyBatisUtil.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
int num = dao.selectCount();
System.out.println(num);
sqlSession.close();
}
Map类型
接口方法
Map<Object,Object> selectMap(Integer id);
mapper文件
<!--返回Map
1、列名是map的key,列值是map的value
2、只能最多返回一行记录,多余一行是不行的
-->
<select id="selectMap" resultType="map">
select * from student where id = #{stuid}
</select>
测试程序
@Test
public void selectMapTest(){
SqlSession sqlSession = MyBatisUtil.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
Map<Object, Object> map = dao.selectMap(1001);
System.out.println(map);
}
/*执行结果
<== Columns: id, name, email, age
<== Row: 1001, 李四, lisi@qq.com, 20
*/
自定义类型的别名
建议使用全限定名称。更加安全!
- 在mybatis主配置文件中定义,使
定义别名
<typeAliases>
<!--第一种方式-->
<!--
一行可以指定一个类型一个自定义别名
type:自定义类型的全限定名称
alias:别名(短小,容易记忆的)
-->
<typeAlias type="org.hanxu.domain.ViewStudent" alias="view"/>
<typeAlias type="org.hanxu.domain.Student" alias="stu"/>
<!--第二种方式-->
<!--
<package> name是包名,包下面的所有类,类名就是别名(类名不区分大小写)
-->
<package name="org.hanxu.domain"/>
</typeAliases>
- 可以在mapper文件中的resultType中使用自定义别名
<!--第一种方式-->
<select id="selectViewStudent" resultType="view">
select * from student where id = #{sid}
</select>
<!--第二种方式-->
<select id="selectViewStudent" resultType="ViewStudent">
select * from student where id = #{sid}
</select>
测试程序
@Test
public void selectViewStudentTest(){
SqlSession sqlSession = MyBatisUtil.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
ViewStudent stu = dao.selectViewStudent(1106);
System.out.println(stu);
sqlSession.close();
}
实体类属性名和数据库列名不同的处理方式
resultMap
resultMap可以自定义sql的结果和java对象属性的映射关系。更灵活的把列值赋值给指定属性。常用在列名和java对象属性名不一样的情况。
使用方式:
- 先定义resultMap,指定列名和属性的对应关系。
- 在<select>中把resultType替换为resultMap。
接口方法
List<Student> selectResultMap();
mapper文件
<!--
创建resultMap:
id:自定义的唯一名称,在<select>使用
type:期望转为的java对象的全限定名称或别名
-->
<resultMap id="studentmap" type="org.hanxu.domain.Student">
<!--主键字段使用id -->
<id column="id" property="id" />
<!--非主键字段使用result-->
<result column="name" property="name"/>
<result column="email" property="email" />
<result column="age" property="age" />
</resultMap>
<!--resultMap: resultMap标签中的id属性值-->
<select id="selectResultMap" resultMap="studentmap">
select id,name,email,age from student
</select>
测试程序
@Test
public void selectResultMapTest(){
SqlSession sqlSession = MyBatisUtil.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
List<Student> students = dao.selectResultMap();
for (Student stu:students
) {
System.out.println(stu);
}
sqlSession.close();
}
使用列别名和<resultType>
resultType的默认原则是同名的列值赋值给同名的属性,使用列别名(java对象的属性名)
mapper文件
<select id="selectUseFieldAlias" resultType="com.bjpowernode.domain.PrimaryStudent">
select id as stuId, name as stuName,age as stuAge from student where name=#{queryName} or age=#{queryAge}
</select>
resultMap和resultType不要一起用,二选一
模糊查询like
模糊查询的实现有两种方式,一是java代码中给查询数据加上“%”; 二是在mapper文件sql语句的条件位置加上“%”
接口方法
List<Student> selectLike(String name);
mapper文件
<select id="selectLike" resultType="org.hanxu.domain.Student">
select id, name,age from student where name like #{name}
</select>
测试程序
@Test
public void selectLikeTest(){
SqlSession sqlSession = MyBatisUtil.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
String name = "%铁%";
List<Student> students = dao.selectLike(name);
for (Student stu:students
) {
System.out.println(stu);
}
sqlSession.close();
}
还有一种方式就是在mapper文件中使用like name "%" #{xxx} "%"
七、MyBatis框架动态SQL
动态sql:sql的内容是变化的,可以根据条件获取到不同的sql语句。主要是where部分发生变化。
动态sql的实现,使用的是mybatis提供的标签,<if>、<where>、<foreach>
动态SQL,主要用于解决查询条件不确定的情况:在程序运行期间,根据用户提交的查询条件进行查询。提交的查询条件不同,执行的SQL语句不同。若将每种可能的情况均逐一列出,对所有条件进行排列组合,将会出现大量的SQL语句。此时,可使用动态SQL来解决这样的问题
动态SQL-if
对于该标签的执行,当test的值为true时,会将其包含的SQL片断拼接到其所在的SQL语句中。
语法:<if test="条件"> sql语句的部分</if>
接口方法
List<Student> selectStudentIf(Student student);
mapper文件
<select id="selectStudentIf" resultType="org.hanxu.domain.Student">
select id,name,email,age from student where 1=1
<if test="name !=null and name != ''">
and name =#{name}
</if>
<if test="age > 0">
and age > #{age}
</if>
</select>
测试方法
@Test
public void selectTest(){
SqlSession sqlSession = MyBatisUtil.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
Student student = new Student();
student.setName("铁锤");
student.setAge(40);
List<Student> students = dao.selectStudentIf(student);
for (Student stu:
students
) {
System.out.println(stu);
}
sqlSession.close();
}
动态SQL-where
<if/>标签的中存在一个比较麻烦的地方:需要在where后手工添加1=1的子句。因为,若where后的所有<if/>条件均为false,而where后若又没有1=1子句,则SQL中就会只剩下一个空的where,SQL出错。所以,在where后,需要添加永为真子句1=1,以防止这种情况的发生。但当数据量很大时,会严重影响查询效率。使用<where/>标签,在有查询条件时,可以自动添加上where子句;没有查询条件时,不会添加where子句。需要注意的是,第一个<if/>标签中的SQL片断,可以不包含and。不过,写上and也不错,系统会将多出的and去掉。但其它<if/>中SQL片断的and,必须要求写上。否则SQL语句将拼接出错。
语法:<where>其他动态sql</where>
接口
List<Student> selectStudentWhere(Student student);
mapper文件
<select id="selectStudentWhere" resultType="org.hanxu.domain.Student">
select id,name,email,age from student
<where>
<if test="name !=null and name != ''">
and name =#{name}
</if>
<if test="age > 0">
or age > #{age}
</if>
</where>
</select>
测试代码
@Test
public void selectStudentWhereTest(){
SqlSession sqlSession = MyBatisUtil.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
Student student = new Student();
// student.setName("铁锤");
// student.setAge(2);
List<Student> students = dao.selectStudentWhere(student);
for (Student stu:
students
) {
System.out.println(stu);
}
sqlSession.close();
}
动态SQL-foreach
<foreach/>标签用于实现对于数组与集合的遍历。对其使用,需要注意
- collection表示要遍历的集合类型,list ,array等。
- open、close、separator为对遍历内容的SQL拼接
语法:
<foreach collection="集合类型" open="开始的字符" close="结束的字符" item="集合中的成员" separator="集合成员之间的分隔符">
#{item的值}
</foreach>
写一个自动拼接sql
@Test
public void selectStudentForeachTest(){
//SqlSession sqlSession = MyBatisUtil.getSqlSession();
//StudentDao dao = sqlSession.getMapper(StudentDao.class);
List<Integer> list = new ArrayList<>();
list.add(1001);
list.add(1002);
list.add(1003);
String sql = "select id,name,email,age from student where id in";
StringBuffer stringBuffer = new StringBuffer();
int init= 0;
int len =list.size();
stringBuffer.append("(");
for (Integer i :
list) {
stringBuffer.append(i).append(",");
}
stringBuffer.deleteCharAt(stringBuffer.length()-1);
stringBuffer.append(")");
System.out.println(sql+stringBuffer.toString());
sqlSession.close();
}
//结果:select id,name,email,age from student where id in(1001,1002,1003)
遍历简单类型list
接口
List<Student> selectStudentForeach(List<Integer> list);
mapper文件
<select id="selectStudentForeach" resultType="org.hanxu.domain.Student">
select id,name,email,age from student where id in
<foreach collection="list" item="myid" open="(" close=")" separator=",">
#{myid}
</foreach>
</select>
测试代码
@Test
public void selectForeachTest(){
SqlSession sqlSession = MyBatisUtil.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
List<Integer> list = new ArrayList<>();
list.add(1001);
list.add(1002);
list.add(1003);
List<Student> students = dao.selectStudentForeach(list);
System.out.println(students);
sqlSession.close();
}
遍历对象类型list
接口方法
List<Student> selectStudentForList2(List<Student> stuList);
mapper文件
<select id="selectStudentForList2" resultType="com.bjpowernode.domain.Student">
select id,name,email,age from student
<if test="list !=null and list.size > 0 ">
where id in
<foreach collection="list" open="(" close=")" item="stuobject" separator=",">
#{stuobject.id}
</foreach>
</if>
</select>
测试方法
@Test
public void testSelectForList2(){
SqlSession sqlSession = MyBatisUtil.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
List<Student> list = new ArrayList<>();
Student s1 = new Student();s1.setId(1002);
list.add(s1);
s1 = new Student();
s1.setId(1005);
list.add(s1);
List<Student> studentList = dao.selectStudentForList2(list);
studentList.forEach( stu -> System.out.println(stu));
}
动态SQL-片段复用
mapper文件
<!--创建sql片段id:片段的自定义名称-->
<sql id="sql">
select id,name,email,age from student
</sql>
<select id="selectStudentWhere" resultType="org.hanxu.domain.Student">
<!--引用sql片段-->
<include refid="sql"/>
<where>
<if test="name !=null and name != ''">
and name =#{name}
</if>
<if test="age > 0">
or age >= #{age}
</if>
</where>
</select>
八、MyBatis配置文件
settings配置
<!-- settings是 MyBatis 中全局的调整设置,它们会改变 MyBatis 的运行时行为,应谨慎设置 -->
<settings>
<!-- 该配置影响的所有映射器中配置的缓存的全局开关。默认值true -->
<setting name="cacheEnabled" value="true"/>
<!--延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置fetchType属性来覆盖该项的开关状态。默认值false -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 是否允许单一语句返回多结果集(需要兼容驱动)。 默认值true -->
<setting name="multipleResultSetsEnabled" value="true"/>
<!--
使用列标签代替列名。不同的驱动在这方面会有不同的表现, 具体可参考相关驱动文档
或通过测试这两种不同的模式来观察所用驱动的结果。默认值true
-->
<setting name="useColumnLabel" value="true"/>
<!--
允许JDBC 支持自动生成主键,需要驱动兼容。 如果设置为 true 则这个设置强制使用
自动生成主键,尽管一些驱动不能兼容但仍可正常工作(比如 Derby)。 默认值false
-->
<setting name="useGeneratedKeys" value="false"/>
<!--
指定 MyBatis 应如何自动映射列到字段或属性。 NONE 表示取消自动映射;PARTIAL
只会自动映射没有定义嵌套结果集映射的结果集。 FULL 会自动映射任意复杂的结果集
(无论是否嵌套)。
-->
<!-- 默认值PARTIAL -->
<setting name="autoMappingBehavior" value="PARTIAL"/>
<setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
<!-- 配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句
(prepared statements); BATCH 执行器将重用语句并执行批量更新。默认SIMPLE
-->
<setting name="defaultExecutorType" value="SIMPLE"/>
<!-- 设置超时时间,它决定驱动等待数据库响应的秒数。 -->
<setting name="defaultStatementTimeout" value="25"/>
<setting name="defaultFetchSize" value="100"/>
<!-- 允许在嵌套语句中使用分页(RowBounds)默认值False -->
<setting name="safeRowBoundsEnabled" value="false"/>
<!--
是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典
Java 属性名 aColumn 的类似映射。 默认false
-->
<setting name="mapUnderscoreToCamelCase" value="false"/>
<!--
MyBatis 利用本地缓存机制(Local Cache)防止循环引用(circular references)
和加速重复嵌套查询。
默认值为 SESSION,这种情况下会缓存一个会话中执行的所有查询。
若设置值为 STATEMENT,本地会话仅用在语句执行上,对相同 SqlSession 的不同调用将不会
共享数据。
-->
<setting name="localCacheScope" value="SESSION"/>
<!--
当没有为参数提供特定的 JDBC 类型时,为空值指定 JDBC 类型。 某些驱动需要指定列的
JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。
-->
<setting name="jdbcTypeForNull" value="OTHER"/>
<!--指定哪个对象的方法触发一次延迟加载。-->
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>
mybatis主配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!--
约束文件的说明
mybatis-3-config.dtd:约束文件的名称
-->
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--
mybatis的主配置文件:主要定义了数据库的配置信息。sql映射的位置。
configuration 根标签
-->
<configuration>
<!--
环境配置:数据库的连接信息
default 必须和某个environment的id一样
告诉mybatis使用哪个数据库的链接信息,也就是访问哪个数据库
-->
<environments default="mydev">
<!---->
<!--environment 一个数据库信息的配置,环境
id:一个唯一值,自定义,表示环境名称。
-->
<environment id="mydev">
<!--
transactionManager :mybatis的事务类型
type:
1、JDBC(表示使用jdbc中的connection对象commit,rollback做事务处理)
2、MANAGED:把mybatis的事务处理委托给其他容器(一个服务器软件、一个框架(spring))
-->
<transactionManager type="JDBC"/>
<!--
dataSource:表示数据源 连接数据库的
type:表示数据源的类型,POOLED表示使用连接池
在java体系中,规定实现了javax.sql.DataSource接口的都是数据源
数据源就是表示链接Connection对象的。
type:指定的数据源类型
1)POOLED:使用链接池,mybatis会创建PooledDataSource类对象
2)UnpooledDataSource:不使用连接池,在每一次执行sql语句,先创建链接,执行sql,再关闭 链接。mybatis会创建一个UnpooledDataSource,管理connection对象的使用
3)JNDI:java命名和目录服务(Windows注册表)
-->
<dataSource type="POOLED">
<!--driver,url,username,password是固定的,不能自定义-->
<!--数据库的驱动-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<!--连接数据库的url字符串-->
<property name="url" value="jdbc:mysql://localhost:3306/test?useSSL=false"/>
<!--访问数据库的用户名-->
<property name="username" value="root"/>
<!--访问数据库的密码-->
<property name="password" value="hanxu"/>
</dataSource>
</environment>
</environments>
<!--sql mapper(sql映射文件)的位置-->
<mappers>
<!--一个mapper标签指定一个文件的位置
从类路径开始的路径信息 target\classes(类路径)
-->
<!-- <mapper resource="org/mybatis/example/BlogMapper.xml"/>-->
<mapper resource="org/hanxu/dao/StudentDao.xml"/>
</mappers>
</configuration>
数据库的属性配置文件
把数据库连接信息放到一个单独的文件中。 和mybatis主配置文件分开。目的是便于修改,保存,处理多个数据库的信息。
- 在resources目录中定义一个属性配置文件, xxxx.properties ,例如 jdbc.properties
- 在属性配置文件中, 定义数据,格式是 key=value
- key: 一般使用 . 做多级目录的。
例如
jdbc.mysql.driver或jdbc.driver, mydriver
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql//.....
jdbc.username=root
jdbc.password=123456
- 在mybatis的主配置文件,使用<property> 指定文件的位置
- 在需要使用值的地方, $
在resources目录下定义jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test?useSSL=false
jdbc.username=root
jdbc.password=hanxu
mybatis的主配置文件,使用<property> 指定文件的位置
<?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"/>
<settings>
<!--设置mybatis输出日志-->
<setting name="logImpl" value="STDOUT_LOGGING" />
</settings>
<!--定义别名-->
<typeAliases>
<!--
可以指定一个类型一个自定义别名
type:自定义类型的全限定名称
alias:别名(短小,容易记忆的)
-->
<typeAlias type="org.hanxu.domain.ViewStudent" alias="view"/>
<package name="org.hanxu.domain"/>
</typeAliases>
<environments default="mydev">
<environment id="mydev">
<transactionManager type="JDBC"/>
<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>
</environment>
</environments>
<mappers>
<mapper resource="org/hanxu/dao/StudentDao.xml"/>
</mappers>
</configuration>
mapper文件映射
第一种方式: 指定多个mapper文件
<mappers>
<mapper resource="org/hanxu/dao/StudentDao.xml"/>
<mapper resource="org/hanxu/dao/OrderDao.xml"/>
</mappers>
第二种方式: 使用包名
<mappers>
<!--
name: xml文件(mapper文件)所在的包名, 这个包中所有xml文件一次都能加载给mybatis
使用package的要求:
1. mapper文件名称需要和接口名称一样, 区分大小写的一样
2. mapper文件和dao接口需要在同一目录
-->
<package name="com.bjpowernode.dao"/>
</mappers>
九、扩展PageHelper
https://github.com/pagehelper/Mybatis-PageHelper
PageHelper支持多种数据库:
1.Oracle
2.Mysql
3.MariaDB
4.SQLite
5.Hsqldb
6.PostgreSQL
7.DB2
8.SqlServer(2005,2008)
9.Informix
10.H2
11.SqlServer2012
12.Derby
13.Phoenix
maven坐标
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.10</version>
</dependency>
加入plugin配置
在主配置文件中<environments>之前加入
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor"/>
</plugins>
测试代码
@Test
public void selectAllTest(){
SqlSession sqlSession = MyBatisUtil.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
PageHelper.startPage(2,3);
/**加入PageHelper的方法,分页
* pageNum:第几页数据,从1开始
* pageSize:一页中有多少数据
*/
List<Student> students = dao.selectAll();
for (Student stu :
students) {
System.out.println(stu);
}
sqlSession.close();
}
踩坑idea2020.1版本
maven仓库中使用默认仓库,idea手动指定仓库位置。否则找不到包!

浙公网安备 33010602011771号