Mybaties使用梳理
框架是什么
框架是半成品的软件,定义好了一些基础功能
用户可以加入新功能,使其完整
基础功能是可重复使用的,可升级的。
Mybaties基础知识和用法
对应三层架构中的数据访问层(data access object: dao)
要素:
- 各种依赖
- Mybaties-Config.xml主配置文件
- SqlSession接口
基本使用流程
- 构建Maven模块
- 在pom文件中导入依赖
- 配置在resources(标记为根目录)Mybaties主配置文件
- 构建实体类和dao映射文件
- 获取SqlSession实例
- 通过sqlSession执行Mapper文件中的sql语句
- 得到数据
常用依赖和插件
<settings>
<setting name="logImpl" value="STDOUT_LOGGING" />
</settings>
<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>
<!--插件:确保映射文件(xxxxDao.xml被写入target的class中) -->
<build>
<resources>
<resource>
<directory>src/main/java</directory><!--所在的目录-->
<includes><!--包括目录下的.properties,.xml 文件都会扫描到-->
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<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>
主配置文件
主配置文件表头:
<?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">
环境:
标签下可以有多个
default: 指明默认的环境
id是自定义的字段
<environments default="mysql">
<environment id="mysql">
</environment>
</environments>
dataSource:
配置数据库信息
mappers:
<mappers>
<!--指定多个mapper文件的方式-->
<!--第一种,使用多个mapper标签,逐个指定对应类路径-->
<mapper resource="com/bjpowernode/dao/StudentDao.xml"/>
<!--第二种,使用包名的方式指定
name:xml文件所在的包名,这个包名下的所有xml文件都会被mybatis加载
使用package的要求:
1. mapper文件名称需要和接口名称一样,区分大小写的一样
2. mapper文件和dao接口需要在同一个目录
-->
<package name="com.bjpowernode.dao"/>
</mappers>
基础实用模版
//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();
//通过sqlsession执行sql语句
ElemType XXX = session.XXXX("dao类的全限定名称.XXXX");
session.close()
对象分析
SqlSession 接口对象用于执行持久化操作。一个 SqlSession 对应着一次数据库会话,一次会话以SqlSession 对象的创建开始,以 SqlSession 对象的关闭结束。
SqlSession 接口对象是线程不安全的,所以每次数据库会话结束前,需要马上调用其 close()方法,将 其关闭。再次需要会话,再次创建。 SqlSession 在方法内部创建,使用完毕后关闭。
SqlSession创建的实例默认关闭事物的自动提交
factory.openSession(true)可将mybaties事物设为自动提交,否则都需要手动commit
进阶
使用dao完成开发
解耦合+提搞代码复用性
步骤:
- 实现创建xxxImpl类,实现dao接口中的方法
- 通过dao接口声明daoImpl的实例
- 通过实例调用访问xxximpl类中的方法,执行sql,并获得结果
例如:
public Iterface StudentDao(){
int insertStudent(Student student);
}
1. 实现接口方法
@Override
public int insertStudent(Student student) {
SqlSession session = MyBatisUtil.getSqlSession();
int nums = session.insert(
"com.bjpowernode.dao.StudentDao.insertStudent",student);
session.commit();
session.close();
return nums;
}
@Test
public void testInsert() throws IOException {
StudentDao studentDao = new StudentDaoImpl();
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);
}
(重点)使用动态代理完成开发
在前面的使用中,Dao 的实现类其实并没有干什么实质性的工作,它仅仅就是通过 SqlSession 的相关 API 定位到映射文件 mapper 中相应 id 的 SQL 语句,真正对 DB 进行操作的工作其实是由框架通过 mapper 中的 SQL 完成的。
Mybaties提供了抛开dao实现类,直接定位到映射文件 mapper 中的相应 SQL 语句的功能,动态代理。从而进一步简化代码,并降低耦合性。
原理:
调用 SqlSession 的 getMapper()方法,获取指定接口的实现类对象。该方法的参数为指定 Dao接口类的 class 值。
例子:
StudentDao studentDao = MyBatisUtil.getSqlSession().getMapper(StudentDao.class);
借此,我们可以直接用studentDao.xxxx执行sql了
传参
#和$的区别
“#”相当于PreparedStatement执行sql。用"?"在传值处做占位符,然后预处理写入。效率高且能够避免sql注入,更安全。
“$“不使用占位符,是字符串连接方式,使用Statement对象执行sql,效率低。有sql注入的风险,缺乏安全性。但可以用于替换表名或者列名
多参数
//接口处
List<Student> selectMultiParam(@Param("自定义1") String name,
@Param("自定义2") int age);
//mapper 文件:
<select id="selectMultiParam" resultType="实体类的全限定名称xx.xx.x.xx">
select id,name,email,age from student where name=#{自定义1} or age = #{自定义2}
</select>
//测试方法:
@Test
public void testSelectMultiParam(){
List<Student> stuList = studentDao.selectMultiParam(" 李力",20);
stuList.forEach( stu -> System.out.println(stu));
}
传对象
使用 java 对象传递参数, java 的属性值就是 sql 需要的参数值。
使用 java 对象传递参数, java 的属性值就是 sql 需要的参数值。 每一个属性就是一个参数。语法格式: #{ property, javaType=java 中数据类型名, jdbcType=数据类型名称 }
javaType, jdbcType 的类型 MyBatis 可以检测出来,一般不需要设置。常用 #{ 对象属性 }
例子
//创建保存参数值的对象 QueryParam
public class QueryParam {
private String queryName;
private int queryAge;
//set , get 方法
}
//接口方法:
List<Student> selectMultiObject(QueryParam queryParam);
//mapper 文件:
<select id="selectMultiObject" resultType="com.bjpowernode.domain.Student">
select id,name,email,age from student where name=#{queryName} or age=#{queryAge}
</select>
按位置传参
传入:xxxx.方法(arg0,arg1)
读取:固定用#{arg0},#{arg1}…
Map传参
${key}读取
Mybaties封装输出
根据接口定义的返回类型去接收就好
值得一提的:
map只能接受一条数据
resultMap 可以自定义 sql 的结果和 java 对象属性的映射关系。
更灵活的把列值赋值给指定属性。
常用在列名和 java 对象属性名不一样的情况。
<!--
创建 resultMap
id: 自定义的唯一名称,在 <select> 使用
type: 期望转为的 java 对象的全限定名称或别名
-->
<resultMap id="studentMap" type="com.bjpowernode.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="selectUseResultMap" resultMap="studentMap">
select id,name,email,age from student where name=#{queryName} or age= {queryAge}
</select>
若数据库列字段和J实体类属性名不同,可在读表时用as,将数据库列名转化为实体类的属性名