第一章 框架概述
1.1 三层架构
界面层: 和用户打交道的, 接收用户的请求参数, 显示处理结果的。(jsp ,html ,servlet)
业务逻辑层: 接收了界面层传递的数据,计算逻辑,调用数据库,获取数据
数据访问层: 就是访问数据库, 执行对数据的查询,修改,删除等等的。
- 三层对应的包
- 界面层: controller包 (servlet)
- 业务逻辑层: service 包(XXXService类)
- 数据访问层: dao包(XXXDao类)
- 三层中类的交互
- 用户使用界面层–> 业务逻辑层—>数据访问层(持久层)–>数据库(mysql)
- 三层对应的处理框架
-
界面层—servlet—springmvc(框架)
-
业务逻辑层—service类–spring(框架)
-
数据访问层—dao类–mybatis(框架)
1.2 框架
框架是一个舞台, 一个模版
1.2.1 模版
- 规定了好一些条款,内容。
- 加入自己的东西
1.2.2 框架是一个模块
1.框架中定义好了一些功能。这些功能是可用的。
2.可以加入项目中自己的功能, 这些功能可以利用框架中写好的功能。
框架是一个软件,半成品的软件,定义好了一些基础功能, 需要加入你的功能就是完整的。
基础功能是可重复使用的,可升级的。
1.2.3 框架特点
- 框架一般不是全能的, 不能做所有事情
- 框架是针对某一个领域有效。 特长在某一个方面,比如mybatis做数据库操作强,但是他不能做其它的。
- 框架是一个软件
1.2.4 mybatis框架
mybatis框架,早期叫做ibatis, 代码在github。
mybatis是 MyBatis SQL Mapper Framework for Java (sql映射框架)
1)sql mapper :sql映射
可以把数据库表中的一行数据 映射为 一个java对象。
一行数据可以看做是一个java对象。操作这个对象,就相当于操作表中的数据
2) Data Access Objects(DAOs) : 数据访问 , 对数据库执行增删改查。
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对象(表中的数据)
1.3 JDBC 的缺陷
- 代码比较多,开发效率低
- 需要关注 Connection ,Statement, ResultSet 对象创建和销毁
- 对 ResultSet 查询的结果,需要自己封装为 List
- 重复的代码比较多些
- 业务代码和数据库的操作混在一起
1.4 总结
mybatis是一个sql映射框架,提供的数据库的操作能力。增强的JDBC,使用mybatis让开发人员集中精神写sql就可以了,不必关心Connection,Statement,ResultSet的创建,销毁,sql的执行。
第二章 快速入门
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gxdUVvTt-1648717794817)(C:\Users\Dell\AppData\Roaming\Typora\typora-user-images\image-20220329210206197.png)]
2.1 实现步骤
2.1.1 创建student数据库表
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g8CVNx60-1648717794819)(C:\Users\Dell\AppData\Roaming\Typora\typora-user-images\image-20220329210359947.png)]
2.1.2加入maven的坐标和插件
<?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>com.bjpowernode</groupId>
<artifactId>ch01-hello-mybatis</artifactId>
<version>1.0-SNAPSHOT</version>
<!--<packaging>jar</packaging>-->
<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>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!--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>
</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>
</project>
2.1.3创建实体类
package com.bjpowernode.domain;
//推荐和表名一样。容易记忆
public class Student {
//定义属性, 目前要求是属性名和列名一样。
private Integer id;
private String name;
private String email;
private Integer age;
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 +
'}';
}
}
2.1.4创建持久层dao接口
package com.bjpowernode.dao;
import com.bjpowernode.domain.Student;
import java.util.List;
//接口操作student表
public interface StudentDao {
//查询student表的所有的数据
public List<Student> selectStudents();
//插入方法
//参数: student ,表示要插入到数据库的数据
//返回值: int , 表示执行insert操作后的 影响数据库的行数
public int insertStudent(Student student);
}
2.1.5创建mybatis的配置文件
叫做sql映射文件:写sql语句的。一般一个表一个sql映射文件
<?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="com.bjpowernode.dao.StudentDao">
<!--
select:表示查询操作。
id: 你要执行的sql语法的唯一标识, mybatis会使用这个id的值来找到要执行的sql语句
可以自定义,但是要求你使用接口中的方法名称。
resultType:表示结果类型的, 是sql语句执行后得到ResultSet,遍历这个ResultSet得到java对象的类型。
值写的类型的全限定名称
-->
<select id="selectStudents" resultType="com.bjpowernode.domain.Student" >
select id,name,email,age from student order by id
</select>
<!--插入操作-->
<insert id="insertStudent">
insert into student values(#{id},#{name},#{email},#{age})
</insert>
</mapper>
<!--
sql映射文件(sql mapper): 写sql语句的, mybatis会执行这些sql
1.指定约束文件
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
mybatis-3-mapper.dtd是约束文件的名称, 扩展名是dtd的。
2.约束文件作用: 限制,检查在当前文件中出现的标签,属性必须符合mybatis的要求。
3.mapper 是当前文件的根标签,必须的。
namespace:叫做命名空间,唯一值的, 可以是自定义的字符串。
要求你使用dao接口的全限定名称。
4.在当前文件中,可以使用特定的标签,表示数据库的特定操作。
<select>:表示执行查询,select语句
<update>:表示更新数据库的操作, 就是在<update>标签中 写的是update sql语句
<insert>:表示插入, 放的是insert语句
<delete>:表示删除, 执行的delete语句
-->
2.1.6创建mybatis的主配置文件
一个项目就一个主配置文件。主配置文件提供了数据库的连接信息和sql映射文件的位置信息。
<?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:控制mybatis全局行为-->
<settings>
<!--设置mybatis输出日志-->
<setting name="logImpl" value="STDOUT_LOGGING" />
</settings>
<!--环境配置: 数据库的连接信息
default:必须和某个environment的id值一样。
告诉mybatis使用哪个数据库的连接信息。也就是访问哪个数据库
-->
<environments default="mydev">
<!-- environment : 一个数据库信息的配置, 环境
id:一个唯一值,自定义,表示环境的名称。
-->
<environment id="mydev">
<!--
transactionManager :mybatis的事务类型
type: JDBC(表示使用jdbc中的Connection对象的commit,rollback做事务处理)
-->
<transactionManager type="JDBC"/>
<!--
dataSource:表示数据源,连接数据库的
type:表示数据源的类型, POOLED表示使用连接池
-->
<dataSource type="POOLED">
<!--
driver, user, username, password 是固定的,不能自定义。
-->
<!--数据库的驱动类名-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<!--连接数据库的url字符串-->
<property name="url" value="jdbc:mysql://localhost:3306/springdb"/>
<!--访问数据库的用户名-->
<property name="username" value="root"/>
<!--密码-->
<property name="password" value="123456"/>
</dataSource>
</environment>
<!--表示线上的数据库,是项目真实使用的库-->
<environment id="online">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/onlinedb"/>
<property name="username" value="root"/>
<property name="password" value="fhwertwr"/>
</dataSource>
</environment>
</environments>
<!-- sql mapper(sql映射文件)的位置-->
<mappers>
<!--一个mapper标签指定一个文件的位置。
从类路径开始的路径信息。 target/clasess(类路径)
-->
<mapper resource="com/bjpowernode/dao/StudentDao.xml"/>
<!--<mapper resource="com/bjpowernode/dao/SchoolDao.xml" />-->
</mappers>
</configuration>
<!--
mybatis的主配置文件: 主要定义了数据库的配置信息, sql映射文件的位置
1. 约束文件
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
mybatis-3-config.dtd:约束文件的名称
2. configuration 根标签。
-->
2.1.7创建测试类
package com.bjpowernode;
import com.bjpowernode.domain.Student;
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;
import java.util.List;
public class MyApp {
public static void main(String[] args) throws IOException {
//访问mybatis读取student数据
//1.定义mybatis主配置文件的名称, 从类路径的根开始(target/clasess)
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 = "com.bjpowernode.dao.StudentDao" + "." + "selectStudents";
String sqlId = "com.bjpowernode.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();
}
}
2.1.8配置日志功能
mybatis.xml 文件加入日志配置,可以在控制台输出执行的 sql 语句和参数
<!--settings:控制mybatis全局行为-->
<settings>
<!--设置mybatis输出日志-->
<setting name="logImpl" value="STDOUT_LOGGING" />
</settings>
效果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qth5Fgrk-1648717794821)(C:\Users\Dell\AppData\Roaming\Typora\typora-user-images\image-20220329211740321.png)]
2.2 主要类的介绍
2.2.1Resources:
mybatis中的一个类, 负责读取主配置文件
InputStream in = Resources.getResourceAsStream(“mybatis.xml”);
2.2.2SqlSessionFactoryBuilder :
创建SqlSessionFactory对象,
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//创建SqlSessionFactory对象
SqlSessionFactory factory = builder.build(in);
2.2.3SqlSessionFactory :
重量级对象, 程序创建一个对象耗时比较长,使用资源比较多。在整个项目中,有一个就够用了。
SqlSessionFactory:接口 , 接口实现类: DefaultSqlSessionFactory
SqlSessionFactory作用: 获取SqlSession对象。SqlSession sqlSession = factory.openSession();
openSession()方法说明:
1. openSession() :无参数的, 获取是非自动提交事务的SqlSession对象
- openSession(boolean): openSession(true) 获取自动提交事务的SqlSession.
openSession(false) 非自动提交事务的SqlSession对象
2.2.4SqlSession:
SqlSession接口 :定义了操作数据的方法 例如 selectOne() ,selectList() ,insert(),update(), delete(), commit(), rollback()
SqlSession接口的实现类DefaultSqlSession。
使用要求: SqlSession对象不是线程安全的,需要在方法内部使用, 在执行sql语句之前,使用openSession()获取SqlSession对象。
在执行完sql语句后,需要关闭它,执行SqlSession.close(). 这样能保证他的使用是线程安全的。
这里有一个问题,我们从始至终都没有用到Dao接口类,我们现在来用传统的Dao实现类来使用Dao接口
2.3mybatis使用传统dao开发方式
2.3.1创建持久层dao接口
package com.bjpowernode.dao;
import com.bjpowernode.domain.Student;
import java.util.List;
public interface StudentDao {
List<Student> selectStudents();
int insertStudent(Student student);
}
2.3.2创建dao接口实现类
package com.bjpowernode.dao.impl;
import com.bjpowernode.dao.StudentDao;
import com.bjpowernode.domain.Student;
import com.bjpowernode.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import java.util.List;
public class StudentDaoImpl implements StudentDao {
@Override
public List<Student> selectStudents() {
//获取SqlSession对象
SqlSession sqlSession = MyBatisUtils.getSqlSession();
String sqlId="com.bjpowernode.dao.StudentDao.selectStudents";
//执行sql语句, 使用SqlSession类的方法
List<Student> students = sqlSession.selectList(sqlId);
//关闭
sqlSession.close();
return students;
}
@Override
public int insertStudent(Student student) {
//获取SqlSession对象
SqlSession sqlSession = MyBatisUtils.getSqlSession();
String sqlId="com.bjpowernode.dao.StudentDao.insertStudent";
//执行sql语句, 使用SqlSession类的方法
int nums = sqlSession.insert(sqlId,student);
//提交事务
sqlSession.commit();
//关闭
sqlSession.close();
return nums;
}
}
2.3.3测试类
package com.bjpowernode;
import com.bjpowernode.dao.StudentDao;
import com.bjpowernode.dao.impl.StudentDaoImpl;
import com.bjpowernode.domain.Student;
import org.junit.Test;
import java.util.List;
public class TestMyBatis {
@Test
public void testSelectStudents(){
//com.bjpowernode.dao.StudentDao
StudentDao dao = new StudentDaoImpl();
/** 实现原理:
* List<Student> studentList = dao.selectStudents(); 调用
* 1.dao对象,类型是StudentDao,全限定名称是:com.bjpowernode.dao.StudentDao
* 全限定名称 和 namespace 是一样的。
*
* 2.方法名称, selectStudents, 这个方法就是 mapper文件中的 id值 selectStudents
*
* 3.通过dao中方法的返回值也可以确定MyBatis要调用的SqlSession的方法
* 如果返回值是List ,调用的是SqlSession.selectList()方法。
* 如果返回值 int ,或是非List的, 看mapper文件中的 标签是<insert>,<update> 就会调用
* SqlSession的insert, update等方法
*
* mybatis的动态代理: mybatis根据 dao的方法调用,获取执行sql语句的信息。
* mybatis根据你的dao接口,创建出一个dao接口的实现类, 并创建这个类的对象。
* 完成SqlSession调用方法, 访问数据库。
*
*/
List<Student> studentList = dao.selectStudents();
for(Student stu:studentList){
System.out.println(stu);
}
}
@Test
public void testInsertStudent(){
StudentDao dao = new StudentDaoImpl();
Student student = new Student();
student.setId(1005);
student.setName("盾山");
student.setEmail("dunshan@qq.com");
int nums = dao.insertStudent(student);
System.out.println("添加对象的数量:"+nums);
}
}
2.2.4工具类
package com.bjpowernode.utils;
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对象,使用SqlSessionFactoryBuild
factory = new SqlSessionFactoryBuilder().build(in);
} catch (IOException e) {
e.printStackTrace();
}
}
//获取SqlSession的方法
public static SqlSession getSqlSession() {
SqlSession sqlSession = null;
if( factory != null){
sqlSession = factory.openSession();// 非自动提交事务
}
return sqlSession;
}
}
2.4 传统 Dao 开发方式的分析
在前面例子中自定义 Dao 接口实现类时发现一个问题:Dao 的实现类其实并没有干什么实质性的工 作,它仅仅就是通过 SqlSession 的相关 API 定位到映射文件 mapper 中相应 id 的 SQL 语句,真正对 DB 进 行操作的工作其实是由框架通过 mapper 中的 SQL 完成的。
所以,MyBatis 框架就抛开了 Dao 的实现类,直接定位到映射文件 mapper 中的相应 SQL 语句,对 DB 进行操作。这种对 Dao 的实现方式称为 Mapper 的动态代理方式。
Mapper 动态代理方式无需程序员实现 Dao 接口。接口是由 MyBatis 结合映射文件自动生成的动态代 理实现的。
第三章 Mybatis框架Dao代理
3.1 实现方式
3.1.1去掉Dao接口实现类
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FKiHu7id-1648717794822)(C:\Users\Dell\AppData\Roaming\Typora\typora-user-images\image-20220329214821252.png)]
由于用到了动态代理,所以,我们不需要创建Dao的接口实现类,直接交给代理来生成Dao的接口实现类。
动态代理: 使用SqlSession.getMapper(dao接口.class) 获取这个dao接口的对象
3.1.2 getMapper获取代理对象
package com.bjpowernode;
import com.bjpowernode.dao.StudentDao;
import com.bjpowernode.domain.Student;
import com.bjpowernode.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.junit.Test;
import java.util.List;
public class TestMyBatis {
@Test
public void testSelectStudents(){
/**
* 使用mybatis的动态代理机制, 使用SqlSession.getMapper(dao接口)
* getMapper能获取dao接口对于的实现类对象。
*/
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
//com.sun.proxy.$Proxy2 : jdk的动态代理
System.out.println("dao="+dao.getClass().getName());
//调用dao的方法, 执行数据库的操作
List<Student> students = dao.selectStudents();
for(Student stu: students){
System.out.println("学生="+stu);
}
}
@Test
public void testInsertStudent(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
Student student = new Student();
student.setId(1007);
student.setName("李飞");
student.setEmail("dunshan@qq.com");
student.setAge(28);
int nums = dao.insertStudent(student);
sqlSession.commit();
System.out.println("添加对象的数量:"+nums);
}
}
3.2 深入理解参数
3.2.1 parameterType
parameterType : dao接口中方法参数的数据类型。parameterType它的值是java的数据类型全限定名称或者是mybatis定义的别名
例如:parameterType=“java.lang.Integer”
parameterType=“int”
int 或 java.lang.Integer
hashmap 或 java.util.HashMap
list 或 java.util.ArrayList
student 或 com.bjpowernode.domain.Student
注意:默认值为未设置(unset)。接口中方法的参数从 java 代码传入到 mapper 文件的 sql 语句。
parameterType不是强制的,mybatis通过反射机制能够发 现接口参数的数类型。 所以可以没有。 一般我们也不写。
当传递的参数只有一个的时候:多个则不能使用这个属性
<select id="selectStudentById" parameterType="int" resultType="com.bjpowernode.domain.Student">
select id,name, email,age from student where id=${studentId}
</select>
3.2.2 MyBatis 传递参数
1.一个简单参数
Dao 接口中方法的参数只有一个简单类型(java 基本类型和 String),占位符 #{ 任意字符 },和方法的参数名无关。与传入的对象无关,与传入的值有关。
单个参数传递给sql语句时不需要用命名参数,否则就需要使用命名参数。
接口:
/**
* 一个简单类型的参数:
* 简单类型: mybatis把java的基本数据类型和String都叫简单类型。
* 在mapper文件获取简单类型的一个参数的值,使用 #{任意字符}
*/
public Student selectStudentById(@Param("studentId") Integer id);
mapper:
<select id="selectStudentById" resultType="com.bjpowernode.domain.Student">
select id,name, email,age from student where id=#{studentId}
</select>
#{studentId} , studentId 是自定义的变量名称,和方法参数名无关。
2.多个参数-使用@Param
当 Dao 接口方法多个参数,需要通过名称使用参数。在方法形参前面加入@Param(“自定义参数名”), mapper 文件使用#{自定义参数名}。
接口:
/**
* 多个参数: 命名参数,在形参定义的前面加入 @Param("自定义参数名称")
*/
List<Student> selectMultiParam(@Param("myname") String name,
@Param("myage") Integer age);
mapper:
<!--多个参数,使用@Param命名-->
<select id="selectMultiParam" resultType="com.bjpowernode.domain.Student">
select id,name, email,age from student where name=#{myname} or age=#{myage}
</select>
3.多个参数-使用对象
-
vo: value object , 放一些存储数据的类。比如说 提交请求参数, name ,age 现在想把name ,age 传给一个service 类。
-
vo: view object , 从servlet把数据返回给浏览器使用的类,表示显示结果的类。
-
pojo: 普通的有set, get方法的java类。 普通的java对象
Servlet --- StudentService( addStudent( MyParam param) )
-
entity(domain域): 实体类, 和数据库中的表对应的类,
多个参数, 使用java对象的属性值,作为参数实际值
使用对象语法: #{属性名,javaType=类型名称,jdbcType=数据类型} 很少用。
javaType:指java中的属性数据类型。
jdbcType:在数据库中的数据类型。
例如: #{paramName,javaType=java.lang.String,jdbcType=VARCHAR}
我们使用常用的的简化方式:#{属性名} ,javaType, jdbcType的值mybatis反射能获取。不用提供。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KbqZTtdA-1648717794825)(C:\Users\Dell\AppData\Roaming\Typora\typora-user-images\image-20220329225921187.png)]
接口:
/**
* 多个参数,使用java对象作为接口中方法的参数
*/
List<Student> selectMultiObject(QueryParam param);
mapper:
<select id="selectMultiObject" resultType="com.bjpowernode.domain.Student">
select id,name, email,age from student where
name=#{paramName,javaType=java.lang.String,jdbcType=VARCHAR}
or age=#{paramAge,javaType=java.lang.Integer,jdbcType=INTEGER}
</select>
<!-- =================以下是常用的格式================= -->
<select id="selectMultiObject" resultType="com.bjpowernode.domain.Student">
select id,name, email,age from student where
name=#{paramName} or age=#{paramAge}
</select>
4.多个参数-按位置
参数位置从 0 开始, 引用参数语法 #{ arg 位置 } , 第一个参数是#{arg0}, 第二个是#{arg1}
接口:
/**
* 多个参数-简单类型的,按位置传值,
* mybatis.3.4之前,使用 #{0} ,#{1}
* mybatis。3.4之后 ,使用 #{arg0} ,#{arg1}
*/
List<Student> selectMultiPosition( String name,Integer age);
mapper:
<!--多个参数使用位置-->
<select id="selectMultiPosition" resultType="com.bjpowernode.domain.Student">
select id,name, email,age from student where
name = #{arg0} or age=#{arg1}
</select>
5.多个参数-使用Map
Map 集合可以存储多个值,使用Map向 mapper 文件一次传入多个参数。Map 集合使用 String的 key, Object 类型的值存储参数。 mapper 文件使用 # { key } 引用参数值。
接口:
/**
* 多个参数,使用Map存放多个值
*/
List<Student> selectMultiByMap(Map<String,Object> map);
mapper:
<!--多个参数,使用Map , 使用语法 #{map的key}-->
<select id="selectMultiByMap" resultType="com.bjpowernode.domain.Student">
select id,name, email,age from student where
name = #{myname} or age=#{age1}
</select>
6.#和$
#:占位符,告诉 mybatis 使用实际的参数值代替。并使用 PrepareStatement 对象执行 sql 语句, #{…}代替 sql 语句的“?”。这样做更安全可以防止sql注入,更迅速,通常也是首选做法。
$ 字符串替换,告诉 mybatis 使用 包 含 的 “ 字 符 串 ” 替 换 所 在 位 置 。 使 用 S t a t e m e n t 把 s q l 语 句 和 包含的“字符串”替换所在位置。使用 Statement 把 sql 语句和 包含的“字符串”替换所在位置。使用Statement把sql语句和{}的 内容连接起来。主要用在:替换表名,列名,不同列排序等操作。可以替换表名或者列名, 你能确定数据是安全的。
<!--使用 ${}-->
<select id="selectUse$" resultType="com.bjpowernode.domain.Student">
select * from student where name=${myname}
</select>
<!--使用 #{}-->
<select id="selectUse" resultType="com.bjpowernode.domain.Student">
select * from student where name=#{myname}
</select>
在日志中看到select语句是有?占位符出现的,这就说明,mybatis底层是调用执行对象preparedStatement对象。
实际上一个#{}就是对应着在底层的JDBC中的一个?号占位符
转为 MyBatis 的执行是: String sql=” select id,name,email,age from student where id=?”;
PreparedStatement ps = conn.prepareStatement(sql);
ps.setInt(1,1005);
select id,name, email,age from student where id=#{studentId}
# 的结果: select id,name, email,age from student where id=?
// String sql="select id,name, email,age from student where id=" + "1001";
// 使用的Statement对象执行sql, 效率比PreparedStatement低。
select id,name, email,age from student where id=${studentId}
$ 的结果:select id,name, email,age from student where id=1001
#和 $区别
1. #使用 ?在sql语句中做站位的, 使用PreparedStatement执行sql,效率高
2. #能够避免sql注入,更安全。
3. $不使用占位符,是字符串连接方式,使用Statement对象执行sql,效率低
4. $有sql注入的风险,缺乏安全性。
5. $:可以替换表名或者列名
3.2.3 别名的定义
定义自定义类型的别名
- 在mybatis主配置文件中定义,使定义别名
- 可以在resultType中使用自定义别名
定义在mybatis主配置文件当中:
<!--定义别名-->
<typeAliases>
<!--
第一种方式:
可以指定一个类型一个自定义别名
type:自定义类型的全限定名称
alias:别名(短小,容易记忆的)
-->
<typeAlias type="com.bjpowernode.domain.Student" alias="stu" />
<typeAlias type="com.bjpowernode.vo.ViewStudent" alias="vstu" />
</typeAliases>
<typeAliases>
<!--
第二种方式
<package> name是包名, 这个包中的所有类,类名就是别名(类名不区分大小写)
-->
<package name="com.bjpowernode.domain"/>
<package name="com.bjpowernode.vo"/>
</typeAliases>
3.3 封装Mybatis的输出结果
3.3.1 resultType
resultType结果类型, 指sql语句执行完毕后, 数据转为的java对象, java类型是任意的。resultType结果类型的它值 1. 类型的全限定名称 2. 类型的别名。
例如 java.lang.Integer别名是int。
处理方式:
1. mybatis执行sql语句, 然后mybatis调用类的无参数构造方法,创建对象。
2. mybatis把ResultSet指定列值付给同名的属性。
<select id="selectMultiPosition" resultType="com.bjpowernode.domain.Student">
select id,name, email,age from student
</select>
对等的jdbc
ResultSet rs = 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"))
}
resultType: 执行 sql 得到 ResultSet 转换的类型,使用类型的完全限定名或别名。 注意如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身。resultType 和 resultMap,不能同时使用。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EwkfdDys-1648717794827)(C:\Users\Dell\AppData\Roaming\Typora\typora-user-images\image-20220330213158335.png)]
可以把resultType里面的值,可以看做是接口中方法的返回值
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-88vXlepi-1648717794828)(C:\Users\Dell\AppData\Roaming\Typora\typora-user-images\image-20220330155940294.png)]
1.简单类型
接口:int countStudent();
mapper:
<!--sql执行后返回一行一列-->
<!--<select id="countStudent" resultType="int">-->
<select id="countStudent" resultType="java.lang.Integer">
select count(*) from student
</select>
2.对象类型
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fHoXwUL8-1648717794829)(C:\Users\Dell\AppData\Roaming\Typora\typora-user-images\image-20220330160233384.png)]
接口:
ViewStudent selectViewStudent(int id);
mapper:
<!-- 返回的参数是对象类型-->
<select id="selectViewStudent" resultType="com.gz.vo.ViewStudent" >
select id,name,email,age from student where id=#{id}
</select>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LzHw6uNx-1648717794830)(C:\Users\Dell\AppData\Roaming\Typora\typora-user-images\image-20220330214240452.png)]
3.Map
sql 的查询结果作为 Map 的 key 和 value。推荐使用 Map。 注意:Map 作为接口返回值,sql 语句的查询结果最多只能有一条记录。大于一条记录是错误。
//定义方法返回Map
Map<Object,Object> selectMapById(Integer id);
<!--返回Map
1)列名是map的key, 列值是map的value
2)只能最多返回一行记录。多余一行是错误
-->
<select id="selectMapById" resultType="java.util.HashMap">
select id,name,email from student where id=#{stuid}
</select>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0j3PqWPK-1648717794832)(C:\Users\Dell\AppData\Roaming\Typora\typora-user-images\image-20220330214507029.png)]
3.3.2 resultMap
resultMap:结果映射, 指定列名和java对象的属性对应关系。
1)你自定义列值赋值给哪个属性
2)当你的列名和属性名不一样时,一定使用resultMap resultMap和resultType不要一起用,二选一
resultMap 可以自定义 sql 的结果和 java 对象属性的映射关系。更灵活的把列值赋值给指定属性。 常用在列名和 java 对象属性名不一样的情况。
使用方式: 1.先定义 resultMap,指定列名和属性的对应关系。
2.在中把 resultType 替换为 resultMap。
接口:
/*
* 使用resultMap定义映射关系
* */
List<Student> selectAllStudents();
mapper:
<!--使用resultMap
1)先定义resultMap
2)在select标签,使用resultMap来引用1定义的。
-->
<!--定义resultMap
id:自定义名称,表示你定义的这个resultMap在<select>使用
type:期望转为的 java 对象的全限定名称或别名
-->
<resultMap id="studentMap" type="com.bjpowernode.domain.Student">
<!--列名和java属性的关系-->
<!--注解列,使用id标签
column :列名
property:java类型的属性名
-->
<id column="id" property="id" />
<!--非主键列,使用result-->
<result column="name" property="name" />
<result column="email" property="email" />
<result column="age" property="age" />
</resultMap>
<select id="selectAllStudents" resultMap="studentMap">
select id,name, email , age from student
</select>
当数据库列名和 java 对象属性名不一样的情况下:
<resultMap id="myStudentMap" type="com.bjpowernode.domain.MyStudent">
<!--列名和java属性的关系-->
<id column="id" property="stuid" />
<!--非主键列,使用result-->
<result column="name" property="stuname" />
<result column="email" property="stuemail" />
<result column="age" property="stuage" />
</resultMap>
<!--列名和属性名不一样:第一种方式-->
<select id="selectMyStudent" resultMap="myStudentMap">
select id,name, email , age from student
</select>
3.3.3 实体类属性名和列名不同的处理方式
步骤:
创建新的实体类 PrimaryStuden
package com.gz.entity;
public class PrimaryStudent {
private Integer stuid;
private String stuname;
public PrimaryStudent() {
}
@Override
public String toString() {
return "PrimaryStudent{" +
"stuid=" + stuid +
", stuname='" + stuname + '\'' +
'}';
}
public Integer getStuid() {
return stuid;
}
public void setStuid(Integer stuid) {
this.stuid = stuid;
}
public String getStuname() {
return stuname;
}
public void setStuname(String stuname) {
this.stuname = stuname;
}
}
1.使用列别名和resultType
接口方法
List<MyStudent> selectMyStudent();
mapper
<!-- 第一种:当列名和java对象属性名不一样,使用resultMap-->
<resultMap id="studentMap" type="Student">
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="email" property="email"/>
<result column="age" property="age"/>
</resultMap>
<select id="studentResultMap" resultMap="studentMap">
select id,name,email,age from student where id = #{id}
</select>
2.使用resultMap
<!-- 第二种:当列名和java对象属性名不一样,使用数据库别名-->
<select id="studentResultType" resultType="com.gz.entity.PrimaryStudent">
select id as stuid,name as stuname,email,age from student where id = #{id}
</select>
<resultMap id="studentMap1" type="com.gz.entity.PrimaryStudent">
<id column="id" property="stuid"/>
<result column="name" property="stuname"/>
</resultMap>
3.使用数据库别名的方式
<!-- 第三种:
1.当列名和java对象属性名不一样,使用数据库别名和实体类的属性名相同
2.resultType的默认原则是 同名的列值赋值给同名的属性, 使用列别名(java对象的属性名)-->
<select id="studentResultType" resultType="com.gz.entity.PrimaryStudent">
select id as stuid,name as stuname,email,age from student where id = #{id}
</select>
3.4 模糊like
模糊查询的实现有两种方式:一是 java 代码中给查询数据加上“%” ;
二是在 mapper 文件 sql 语句的条件位置加上“%”。
1.java 代码中提供要查询的 “%xxx%”
mapper
<!--第一种 like , java代码指定 like的内容-->
<select id="selectLikeOne" resultType="com.bjpowernode.domain.Student">
select id,name,email,age from student where name like #{name}
</select>
测试类
@Test
public void testSelectLikeOne(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
//准备好like的内容
String name = "%李%";
List<Student> students = dao.selectLikeOne(name);
for(Student stu: students){
System.out.println("#######学生="+stu);
}
sqlSession.close();
}
2.mapper 文件中使用 “%” #{xxx} “%”
mapper
<!--第二种方式:在mapper文件中拼接 like的内容-->
<select id="selectLikeTwo" resultType="com.bjpowernode.domain.Student">
select id,name,email,age from student where name like "%" #{name} "%"
</select>
测试类
@Test
public void testSelectLikeTwo(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
//准备好like的内容
String name = "张";
List<Student> students = dao.selectLikeTwo(name);
for(Student stu: students){
System.out.println("*******学生="+stu);
}
sqlSession.close();
}
第四章 动态SQL
动态SQL: SQL的内容是变化的,可以根据条件获取到不同的sql语句。
主要是where部分发生变化。
动态 SQL,主要用于解决查询条件不确定的情况:在程序运行期间,根据用户提交的查询条件进行 查询。提交的查询条件不同,执行的 SQL 语句不同。若将每种可能的情况均逐一列出,对所有条件进行 排列组合,将会出现大量的 SQL 语句。此时,可使用动态 SQL 来解决这样的问题。
4.1 注意事项
- 在 mapper 的动态 SQL 中若出现大于号(>)、小于号(<)、大于等于号(>=),小于等于号(<=)等 符号,最好将其转换为实体符号。否则,XML 可能会出现解析出错问题。
- 在使用动态SQL的使用,接口接收的参数一定要使用对象的方式。
特别是对于小于号(<),在 XML 中是绝不能出现的。否则解析 mapper 文件会出错。所以我们要使用实体符号:
< | 小于 | & lt; |
---|---|---|
> | 大于 | & gt; |
>= | 大于等于 | & gt;= |
<= | 小于等于 | & lt;= |
4.2动态SQL之< if >
对于该标签的执行,当 test 的值为 true 时,会将其包含的 SQL 片断拼接到其所在的 SQL 语句中。 语法:< if test=“条件”> sql 语句的部分 </ if>
接口:
//动态sql ,使用java对象作为参数
List<Student> selectStudentIf(Student student);
mapper:
<!-- if
<if:test="使用参数java对象的属性值作为判断条件,语法 属性=XXX值">
(id > 0,1 = 1)是使用技巧,为了能够使语句正常执行,无论if能否执行都可以正常执行
-->
<select id="selectStudentIf" resultType="com.bjpowernode.domain.Student">
select id,name, age, email from student
where id > 0
<if test="name !=null and name !='' ">
and name = #{name}
</if>
<if test="age > 0">
or age > #{age}
</if>
</select>
4.3动态SQL之< where >
-
< if >标签的中存在一个比较麻烦的地方:需要在 where 后手工添加 1=1 的子句。因为,若 where 后 的所有条件均为 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 />
<!--
where: <where> <if> <if>...</where>
-->
<select id="selectStudentWhere" resultType="com.bjpowernode.domain.Student">
<include refid="studentSql" />
<where>
<if test="name !=null and name !='' ">
name = #{name}
</if>
<if test="age > 0">
or age > #{age}
</if>
</where>
</select>
4.4动态SQL之< foreach >
引入:当我们需要动态的给in命令里面添加参数时,我们要这样做
@Test
public void testfor(){
List<Integer> list = new ArrayList<>();
list.add(1001);
list.add(1002);
list.add(1003);
//String sql="select * from student where id in (1001,1002,1003)";
String sql="select * from student where id in";
StringBuilder builder = new StringBuilder("");
int init=0;
int len = list.size();
//添加开始的 (
builder.append("(");
for(Integer i:list){
builder.append(i).append(",");
}
builder.deleteCharAt(builder.length()-1);
//循环结尾
builder.append(")");
sql = sql + builder.toString();
System.out.println("sql=="+sql);
}
特别的麻烦,所以我们有了< foreach >标签
在foreach中可以放循环的对象,也可以自定义小括号,用法灵活
- 标签用于实现对于数组与集合的遍历。主要用在sql的in语句中。对其使用,需要注意:
➢ collection 表示要遍历的集合类型, list ,array 等。
➢ open、close、separator 为对遍历内容的 SQL 拼接。
- 具体含义:
collection:表示接口中的方法参数的类型, 如果是数组使用array , 如果是list集合使用list
item:自定义的,表示数组和集合成员的变量
open:循环开始是的字符
close:循环结束时的字符
separator:集合成员之间的分隔符
- 对应关系:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MhwesW6o-1648717794833)(C:\Users\Dell\AppData\Roaming\Typora\typora-user-images\image-20220331105311586.png)]
第一种用法:遍历 List<简单类型>
接口:
//foreach 用法 1
List<Student> selectForeachOne(List<Integer> idlist);
mapper:
<select id="selectForeachTwo" resultType="com.bjpowernode.domain.Student">
select * from student where id in
<foreach collection="list" item="stu" open="(" close=")" separator=",">
#{stu.id}
</foreach>
</select>
测试:
@Test
public void testSelectForEach(){
SqlSession sqlSession = MyBatisUtils.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.selectForeachOne(list);
for(Student stu:students){
System.out.println("foreach--one ==="+stu);
}
}
第二种用法:遍历 List<对象类型>
接口:
//foreach 用法 2
List<Student> selectForeachTwo(List<Student> stulist);
mapper:
<select id="selectForeachTwo" resultType="com.bjpowernode.domain.Student">
select * from student where id in (
<foreach collection="list" item="stu" >
#{stu.id},
</foreach>
-1 )
</select>
测试:
@Test
public void testSelectForTwo(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
List<Student> stuList = new ArrayList<>();
Student s1 = new Student();
s1.setId(1002);
s1.setName("lisi");
stuList.add(s1);
s1 = new Student();
s1.setId(1005);;
s1.setName("zs");
stuList.add(s1);
List<Student> students = dao.selectForeachTwo(stuList);
for(Student stu:students){
System.out.println("foreach--two ==="+stu);
}
}
4.5动态SQL之< sql >
< sql />标签用于定义 SQL 片断,以便其它 SQL 标签复用。而其它标签使用该 SQL 片断,需要使用< include />子标签。该< sql />标签可以定义 SQL 语句中的任何部分,所以< include />子标签可以放在SQL的任何位置。
<!--定义sql片段-->
<sql id="studentSql">
select id,name, age, email from student
</sql>
<!--
where: <where> <if> <if>...</where>
-->
<select id="selectStudentWhere" resultType="com.bjpowernode.domain.Student">
<include refid="studentSql" />
<where>
<if test="name !=null and name !='' ">
name = #{name}
</if>
<if test="age > 0">
or age > #{age}
</if>
</where>
</select>
第五章 MyBatis配置文件
5.1 主配置文件
之前项目中使用的 mybatis.xml 是主配置文件。 主配置文件特点:
- 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" >
- 根元素,< configguration >
主要包含内容:
➢ 定义别名
➢ 数据源
➢ mapper 文件
5.2 dataSource标签
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1eV2rnyF-1648717794834)(C:\Users\Dell\AppData\Roaming\Typora\typora-user-images\image-20220331164335393.png)]
Mybatis 将数据源分为三类:UNPOOLED 不使用连接池的数据源
POOLED 使用连接池的数据源
JNDI 使用 JNDI 实现的数据源
其中 UNPOOLED ,POOLED 数据源实现了 javax.sq.DataSource 接口, JNDI 和前面两个实现方式不同。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UchdfcpH-1648717794836)(C:\Users\Dell\AppData\Roaming\Typora\typora-user-images\image-20220331164518778.png)]
5.2.1 dataSource配置
<!--
dataSource:表示数据源,java体系中,规定实现了javax.sql.DataSource接口的都是数据源。
数据源表示Connection对象的。
type:指定数据源的类型
1)POOLED: 使用连接池, mybatis会创建PooledDataSource类
2)UPOOLED: 不使用连接池, 在每次执行sql语句,先创建连接,执行sql,在关闭连接
mybatis会创建一个UnPooledDataSource,管理Connection对象的使用
3)JNDI:java命名和目录服务(windows注册表)
-->
<dataSource type="POOLED">
<!--数据库的驱动类名-->
<property name="driver" value="${jdbc.driver}"/>
<!--连接数据库的url字符串-->
<property name="url" value="${jdbc.url}"/>
<!--访问数据库的用户名-->
<property name="username" value="${jdbc.user}"/>
<!--密码-->
<property name="password" value="${jdbc.passwd}"/>
</dataSource>
MyBatis 在初始化时,根据的 type 属性来创建相应类型的的数据源 DataSource,即:
- type=”POOLED”:MyBatis 会创建 PooledDataSource 实例
- type=”UNPOOLED” : MyBatis 会创建 UnpooledDataSource 实例
- type=”JNDI”:MyBatis 会从 JNDI 服务上查找 DataSource 实例,然后返回使用
5.3事务
5.3.1默认需要手动提交事务
- Mybatis 框架是对 JDBC 的封装,所以 Mybatis 框架的事务控制方式,本身也是用 JDBC 的 Connection 对象的 commit(), rollback()
< transactionManager type="JDBC" />
- Connection 对象的 setAutoCommit()方法来设置事务提交方式的。自动提交和手工提交、 该标签用于指定 MyBatis所使用的事务管理器。MyBatis 支持两种事务管理器类型:JDBC 与 MANAGED。
➢ JDBC:使用 JDBC 的事务管理机制。即,通过 Connection 的 commit()方法提交,通过 rollback()方法 回滚。但默认情况下,MyBatis 将自动提交功能关闭了,改为了手动提交。即程序中需要显式的对 事务进行提交或回滚。从日志的输出信息中可以看到。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8NV1r14p-1648717794837)(C:\Users\Dell\AppData\Roaming\Typora\typora-user-images\image-20220331165228331.png)]
➢ MANAGED:由容器来管理事务的整个生命周期(如 Spring 容器)。
5.3.2自动提交事务
设置自动提交的方式,factory 的 openSession() 分为有参数和无参数的。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZwYBAlx6-1648717794839)(C:\Users\Dell\AppData\Roaming\Typora\typora-user-images\image-20220331165239668.png)]
有参数为 true,使用自动提交,可以修改 MyBatisUtil 的 getSqlSession()方法。
session = factory.openSession(false);
再执行 insert 操作,无需执行 session.commit(),事务是自动提交的
5.4 使用数据库属性配置文件
数据库的属性配置文件: 把数据库连接信息放到一个单独的文件中。 和mybatis主配置文件分开。目的是便于修改,保存,处理多个数据库的信息。MyBatis 主配置文件需要从这个属性文件中读取这些数据。
步骤:
5.4.1在 classpath 路径下,创建 properties 文件
在 resources 目录创建 jdbc.properties 文件,文件名称自定义。
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/springdb
jdbc.user=root
jdbc.passwd=123456
5.4.2 使用 properties 标签
修改主配置文件,文件开始位置加入:
<!--指定properties文件的位置,从类路径根开始找文件-->
<properties resource="jdbc.properties" />
5.4.3 使用key值
<dataSource type="POOLED">
<!--数据库的驱动类名-->
<property name="driver" value="${jdbc.driver}"/>
<!--连接数据库的url字符串-->
<property name="url" value="${jdbc.url}"/>
<!--访问数据库的用户名-->
<property name="username" value="${jdbc.user}"/>
<!--密码-->
<property name="password" value="${jdbc.passwd}"/>
</dataSource>
5.5 mappers(映射器)
5.5.1 < mapper resource=" " />
使用相对于类路径的资源,从 classpath 路径查找文件 例如:
<!-- sql mapper(sql映射文件)的位置-->
<mappers>
<!--第一种方式:指定多个mapper文件-->
<mapper resource="com/bjpowernode/dao/StudentDao.xml"/>
<mapper resource="com/bjpowernode/dao/OrderDao.xml" />
</mappers>
5.5.2 < package name=" " />
指定包下的所有 Dao 接口
<mappers>
<!--第二种方式: 使用包名
name: xml文件(mapper文件)所在的包名, 这个包中所有xml文件一次都能加载给mybatis
使用package的要求:
1. mapper文件名称需要和接口名称一样, 区分大小写的一样
2. mapper文件和dao接口需要在同一目录
-->
<package name="com.bjpowernode.dao"/>
<package name="com.bjpowernode.dao2"/>
<package name="com.bjpowernode.dao3"/>
</mappers>
注意:此种方法要求Dao 接口名称和 mapper 映射文件名称相同,且在同一个目录中。< mapper >里面填的是路径,而< package >是包名