目录
传参(从java代码中把数据传入到mapper文件的sql语句中)
数据库的属性配置文件:把数据库连接信息放入一个单独的文件中,和mybatis配置文件分开。
这是我在网上根据老师讲课自学写的MyBatis框架的学习笔记。发个博客是想记录和分享给大家。对于MyBatis框架目前我只是会用,处于一个知其然,不知其所以然的状态。如果笔记有不对的地方,请各位大佬,同学,朋友不吝赐教,一起交流进步。
pdf文档0积分下载:https://download.csdn.net/download/D_wang1/20283961?spm=1001.2014.3001.5503
Mybatis框架
第一章 框架概述
1.1 软件开发常用结构
1.1.1 三层架构
三层包括:
视图层:接受用户的请求参数,显示处理结果,使用web页面和用户交互。(jsp,html,servlet)
业务逻辑层:接收视图层传递过来的数据,计算逻辑,调用数据库,获取数据
数据逻辑层:访问数据库,执行对数据的查询、修改、删除等。
三层对应的包:
页面层: controller包 (servlet)
业务逻辑层: service包(XXXService类)
数据访问层:dao包(XXXDao类)
三层中类的交互
用户使用视图层->业务逻辑层->数据访问层(持久层)->数据库
三层对应的处理框架
视图层:servlet---SpringMVC(框架)
业务逻辑层:service---Spring (框架)
数据访问层:dao---Mybatis(框架)
1.2 框架
框架是一个舞台(提供了基础功能的一个平台),一个模板
意味着:1. 框架中定义好了一些功能,这些功能是可用的。2. 可以在项目中加入自己的功能,这些功能可以利用框架中写好的功能。
框架的特点
1、框架一般不是全能的,不能做所有事情
2、框架是针对某一领域有效。特长在某一方面,比如MyBatis做数据库操作强,不能做其他的。
3、框架是个软件
1.3 MyBatis框架概述
MyBatis框架:早期叫iBatis,代码在GitHub上。MyBatis SQL Mapper FrameWork for Java(SQL映射框架)
-
SQL Mapper: sql映射:可以把数据库中的一行数据映射为一个Java对象。一行数据可以看成一个Java对象。操作这个对象,就相当于操作表中的数据。
-
Data Access Objects(Daos):数据访问,对数据库执行增删改查。
MyBatis提供了哪些功能:
-
提供了创建Connection,Statement,ResultSet的能力,不用开发人员创建这些对象。
-
提供了执行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")); stuList.add(stu); }
-
提供了关闭资源的能力,不用你关闭Connection,Statement,ResultSet
开发人员要做的是:提供SQL语句->MyBatis处理SQL ->开发人员得到List集合或者Java对象
总结 :Mybatis是一个SQL映射框架,提供数据库的操作能力,增强的JDBC。使用MyBatis能够让开发人员集中精神写SQL就行了,不需要关心Connection、statement,ResultSet的创建,销毁,SQL的执行。
第二章 MyBatis快速入门(idea,maven项目)
基本配置步骤
1、第一步在maven中添加mybatis和mysql的依赖
<dependencies>
<!--在maven文件的pom.xml文件中添加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>
<!--____________________________________________-->
<!--builde下的resources的作用是把java下的包拷贝到target中-->
<build>
<resources>
<resource>
<directory>src/main/java</directory> <!--所在的目录-->
<includes><!--包括目录下的。properties和.xml 文件都会扫描到-->
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
2、创建Dao接口(接口的返回类型是执行数据库操作后返回类型)
public interface studentDao {
/*查询student对象*/
public List<student> selectStudents();
}
3、创建mapper文件即sql映射文件(标签里的id对应接口中的方法)
<mapper namespace="org.example.dao.studentDao">
<!--namespace的值是对应Dao接口的全限定名称-->
<!--select标签中的id对应studentDao接口里的方法-->
<!--resultType对应返回搜索结果的类型:student对象-->
<!--同理parameterType对应传入的数据的类型(全限定名称)-->
<select id="selectStudents" resultType="org.example.domain.student">
select * from student order by id
</select>
</mapper>
4、创建mybatis的主配置文件(连接数据库&指定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>
<!--环境配置:数据库的连接信息
default:必须和某个environment的id值一样。
告诉mybatis使用哪个数据库的连接信息。也就是访问哪个数据库。
-->
<typeAliases>
<!--别名,将org.example.Bean.student用student代替-->
<typeAlias alias="student" type="org.example.Bean.student"></typeAlias>
</typeAliases>
<environments default="development">
<!--environment:一个数据库信息的配置,环境
id:一个唯一值就,自定义,显示环境的名称。-->
<environment id="development">
<!-- transactionManager:mybatis事务类型
type:JDBC(表示使用jdbc中的Connection对象的commit,rollback做事务处理)-->
<transactionManager type="JDBC"/>
<!-- dataSource:表示数据源,连接数据库的
type:表示数据源的类型,POOLED表示使用连接池-->
<dataSource type="POOLED">
<!--drive,user,username,password是固定的,不能自定义-->
<!--数据库的驱动类名-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<!--连接数据库的url字符串-->
<property name="url" value="jdbc:mysql://localhost:3306/ssm?useUnicode=true&characterEncoding=utf8"/>
<!--访问数据库的用户名-->
<property name="username" value="root"/>
<!--密码-->
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!--sql映射文件的位置
-->
<mappers>
<!--一个mapper标签指定一个文件的位置,从类路径开始的路径信息 target/clasess(类路径)-->
<mapper resource="org/example/dao/studentDao.xml"/>
</mappers>
</configuration>
<!--
mybatis的主要配置文件:定义了数据库的配置信息
mybatis-3-config.dtd:约束文件名称
-->
5、使用SqlSession调用方法执行。
需要注意的是mybatis默认不会提交事务,所以在每次操作数据库增删改时需要提交事务。sqlSession.commit()
public class MyApp {
public static void main(String[] args) throws IOException {
//访问mybatis读取student数据
//1.定义mybatis的主配置文件的名称
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.example.dao.studentDao"+"."+"selectStudents";
//7.执行sql语句,通过SqlId找到语句
List<student> studentList = sqlSession.selectList(sqlId);
//8.输出结果
for(student stu:studentList) {
System.out.println(stu);
}
//关闭SqlSession对象
sqlSession.close();
}
}
工具类MyBatisUtils
工具类的作用是获取SqlSession对象
package org.example.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对象,使用SqlSessionFactoryBuilder
factory = new SqlSessionFactoryBuilder().build(in);
} catch (IOException e) {
e.printStackTrace();
}
}
//获取sqlSession的方法
public static SqlSession getSqlSesison() {
SqlSession sqlSession = null;
if(factory != null) {
sqlSession = factory.openSession();//非自动提交事务
}
return sqlSession;
}
}
第三章 mybatis框架Dao代理
动态代理的实现(创建Dao接口的实现类)
studentDao std = sqlSession.getMapper(studentDao.class);
//使用SqlSession.getMapper(dao接口.class)获取这个到接口的对象
传参(从java代码中把数据传入到mapper文件的sql语句中)
parameterType:写在mapper文件中的一个属性。表示dao接口方法中参数的数据类型。为全限定名称。
<select id="selectStudents" parameterType="java.lang.Integer" resultType="student">
select * from student where name = #{myname} and age = #{myage}
</select>
<!--parameterType:dao接口中方法参数的数据类型
parameterType的值是java的数据类型,或者是mybatis中的别名
例如:parameterType = "org.example.bean.student"
parameterType = "java.lang.Integer"
-->
使用#{ }之后,mybatis执行sql是使用jdbc中的parameterType对象
由mybatis执行下面的代码:
-
mybatis创建Connection,ParameterStatement对象
String sql = " select * from student where id = ?";
ParameterStatement pst = conn.perparedStatement(sql);
pst.setInt(1,1001);
-
执行sql封装为resultType = "org.example.bean.student"这个对象
ResultSet rs = ps.executeQuery(); while(rs.next()) { student student = new student(); student.setId(rs.getInt("id")); student.setName(rs.getString("name")); student.setEmail(rs.getString("email")); student.setAge(rs.getInt("age")); } return student;
传递多个参数
1.命名参数
//dao接口中
List<student> selectMulitParam(@Param("myname") String name,@Param("myage") Integer age);
//xml映射器中
<select id="selectStudents" resultType="student">
select * from student where name = #{myname} and age = #{myage}
</select>
2.使用对象
//dao接口中
public student selectStudent(student student);
//xml映射器中
<select id="selectStudent" parameterType="student" resultType="student">
select * from student where id = #{id} and name = #{name}
</select>
<!--其中,多个参数使用java对象的属性值,作为参数实际值
使用对象的语法:#{属性名,javaType=类型名称,jdbcType=数据类型} 这是最完整的语法格式
javaType是java中的属性数据类型
jdbcType是数据库中的数据类型
如:#{id,javaType=java.lang.Integer,jdbcType=INTEGER}
我们一般使用简化方式:#{属性名},javaType,jdbcType的值mybatis反射能获取,不用提供。
-->
3.按位置传参
//dao中
public student selectStudent(String name,Integer age,String email);
/**多个参数按位置传参
*mybatis 3.4之前,使用#{0},#{1}
*mybatis 3.4之后,使用#{arg0},#{arg1}*/
//xml映射器中
<select id="selectStudent" resultType="student">
select * from student where name = #{arg0} and age = #{arg1}
</select>
4.Map传参
首先创建map对象,将参数存入map对象中
Map<String,Object> data = new HashMap();
data.put("myname","张三");
data.put("age",28);
List<student> student = dao.testMapSelect(data); //传参
//dao中
List<student> testMapSelect(Map<String,Object> map);
//xml映射器中,利用map的key识别参数
<select id="selectStudent" resultType="student">
select * from student where name = #{myname} and age = #{myage}
</select>
#和$区别
-
#:占位符,告诉mybatis使用实际的参数值代替。并使用PrepareStatement对象执行sql语句,#{...}代替sql语句的"?"。这样做更安全,更迅速,通常是首选做法
-
$:字符串替换,告诉mybatis使用$包含的“字符串”替换所在位置。使用Statement把sql语句和$()的内容连接起来。主要用在替换表名、列名、不同顺序等操作。
// # 的结果:select * from student where name = ?
// $ 的结果:select * from student where name = "张三"是哦那个Statement对象执行sql,效率比PreparedStatement低。sql注入破坏数据库。
$ 可以替换列名、表名。当确定数据是安全的时候可以用$。
resultType
resultType:指SQL执行完后,数据转为的java对象
处理方式
返回对象类型
-
mybatis执行sql语句,然后mybatis调用类的无参构造方法,创建对象。
-
mybatis把ResultSet指定列值付给同名的属性。
//映射器中: <select id="selectStudent" resultType="student"> select * from student </select> //对应的JDBC ResultSet rs = executeQuery(" select * from student"); while(rs.next()) { student.setId(rs.getInt("id")); student.setName(rs.getString("name")); student.setEmail(rs.getString("email")); student.setAge(rs.getInt("age")); }
返回map类型
返回Map<Object,Object> map
1.列名是map的key,列值是map的value 2.返回map最多返回一行记录。多一行报错。
//dao中
Map<Object,Object> selsectStudent(Integer id);
//xml中
<!--返回map
1.列名是map的key,列值是map的value
2.返回map最多返回一行记录。多一行报错。
-->
<select id="selectStudents" resultType="java.Util.Map">
select * from student
</select>
//test测试类中
Map<Object,Object> map = dao.selectStudent(1001);
System.out.println(map);
返回List<map<Object,Object>>
如果想利用Map返回多行数据,这时我们可以用List<map<Object,Object>>
//dao中
List<Map<Object,Object>> selectStudents();
//xml中
<select id="selectStudents" resultType="java.util.Map">
select * from student
</select>
//test测试类中
List<Map<Object,Object>> students = dao.selectStudents();
resultMap
//dao中
List<student> selectStudents();
//xml中
<!--定义resultMap
id:自定义名称,表示定义的这个resultMap
type:java类型的全限定名称
-->
<resultMap id="studentMap" type="org.example.Bean.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>
配置别名
在主配置文件mybatis.xml中配置别名
1. ==定义别名的第一种方式==
指定一个类型一个自定义别名
```
<typeAliases>
<!--别名,将org.example.Bean.student用student代替-->
<typeAlias alias="student" type="org.example.Bean.student"></typeAlias>
</typeAliases>
```
2. ==定义别名的第二种方式==
<package>中,name是包名,这个包中的所有类,类名就是别名(类名不区分大小写)
```
//mybatis.xml文件中
<package name="org.example.Bean">
//xml文件中
<select id="selectStudents" resultType="student">
select * from student
</select>
### 模糊查询
两种方式:推荐使用第一种
-
第一种,在java代码中指定like的内容
//xml中 <select id="selectLikeOne" resultType="org.example.Bean.student"> select * from student where name like #{name} </select> //测试类test中 String name = "%李%"; List<student> students = dao.selectLikeOne(name);
-
第二种,在mapper中拼接 like "%" 李 "%"
//xml中 <select id="selectLikeTwo" resultType="org.example.Bean.student"> select * from student where name like "%" #{name} "%" </select> //测试类test中 String name = "李"; List<student> students = dao.selectLikeTwo(name);
第四章动态SQL
动态sql:意味着sql内容是变化的,可以跟据条件获取不同的sql语句。主要是where内容的部分发生变化。
动态sql的实现:使用mybatis提供的标签:<if>、<where>、<foreach>
-
<if>是判断条件。语法<if test="判断java对象的属性值"> 部分sql语句 </if>
<select id="selectStudentIf" resultType="org.example.Bean.student"> select * from student where 1=1 <if test="name != null and name !=''"> and name = #{name} </if> <if test="age>0"> or age > #{age} </if> </select> //其中where后面的1=1这个条件,可以解决if标签某个条件不成立时造成的sql语法错误。<where>可解决if标签这个问题。
-
<where>用来包含多个<if>的,当多个<if>有一个成立时,<where>会自动增加一个where关键字,并去掉<if>中多余的and,or等连接词。
<select id="selectStudentWhere" resultType="org.example.Bean.student"> select * from student <where> <if test="name != null and name !=''"> name = #{name} </if> <if test="age>0"> or age > #{age} </if> </where> </select> //条件不满足时自动去掉多余的and,or
-
<foreach>循环java中的数组,list集合,主要用在sql的in语句中。
学生id是1001.1002,1003
select * from student where id in(1001,1002,1003)
<!--第一种方式,简单参数的链表传值-->
<!--foreach使用--> <!-- collection:表示接口中方法参数的类型,数组用array,list集合用list item:自定义的,表示数组和集合成员的变量 open:循环开始时的字符 close:循环结束时的字符 separator:集合成员间的分隔符 --> <select id="selectForeachOne" resultType="org.example.Bean.student"> select * from student where id in <foreach collection="list" item="myid" open="(" close=")" separator=","> #{myid} </foreach> </select>
<!--第二种方式,包含多个对象的链表传值-->
<select id="selectForeachTwo" resultType="org.example.Bean.student"> select * from student where age in <foreach collection="list" item="stu" open="(" close=")" separator=","> #{stu.age} , #{stu.name} </foreach> </select>
动态SQL之代码片段
sql代码片段,就是复用一些语法
步骤:
-
先定义<sql id="自定义名称,唯一"> sql语句,表名,字段等</sql> 此处可任意定义
-
再使用,<include refid="id的值" />
<!--定义sql片段-->
<sql id="studentSql">
select * from student
</sql>
<select id="selectForeachTwo" resultType="org.example.Bean.student">
<!--引入片段-->
<include refid="studentSql"> where age in
<foreach collection="list" item="stu" open="(" close=")" separator=",">
#{stu.age} , #{stu.name}
</foreach>
</select>
第五章 扩展
数据库的属性配置文件:把数据库连接信息放入一个单独的文件中,和mybatis配置文件分开。
目的时便于修改保存,处理多个数据库的信息。
-
在resources目录中定义一个属性配置文件,xxx.properties。例如:jdbc.properties
key:一般使用。做多级目录
例如 jdbc.mysql.driver
-
在mybatis主配置文件中,使用<property>指定文件的位置
在需要值的地方${key}
//jdbc.properties文件:
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssm?characterEncoding=utf8
jdbc.user=root
jdbc.password=123456
//mybatis主配置文件中:在configuration标签下第一行注明:
<!--指定properties文件的位置,从类路径开始找文件-->
<properties resource="jdbc.properties"></properties>
<!--在environment中property标签的value值应该填写为jdbc.properties文件里的key值-->
<property name="driver" value="${jdbc.driver}"/>
<!--连接数据库的url字符串-->
<property name="url" value="${jdbc.url}"/>
<!--访问数据库的用户名-->
<property name="username" value="${jdbc.user}"/>
<!--密码-->
<property name="password" value="${jdbc.password}"/>
pageHelper 分页
-
在maven配置文件中导入依赖
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.10</version>
</dependency>
-
加入plugin配置
在mybatis主配置文件中,<environments>之前加入
<!--配置插件-->
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
-
使用
//加入一个分页PageHelper
//pageNum:第几页开始
//pageSize:一页有多少行数据
PageHelper.startPage(1,1);