Mybatis从入门到精通(全)
目录
- 前言
- 1. idea软件小技巧
- 2. mybatis优势
- 3. mybatis入门项目
- 3.1 项目具体步骤
- 3.2 创建数据表
- 3.3 创建maven项目
- 3.4 pom.xml配置文件
- 3.5 数据类、接口类和映射文件
- 3.6 mybatis主配置文件
- 3.7 测试文件
- 3.8 dubug代码
- 3.9 配置文件模板
- 3.10 功能添加-插入元素
- 3.11 日志提交
- 4. 改进步骤
- 4.1 常用类介绍
- 4.2 封装工具类
- 4.3 传统dao类改进
- 5. 动态代理
- 5.1 参数剖析
- 5.2 深入理解参数
- 5.2.1 单参数
- 5.2.2 多参数
- 5.2.3 占位符
- 5.2.4 总结
- 5.3 封装mybatis输出结果
- 5.3.1 resultType
- 5.3.2 别名
- 5.3.3 resultMap
- 5.4 模糊like
- 6. 动态sql
- 6.1 if结构
- 6.2 where结构
- 6.3 foreach结构
- 6.4 动态sql
- 7. 配置文件
- 7.1 数据库配置
- 7.2 mapper位置
- 8. PageHelper
前言
项目框架中 mybatis用于数据访问层
界面层:servlet–springmvc
业务逻辑层:service类–spring
数据访问层:dao类–mybatis
三层的访问交互是依次进行 在深入访问数据库后依次退出
了解更多mybatis 可查看
mybatis入门中文文档
该文章的学习主要通过视频进行总结汇总
2020最新MyBatis教程【IDEA版】-MyBatis从入门到精通
该文章的学习代码如下
mybatis从入门到精通的学习代码.rar
1. idea软件小技巧
- ctrl+alt+shift+c 复制全限定名称 相当于copy reference
- ctrl+shift+o 相当于reimport
- 创建类文件 =包名.类名 会自动生成包与类
- 无法创建xml文件,可以直接创建普通文件,名字后缀加xml
- 代码变红色,引入class包名,alt+enter
2. mybatis优势
而mybatis框架的好处对比
mybatis与jdbc、hibernate的对比:
jdbc:代码比较多,开发效率低,重复代码多,业务代码和数据库操作混杂一起。在代码块中对象要创建和销毁,查询的结果要封装list。
hibernate:全自动
mybatis:提供访问数据库基本功能,半自动,sql与java编码分离,轻量级的框架
回顾jdbc的代码可看我之前的文章
jdbc从入门到精通(全)
学完之后,发现jdbc的代码
- 业务代码和数据库的操作混在一起
- 重复的代码比较多
为此减轻使用 JDBC 的复杂性,不用编写重复的创建 Connetion , Statement ; 不用编写关闭资源代码。直接使用 java 对象,表示结果数据。让开发者专注 SQL 的处理。 其他分心的工作由 MyBatis 代劳
mybatis两大功能:
- sql mapper:sql映射,可以把数据库表中的一行数据,映射为一个java对象,操作此对象即操作此数据
- dao类:数据访问,进行数据增删改查
写sql即可,不必关心Connection,Statement,ResultSet的创建,销毁,sql的执行
- MyBatis 是一个优秀的基于 java 的持久层框架,内部封装了 jdbc,开发者只需要关注 sql 语句本身,而不需要处理加载驱动、创建连接、创建statement、关闭连接,资源等繁杂的过程。
- MyBatis 通过 xml 或注解两种方式将要执行的各种 sql 语句配置起来,并通过 java 对象和 sql 的动态参数进行映射生成最终执行的 sql 语句,最后由 mybatis 框架执行 sql 并将结果映射为 java 对象并返回。
3. mybatis入门项目
3.1 项目具体步骤
这个具体步骤比较重要
可以边建立项目的时候边想代码是如何调用
- 新建数据表
- maven配置以及在pom.xml中加入mybatis坐标和mysql驱动依赖 还有xml的生成配置(因为类路径下不会自动生成)
- 创建类,保存表中的数据
- 创建dao接口,定义操作数据库方法接口方法。
- 创建mapper文件,即在同一目录下定义sql映射文件,写sql文件和接口方法对应的sql语句
- 创建mybatis主配置文件(提供数据库连接信息和xml中sql的映射信息(指定mapper文件的位置),也就是类路径的具体位置。
- 创建mybatis类(SqlSession对象),来访问数据库sql
3.2 创建数据表
将java与数据库连接
涉及数据库可看我上一篇文章
数据库中增删改常用语法语句(全)
数据库查询常用语句语法
CREATE TABLE `student` (`id` int(11) NOT NULL ,`name` varchar(255) DEFAULT NULL,`email` varchar(255) DEFAULT NULL,`age` int(11) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
3.3 创建maven项目
项目启用maven,具体配置可查看我上一篇文章
Maven详细配置(全)
项目启动成功后截图 出现build success
3.4 pom.xml配置文件
- 坐标、mybatis依赖和mysql驱动
- 扫描的xml插件、编译器版本和单元测试
<!--坐标 --><groupId>org.example</groupId><artifactId>mybatis</artifactId><version>1.0-SNAPSHOT</version><!--配置该有的编译器版本,此版本为1.8 --><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>
还要添加一个xml的配置文件
因为java默认文件路径识别不到xml的后缀
之后再target下才会生成
<!--扫描xml插件 -->
<build><resources><resource><directory>src/main/java</directory><!--所在的目录--><includes><!--包括目录下的.properties,.xml 文件都会扫描到--><include>**/*.properties</include><include>**/*.xml</include></includes><filtering>false</filtering></resource></resources></build>
配置好之后ctrl+shift+o更新配置或者是右键在maven中 reimport
3.5 数据类、接口类和映射文件
创建一个数据类,包含数据的定义,设值以及获取等
//推荐和表名一样。容易记忆
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;}@Overridepublic String toString() {return "Student{" +"id=" + id +", name='" + name + '\'' +", email='" + email + '\'' +", age=" + age +'}';}
}
创建另一个包,包含接口类和配置文件
创建一个包含所有数据的列表,每个数据就是一个对象
用该方法来调用数据
//查询student表的所有的数据public List<Student> selectStudents();
而这个数据要用在该类中同一目录之中,同一包之下的xml文件
mybatis会执行这些sql文件,具体格式代码说明:
1.dtd为约束文件,限制和检查出现的标签是否符合mybatis定义的规则
2.mapper为根标签,namespace为命名空间,可以自定义的字符串,最好用dao接口全限定名称
3.使用特定标签表示数据库特定操作
~select查询,update更新,insert插入,delete删除
~3.1 内部名称为 id是sql的唯一标识,mybatis会通过id值执行sql语句,可以任意定值,但最好用接口中方法的名称调用
~3.2 resultType为结果类型,执行sql后得到resultSet,并且遍历它所得到java对象类型。类比jdbc的创建数据集即执行的sql数据得到的结果,最后一一赋给java对象获取,最好用全限定名称,也就是实体类的全限定名称
总结:
- dao接口全限定名称用在mapper的根标签
- id为方法名
- resultType为返回的实体类对象全限定名称
namespace为接口名,id为方法名,resultType为定义的类名
后面定义的测试类中 执行数据库语句的字符串即为接口名.方法名
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//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>
</mapper>
总之id用列表定义的方法名,namespace和resultType用全限定名称路径名
3.6 mybatis主配置文件
这个主配置文件和jdbc文件中的这个代码功能一致
新建一个resources目录并且设置改目录为resources root
在该目录下新建一个mybatis.xml的配置文件
- dtd约束文件名称
- configuration根标签
- environments 环境配置为连接数据库的信息,default需要与environment某个id值一样,表示需要使用哪个数据库信息
- environment 数据库配置信息,id唯一值 表示环境名称
- transactionManager为mybatis的事务类型
- dataSource表示数据源,连接数据库
主要看代码中的注释也可以
数据库连接信息
<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>
sql映射mapper位置
一个mapper标签指定一个文件位置,可以用多个mapper标签指定
这个文件位置间隔需要用 /
点击maven的compile编译即可
上面的pom.xml配置了识别xml配置文件
会在target/clasess(类路径)下生成
具体调用的映射文件的位置(通过target/clasess(类路径))要通过mapper进行映射
<!-- sql mapper(sql映射文件)的位置--><mappers><!--一个mapper标签指定一个文件的位置。从类路径开始的路径信息。 target/clasess(类路径)--><mapper resource="com/bjpowernode/dao/StudentDao.xml"/><!--<mapper resource="com/bjpowernode/dao/SchoolDao.xml" />--></mappers>
做项目整合的时候只需要修改
数据库的连接信息以及sql映射位置即可
其他都雷同,只需修改此处两个位置
3.7 测试文件
在生成的/target/class下有xml配置文件路径
(class文件中必须要有主配置文件)
- 用sql的SqlSessionFactory对象调用读取的主配置文件
- 以此来打开session文件,赋值给SqlSessionFactoryBuilder对象
- 通过sql文件映射的执行语句输出结果
具体怎么识别是哪个xml配置文件
主要通过xml配置文件中的namespace的命名空间
com.bjpowernode.dao.StudentDao(为全限定名称名)+selectStudents(方法名)
最后为com.bjpowernode.dao.StudentDao.selectStudents
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中获取SqlSessionSqlSession sqlSession = factory.openSession();//6.【重要】指定要执行的sql语句的标识。 sql映射文件中的namespace + "." + 标签的id值//String sqlId = "com.bjpowernode.dao.StudentDao" + "." + "selectStudents";//namespace.id值为sqlId的执行语句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();}
运行的即种解决方法:
- maven插件的 clean->compile
- 窗口中build的rebuild project
- 窗口中file的Invalidate Caches
- 手工拷贝复制target不存在的文件
在编译过程中如果出现以下问题
可查看我之前的文章
- 出现Could not find resource mybatis.xml的解决方法
- 出现target\surefire-reports for the individual test results的解决方法
编译成功之后的数据展示台如下
配合数据库表可一一验证
3.8 dubug代码
- 定义一个配置文件之后直接获取配置文件
进入到直接获取配置文件的源码,直接获取
return返回另一个代码函数
在调用另外一个函数,也就是类加载器
一直遍历判断直到他是为止
- 用sql的SqlSessionFactory对象调用读取的主配置文件
具体源码内部如下
- 以此来打开session文件,赋值给SqlSessionFactoryBuilder对象
3.9 配置文件模板
1.映射文件模板
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="接口包名全名称"><select id=" 方法名" resultType="含数据的类名全名称"></select></mapper>
2.主配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//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><environments default="mydev"><environment id="mydev"><transactionManager type="JDBC"/><dataSource type="POOLED"> <!--数据库连接池--><!--数据库的驱动类名--><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></environments><!-- sql mapper(sql映射文件)的位置--><mappers><mapper resource="com/bjpowernode/dao/StudentDao.xml"/><!--<mapper resource="com/bjpowernode/dao/SchoolDao.xml" />--></mappers>
</configuration>
idea具体设置位置:
3.10 功能添加-插入元素
基于以上项目进行整改
添加额外的插入数据库元素的功能
数据库的增删改查,原本有查询功能,现在额外补充一个插入元素功能
1.接口类中补充插入元素的方法
插入的元素为类对象,返回结果为数据行数,即int类型
//插入方法//参数: student ,表示要插入到数据库的数据//返回值: int , 表示执行insert操作后的 影响数据库的行数public int insertStudent(Student student);
2.与接口类中同一目录下的sql映射文件xml中 添加一个插入元素
id最好用插入方法类
插入的具体格式是 #{ }
,没有返回的实体类类型,所以不用resultType这个属性
<!--插入操作--><insert id="insertStudent">insert into student values(#{id},#{name},#{email},#{age})</insert>
以上两个文件的具体位置如下
3.测试类中额外几个函数
//6.【重要】指定要执行的sql语句的标识。 sql映射文件中的namespace + "." + 标签的id值String sqlId = "com.bjpowernode.dao.StudentDao.insertStudent";//7. 重要】执行sql语句,通过sqlId找到语句Student student = new Student();student.setId(1006);student.setName("关羽");student.setEmail("guanyu@163.com");student.setAge(20);int nums = sqlSession.insert(sqlId,student);//mybatis默认不是自动提交事务的, 所以在insert ,update ,delete后要手工提交事务//sqlSession.commit();
添加代码主要通过sqlSession这个类中的函数
这个函数源码是
第一个为sql语句,第二个为对象参数
完整代码如下:
public class TestMyBatis {//测试方法,测试功能@Testpublic void testInsert() 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中获取SqlSessionSqlSession sqlSession = factory.openSession();//SqlSession sqlSession = factory.openSession(true);//6.【重要】指定要执行的sql语句的标识。 sql映射文件中的namespace + "." + 标签的id值String sqlId = "com.bjpowernode.dao.StudentDao.insertStudent";//7. 重要】执行sql语句,通过sqlId找到语句Student student = new Student();student.setId(1006);student.setName("关羽");student.setEmail("guanyu@163.com");student.setAge(20);int nums = sqlSession.insert(sqlId,student);//mybatis默认不是自动提交事务的, 所以在insert ,update ,delete后要手工提交事务sqlSession.commit();//8.输出结果System.out.println("执行insert的结果="+nums);//9.关闭SqlSession对象sqlSession.close();}
}
编译完成之后,需要提交事务才可看到新增加的数据,mybatis默认是没有提交事务
即在insert ,update ,delete后要手工提交事务
//mybatis默认不是自动提交事务的, 所以在insert ,update ,delete后要手工提交事务sqlSession.commit();
insert ,update ,delete这些数据在编译器的输出平台中看不到
需要添加一个日志才可看到
具体日志的配置在下面
具体显示结果如下(添加了日志)
查看其数据库的结果如下
具体可看我这篇文章
添加数据到数据库中显示乱码的解决方法
3.11 日志提交
需要在mybatis.xml主配置文件中添加一个日志
才会在编译器看到修改数据库的结果
<!--settings:控制mybatis全局行为--><settings><!--设置mybatis输出日志--><setting name="logImpl" value="STDOUT_LOGGING" /></settings>
4. 改进步骤
4.1 常用类介绍
介绍如何改进的时候
先介绍下常用类的代码逻辑
//访问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();
SqlSession sqlSession = factory.openSession(true);
//6.【重要】指定要执行的sql语句的标识。 sql映射文件中的namespace + "." + 标签的id值
String sqlId = "com.bjpowernode.dao.StudentDao.insertStudent";
//7. 重要】执行sql语句,通过sqlId找到语句
Student student = new Student();
student.setId(1006);
student.setName("关羽");
student.setEmail("guanyu@163.com");
student.setAge(20);
int nums = sqlSession.insert(sqlId,student);//mybatis默认不是自动提交事务的, 所以在insert ,update ,delete后要手工提交事务
sqlSession.commit();//8.输出结果
System.out.println("执行insert的结果="+nums);//9.关闭SqlSession对象
sqlSession.close();
主要是介绍上面这些方法中的具体步骤以及使用过程
- 1. Resources:读取主配置文件,是mybatis的一个类
InputStream in = Resources.getResourceAsStream("mybatis.xml");
- 2. SqlSessionFactoryBuilder : 创建SqlSessionFactory对象
主要的过程是先创建自我的实体类对象,之后通过自我实体类对象创建一个SqlSessionFactory对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
总体来说就是
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
- 3.SqlSessionFactory :接口类,整个项目有一个此对象即可
获取SqlSession对象,SqlSession sqlSession = factory.openSession();
openSession() :无参数, 非自动提交事务SqlSession
openSession(true) : 自动提交事务的SqlSession
openSession(false) 非自动提交事务的SqlSession
即在接口类这样定义即可
//5.获取SqlSession对象,从SqlSessionFactory中获取SqlSession
SqlSession sqlSession = factory.openSession(true);
上下两条语句对等
//5.获取SqlSession对象,从SqlSessionFactory中获取SqlSession
SqlSession sqlSession = factory.openSession();
//mybatis默认不是自动提交事务的, 所以在insert ,update ,delete后要手工提交事务
sqlSession.commit();//或者直接写
SqlSession sqlSession = factory.openSession(true);
- 4.SqlSession接口 :定义了操作数据的方法
有selectOne() ,selectList() ,insert(),update(), delete(), commit(), rollback()等
SqlSession对象不是线程安全的,即执行sql语句之前,使用openSession()获取SqlSession对象。执行结束后关闭SqlSession.close()
,这样才是安全的
SqlSession的实现类是DefaultSqlSession,都重写了这些方法,主要是多态的一个使用方法
4.2 封装工具类
将常用类进行封装
大部分都是一样的
public class MyBatisUtils {private static SqlSessionFactory factory = null;static {String config="mybatis.xml"; // 需要和你的项目中的文件名一样try {InputStream in = Resources.getResourceAsStream(config);//创建SqlSessionFactory对象,使用SqlSessionFactoryBuildfactory = 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;}
}
在测试类的完整代码如下:
public class MyApp2 {public static void main(String[] args) throws IOException {//获取SqlSession对象,从SqlSessionFactory中获取SqlSessionSqlSession sqlSession = MyBatisUtils.getSqlSession();//【重要】指定要执行的sql语句的标识。 sql映射文件中的namespace + "." + 标签的id值String sqlId = "com.bjpowernode.dao.StudentDao.selectStudents";//【重要】执行sql语句,通过sqlId找到语句List<Student> studentList = sqlSession.selectList(sqlId);//输出结果studentList.forEach( stu -> System.out.println(stu));//关闭SqlSession对象sqlSession.close();}}
4.3 传统dao类改进
本身
StudentDao类很少用到,主要还是用到了sqlsession的方法,StudentDao类主要是做一个指引的指示
为了封装更好的使用重写这个类的方法
主要区别在于改写接口类的方法,以便在测试类中直接定义,和传统写法保持一致,定义的接口和测试类分隔开
获取数据库,执行sql语句,在测试类进行书写
public class StudentDaoImpl implements StudentDao {@Overridepublic List<Student> selectStudents() {//获取SqlSession对象//通过封装类进行执行SqlSession sqlSession = MyBatisUtils.getSqlSession();//主要是这个sql语句String sqlId="com.bjpowernode.dao.StudentDao.selectStudents";//执行sql语句, 使用SqlSession类的方法List<Student> students = sqlSession.selectList(sqlId);//关闭sqlSession.close();return students;}@Overridepublic 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;}
}
测试类的定义
通过调用执行类
在调用执行类的方法
public class TestMyBatis {@Testpublic void testSelectStudents(){//com.bjpowernode.dao.StudentDaoStudentDao dao = new StudentDaoImpl();List<Student> studentList = dao.selectStudents();for(Student stu:studentList){System.out.println(stu);}}@Testpublic 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);}}
通过以上改写接口类和测试类的代码中,可以看到很多冗余一样的代码,只不过几处不一样而已,其实还可以继续封装
5. 动态代理
关于这部分知识涉及到了jdk的动态代理
可看我之前的文章进行了解
jdk动态代理(AOP)从入门到精通(全)
xml文件定义如下
通过调用执行类来执行xml下的sql文件(也就是映射对象)
StudentDao dao = new StudentDaoImpl();
这个语句调用dao对象,类型是StudentDao,全限定名称是:com.bjpowernode.dao.StudentDao,全限定名称 和 namespace 是一样的。List<Student> studentList = dao.selectStudents();
通过dao中方法的返回值也可以确定MyBatis要调用的SqlSession的方法,也就是查看xml配置文件中的定义
如果返回值是List ,调用的是SqlSession.selectList()方法
如果返回值 int ,或是非List的,看mapper文件中的标签是<insert>,<update> 就会调用SqlSession的insert, update等方法
以此引出动态代理的结构,节省代码量,也就是测试类可以不用这么冗余,也不用定义实现类
- mybatis根据 dao的方法调用,获取执行sql语句的信息
- mybatis根据dao接口,创建dao接口的实现类, 并创建该类的对象,完成SqlSession调用方法, 访问数据库
具体如何创建如何执行
使用mybatis的动态代理机制, 使用SqlSession.getMapper(dao接口),getMapper能获取dao接口对于的实现类对象
mybatis内部通过接口名和方法名映射到对应xml文件中的sql语句执行
将其上面的测试类和实现类合并变成一个
直接调用封装类
具体如下
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);
}
5.1 参数剖析
parameterType
此处也是重点讲解一个参数该如何使用
- 接口中方法参数的类型, 类型的完全限定名或别名
例如:parameterType=“java.lang.Integer”
parameterType=“int” - parameterType不是强制的,mybatis通过反射机制能够发现接口参数的数类型,可以没有,一般不写
主要写在dao.xml的配置文件下
<select id="selectStudentById" parameterType="java.lang.Integer" resultType="com.bjpowernode.domain.Student">select id,name, email,age from student where id=${id}
</select>
或者是
<select id="selectStudentById" parameterType="int" resultType="com.bjpowernode.domain.Student">select id,name, email,age from student where id=${id}
</select>
5.2 深入理解参数
5.2.1 单参数
主要写在dao.xml的配置文件下
<select id="selectStudentById" resultType="com.bjpowernode.domain.Student">select id,name, email,age from student where id=${id}
</select>
具体接口类的定义如下
public Student selectStudentById(Integer id)
使用#{}
之后, mybatis执行sql是使用的jdbc中的PreparedStatement
对象
由mybatis执行下面的代码:
- mybatis创建Connection , PreparedStatement对象
String sql="select id,name, email,age from student where id=?";
PreparedStatement pst = conn.preparedStatement(sql);
pst.setInt(1,1001);
- 执行sql封装为resultType="com.bjpowernode.domain.Student"这个对象
ResultSet rs = ps.executeQuery();
Student student = null;
while(rs.next()){//从数据库取表的一行数据, 存到一个java对象属性中
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; //给了dao方法调用的返回值
5.2.2 多参数
@Param
多个参数: 命名参数,在形参定义的前面加入 @Param("自定义参数名称")
xml文件的定义
<!--多个参数,使用@Param命名-->
<select id="selectMultiParam" resultType="com.bjpowernode.domain.Student">select id,name, email,age from student where name=#{myname} or age=#{myage}
</select>
dao类接口的定义
List<Student> selectMultiParam(@Param("myname") String name,@Param("myage") Integer age);
具体测试类的书写如下
@Test
public void testSelectMultiParam(){SqlSession sqlSession = MyBatisUtils.getSqlSession();StudentDao dao = sqlSession.getMapper(StudentDao.class);List<Student> students = dao.selectMultiParam("李四",20);for(Student stu: students){System.out.println("学生="+stu);}sqlSession.close();
}
使用对象
使用java对象作为接口中方法的参数
List<Student> selectMultiStudent(Student student);
使用java对象的属性值,作为参数实际值
使用对象语法: #{属性名,javaType=类型名称,jdbcType=数据类型}
很少用。
- javaType:指java中的属性数据类型。
- jdbcType:在数据库中的数据类型。
例如: #{paramName,javaType=java.lang.String,jdbcType=VARCHAR}
我们使用的简化方式: #{属性名} ,javaType, jdbcType的值mybatis反射能获取。不用提供
很少使用
<select id="selectMultiObject" resultType="com.bjpowernode.domain.Student">select id,name, email,age from student wherename=#{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 wherename=#{paramName} or age=#{paramAge}
</select>
测试类的代码
@Test
public void testSelectMultiStudent(){SqlSession sqlSession = MyBatisUtils.getSqlSession();StudentDao dao = sqlSession.getMapper(StudentDao.class);Student student = new Student();student.setName("张三");student.setAge(28);List<Student> students = dao.selectMultiStudent(student);for(Student stu: students){System.out.println("学生="+stu);}sqlSession.close();
}
按照位置
不推荐,不是很灵活
- mybatis.3.4之前,使用
#{0} ,#{1}
- mybatis。3.4之后 ,使用
#{arg0} ,#{arg1}
List<Student> selectMultiPosition( String name,Integer age);
xml文件的定义
<select id="selectMultiPosition" resultType="com.bjpowernode.domain.Student">select id,name, email,age from student wherename = #{arg0} or age=#{arg1}
</select>
直接在测试类的时候一一对应进行输入
@Test
public void testSelectMultiPosition(){SqlSession sqlSession = MyBatisUtils.getSqlSession();StudentDao dao = sqlSession.getMapper(StudentDao.class);List<Student> students = dao.selectMultiPosition("李四",20);for(Student stu: students){System.out.println("学生="+stu);}sqlSession.close();
}
多个参数,使用Map存放多个值
不推荐,不是很灵活
List<Student> selectMultiByMap(Map<String,Object> map);
xml文件的配置
<select id="selectMultiByMap" resultType="com.bjpowernode.domain.Student">select id,name, email,age from student wherename = #{myname} or age=#{age1}
</select>
通过放置一个key值进行一一相应
@Test
public void testSelectMultiByMap(){SqlSession sqlSession = MyBatisUtils.getSqlSession();StudentDao dao = sqlSession.getMapper(StudentDao.class);Map<String,Object> data = new HashMap<>();data.put("myname","张三");data.put("age1",28);List<Student> students = dao.selectMultiByMap(data);for(Student stu: students){System.out.println("学生="+stu);}sqlSession.close();
}
5.2.3 占位符
关于占位符的知识点,可看我之前的文章补充
jdbc之问号占位符的详细分析
对比一下两个占位符#
和 $
- # 的占位符
select id,name, email,age from student where id = #{id}
最后的结果是 select id,name, email,age from student where id =?
- $ 的占位符
select id,name, email,age from student where id = ${id}
最后的结果是 select id,name, email,age from student where id =1001
- $这个占位符使用的是字符串的拼接
使用的是statement对象执行sql,效率比PreparedStatement要低 - $可以替换表名或者列名,如果确定数据安全可以使用这个
具体两者的区别
- # 使用?占位符,使用的是PreparedStatement执行sql,效率高,避免了sql注入,更加安全
- $ 不使用?占位符,使用字符串连接,statement对象执行sql,效率低。有sql注入风险,安全性低。可以替换表名或者列名
所谓的替换列名是这个意思
List<Student> selectUse$Order(@Param("colName") String colName);
xml文件定义如下
<select id="selectUse$Order" resultType="com.bjpowernode.domain.Student">select * from student order by ${colName}
</select>
测试代码如下
@Test
public void testSelectUse$Order(){SqlSession sqlSession = MyBatisUtils.getSqlSession();StudentDao dao = sqlSession.getMapper(StudentDao.class);List<Student> students = dao.selectUse$Order("age");for(Student stu: students){System.out.println("学生="+stu);}sqlSession.close();
}
所谓的数据安全与否
因为是字符串的拼接
所以如果语句结构是这样dao.selectUse$("'李四';select * from user");
引入字符串''
,内容是sql语句,可以实现sql注入修改后台数据,造成数据不安全
5.2.4 总结
回顾一下之前的知识点
大致如下
动态代理:mybatis创建dao接口的实现类,在实现类中调用sqlsession方法执行sql语句
getmapper创建对象的时候本身就是一个jdk动态代理方式
com.sun.proxy.$Proxy2 : jdk的动态代理
之后获取到sqlsession的执行方法,获取其sql语句结构
使用动态代理的方式:
- 获取sqlsession对象
- 使用getmapper方法获取接口对象
- 调用接口方法,执行mapper文件的sql语句
通过debug 剖析其源码
部分截图如下
具体getmapper
5.3 封装mybatis输出结果
5.3.1 resultType
mybatis执行了sql语句,得到java对象
具体执行的思路是
mybatis执行sql语句, 然后mybatis调用类的无参数构造方法,创建对象
mybatis把ResultSet指定列值付给同名的属性
<select id="selectMultiPosition" resultType="com.bjpowernode.domain.Student">select id,name, email,age from student
</select>
在对等的jdbc时
分别通过setId进行配对
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"))
}
- 简单类型
<!--sql执行后返回一行一列-->
<!--<select id="countStudent" resultType="int">-->
<select id="countStudent" resultType="java.lang.Integer">select count(*) from student
</select>
- 对象类型
List<Student> selectMultiParam(@Param("myname") String name,@Param("myage") Integer age);
<!--多个参数,使用@Param命名-->
<select id="selectMultiParam" resultType="com.bjpowernode.domain.Student">select id,name, email,age from student where name=#{myname} or age=#{myage}
</select>
- map类型
只能最多返回一行记录。多余一行是错误
//定义方法返回MapMap<Object,Object> selectMapById(Integer id);
<!--返回Map1)列名是map的key, 列值是map的value2)只能最多返回一行记录。多余一行是错误
-->
<select id="selectMapById" resultType="java.util.HashMap">select id,name,email from student where id=#{stuid}
</select>
具体测试文件如下
//返回Map
@Test
public void testSelecMap(){SqlSession sqlSession = MyBatisUtils.getSqlSession();StudentDao dao = sqlSession.getMapper(StudentDao.class);Map<Object,Object> map = dao.selectMapById(1001);System.out.println("map=="+map);
}
5.3.2 别名
再mybatis.xml配置文件中定义别名的配置
之后就可以直接使用自已定义的实体类的全限定名称的别名
第一种方式(可读性很差,很少使用)
可以指定一个类型一个自定义别名
- type:自定义类型的全限定名称
- alias:别名
<typeAliases><typeAlias type="com.bjpowernode.domain.Student" alias="stu" /><typeAlias type="com.bjpowernode.vo.ViewStudent" alias="vstu" />
</typeAliases>
第二种方式(很少使用,会出错)
<package>
name是包名, 这个包中的所有类,类名就是别名(类名不区分大小写)
<!--定义别名-->
<typeAliases><package name="com.bjpowernode.domain"/><package name="com.bjpowernode.vo"/>
</typeAliases>
最后的类名就是别名
最后一种别名的格式很少使用
因为如果在同一个文件中定义有两个同名类,会不知道引用哪个
5.3.3 resultMap
可以定义多行数据
使用resultMap定义映射关系
List<Student> selectAllStudents();
xml文件的定义
将其property=column 这样赋值
<!--定义resultMapid:自定义名称,表示你定义的这个resultMaptype: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>
具体测试类的定义如下
@Test
public void testSelectAllStudents(){SqlSession sqlSession = MyBatisUtils.getSqlSession();StudentDao dao = sqlSession.getMapper(StudentDao.class);List<Student> students = dao.selectAllStudents();for(Student stu: students){System.out.println("学生="+stu);}sqlSession.close();
}
property 要与实体类的定义一样
而column 要与select 的定义一样
第二种方式是
使用resultType的属性,之后再定义的时候通过
数据库名 id查询 映射到实体类中的的结果 进行辨别
或者直接在数据库中修改别名,和实体类一致就可以使用
<!--列名和属性名不一样:第二种方式resultType的默认原则是 同名的列值赋值给同名的属性, 使用列别名(java对象的属性名)
-->
<select id="selectDiffColProperty" resultType="com.bjpowernode.domain.MyStudent">select id as stuid ,name as stuname, email as stuemail , age stuage from student
</select>
5.4 模糊like
第一种模糊查询, 在java代码指定 like的内容
List<Student> selectLikeOne(String name);
<!--第一种 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();
}
==name就是李值, 在mapper中拼接 like “%” 李 “%” ==
List<Student> selectLikeTwo(String name);
这种方式"%" #{name} "%"
中间一定要带空格
<!--第二种方式:在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();
}
6. 动态sql
6.1 if结构
<if>是判断条件的,语法<if test="判断java对象的属性值">部分sql语句</if>
<if:test=“使用参数java对象的属性值作为判断条件,语法 属性=XXX值”>
//动态sql ,使用java对象作为参数
List<Student> selectStudentIf(Student student);
<select id="selectStudentIf" resultType="com.bjpowernode.domain.Student">select id,name, age, email from studentwhere <if test="name !=null and name !='' ">name = #{name}</if><if test="age > 0">or age > #{age}</if>
</select>
测试代码如下
@Test
public void testSelectStudentIf(){SqlSession sqlSession = MyBatisUtils.getSqlSession();StudentDao dao = sqlSession.getMapper(StudentDao.class);Student student = new Student();student.setName("李四");student.setAge(20);List<Student> students = dao.selectStudentIf(student);for(Student stu:students){System.out.println("if==="+stu);}
但是这种写法有缺陷
如果第一个if不满足了,第二个if 前面会带一个or结构 变成where or 就不对了
为了避免这种规则
可以这样书写xml文件
在前面的条件加上恒等式或者本身属性就会成立的条件
where 1=1
<if test="name !=null and name !='' ">
and name = #{name}
6.2 where结构
当多个if有一个成立的, <where>
会自动增加一个where关键字,并去掉 if中多余的 and ,or等
//where使用
List<Student> selectStudentWhere(Student student);
where: <where> <if> <if>...</where>
<select id="selectStudentWhere" resultType="com.bjpowernode.domain.Student">select id,name, age, email from student<where><if test="name !=null and name !='' ">name = #{name}</if><if test="age > 0">or age > #{age}</if></where>
</select>
也就是当其中一个if条件成立的时候 就会有where,如果都没成立,就没有where
成立的时候还会去掉前面的多余的 or 或者and
6.3 foreach结构
添加常用的类型结构
- collection:表示接口中的方法参数的类型, 如果是数组使用array , 如果是list集合使用list
- item:自定义的,表示数组和集合成员的变量
- open:循环开始是的字符
- close:循环结束时的字符
- separator:集合成员之间的分隔符
//foreach 用法 1List<Student> selectForeachOne(List<Integer> idlist);
<!--foreach使用1 , List<Integer>-->
<select id="selectForeachOne" resultType="com.bjpowernode.domain.Student">select * from student where id in<foreach collection="list" item="myid" open="(" close=")" separator=",">#{myid}</foreach></select>
具体拼接测试代码如下
- 添加列表
- 用builder来遍历添加列表的值
重要代码的逻辑思路
@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);}
这种思路在leetcode中的列表拼接很常用
添加对象为类型
//foreach 用法 2
List<Student> selectForeachTwo(List<Student> stulist);
<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 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);}
}
6.4 动态sql
1.先定义 <sql id="自定义名称唯一"> sql语句, 表名,字段等 </sql>
2.再使用, <include refid="id的值" />
<!--定义sql片段-->
<sql id="studentSql">select id,name, age, email from student
</sql>
之后在下边这样定义
<select id="selectStudentIf" resultType="com.bjpowernode.domain.Student"><include refid="studentSql" />where id > 0<if test="name !=null and name !='' ">and name = #{name}</if><if test="age > 0">or age > #{age}</if>
</select>
7. 配置文件
- 定义别名
- 数据源
- mapper 文件
其中定义别名上面已经讲过了这里就回顾一下
<!--定义别名-->
<typeAliases><!--第一种方式:可以指定一个类型一个自定义别名type:自定义类型的全限定名称alias:别名(短小,容易记忆的)--><!--<typeAlias type="com.bjpowernode.domain.Student" alias="stu" /><typeAlias type="com.bjpowernode.vo.ViewStudent" alias="vstu" />--><!--第二种方式<package> name是包名, 这个包中的所有类,类名就是别名(类名不区分大小写)--><package name="com.bjpowernode.domain"/><package name="com.bjpowernode.vo"/>
</typeAliases>
7.1 数据库配置
数据库的属性配置文件: 把数据库连接信息放到一个单独的文件中。 和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>
指定文件的位置
在需要使用值的地方, ${key}
jdbc的配置文件
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/springdb
jdbc.user=root
jdbc.passwd=123456
xml文件配置
<!--指定properties文件的位置,从类路径根开始找文件-->
<properties resource="jdbc.properties" />
具体的下面的配置文件这么定义
具体链接数据库文件的注释如下
<environments default="mydev"><environment id="mydev"><!--transactionManager:mybatis提交事务,回顾事务的方式type: 事务的处理的类型1)JDBC : 表示mybatis底层是调用JDBC中的Connection对象的,commit, rollback2)MANAGED : 把mybatis的事务处理委托给其它的容器(一个服务器软件,一个框架(spring))--><transactionManager type="JDBC"/><!--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></environment>
</environments>
7.2 mapper位置
mapper(sql映射文件)的位置
- 第一种方式:指定多个mapper文件
<!-- sql mapper(sql映射文件)的位置-->
<mappers><mapper resource="com/bjpowernode/dao/StudentDao.xml"/><mapper resource="com/bjpowernode/dao/OrderDao.xml" />
</mappers>
- 第二种方式: 使用包名
name: xml文件(mapper文件)所在的包名, 这个包中所有xml文件一次都能加载给mybatis使用package的要求:
- mapper文件名称需要和接口名称一样, 区分大小写的一样
- mapper文件和dao接口需要在同一目录
<!-- sql mapper(sql映射文件)的位置-->
<mappers><package name="com.bjpowernode.dao"/><!-- <package name="com.bjpowernode.dao2"/><package name="com.bjpowernode.dao3"/>-->
</mappers>
8. PageHelper
分页的功能
添加依赖包
<!--PageHelper依赖-->
<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>5.1.10</version>
</dependency>
在mybatis.xml下添加插件
这个插件的功能类似数据库关键字中的limit
<!--配置插件-->
<plugins><plugin interceptor="com.github.pagehelper.PageInterceptor" />
</plugins>
通过一个方法测试使用
//使用PageHelper分页数据
List<Student> selectAll();
<!--查询所有-->
<select id="selectAll" resultType="com.bjpowernode.domain.Student">select * from student order by id
</select>
具体的测试代码如下
@Test
public void testSelectAllPageHelper(){SqlSession sqlSession = MyBatisUtils.getSqlSession();StudentDao dao = sqlSession.getMapper(StudentDao.class);//加入PageHelper的方法,分页// pageNum: 第几页, 从1开始// pageSize: 一页中有多少行数据PageHelper.startPage(1,3);List<Student> students = dao.selectAll();for(Student stu:students){System.out.println("foreach--one ==="+stu);}
}
Mybatis从入门到精通(全)相关推荐
- MyBatis从入门到精通(1):MyBatis入门
作为一个自学Java的自动化专业211大学本科生,在学习和实践过程中"趟了不少雷",所以有志于建立一个适合同样有热情学习Java技术的参考"排雷手册". 最近在 ...
- MyBatis从入门到精通(一):MyBatis入门
最近在读刘增辉老师所著的<MyBatis从入门到精通>一书,很有收获,于是将自己学习的过程以博客形式输出,如有错误,欢迎指正,如帮助到你,不胜荣幸! 1. MyBatis简介 2001 ...
- Mybatis从入门到精通二(入门详解)
Mybatis从入门到精通二(想学Mybatis,看了这一篇你就不需要其他的了) 本课程分为两天第一天的请参考: https://blog.csdn.net/weixin_43564627/artic ...
- MyBatis从入门到精通(二):MyBatis XML方式的基本用法之Select
最近在读刘增辉老师所著的<MyBatis从入门到精通>一书,很有收获,于是将自己学习的过程以博客形式输出,如有错误,欢迎指正,如帮助到你,不胜荣幸! 1. 明确需求 书中提到的需求是一个基 ...
- Mybatis从入门到精通下篇
Mybatis从入门到精通下篇: 输入类型: 输出类型: ResultMap: 动态sql: if标签: where标签: sql片段: foreach标签: 关联查询: 以订单作为主体: 一对一查询 ...
- Mybatis从入门到精通读书笔记
Mybatis从入门到精通 resultMap resultMap简介 resultMap resultMap简介 P25-P26
- MyBatis从入门到精通 PDF 完整版
给大家带来的一篇关于MyBatis相关的电子书资源,介绍了关于MyBatis.入门到精通方面的内容,本书是由电子工业出版社出版,格式为PDF,资源大小116.8 MB,刘增辉编写,目前豆瓣.亚马逊.当 ...
- Mybatis从入门到精通上篇
Mybatis从入门到精通上篇: 学习过的持久层框架:DBUtils , Hibernate Mybatis就是类似于hibernate的orm持久层框架. Mybatis介绍: Mybatis是面向 ...
- MyBatis从入门到精通(三):MyBatis XML方式的基本用法之多表查询
最近在读刘增辉老师所著的<MyBatis从入门到精通>一书,很有收获,于是将自己学习的过程以博客形式输出,如有错误,欢迎指正,如帮助到你,不胜荣幸! 1. 多表查询 上篇博客中,我们示例的 ...
最新文章
- python使用matplotlib可视化饼图(pie plot)、可视化嵌套的环形饼图(Nested circular pie chart)
- jpa-和-mybatis创建的事物管理器名称
- 如何用TensorFlow和TF-Slim实现图像分类与分割
- tcp三次握手四次挥手(及原因)详解
- 神经网络优化(二) - 滑动平均
- 一般绘CAD图用计算机配置,cad图形界限一般是多少
- 【Qt】使用QProcess调用其它程序或脚本
- parse_str 相反函数
- 优酷路由宝 OpenWrt 刷机
- linux安装文泉驿字体,centos 安装文泉驿字体相关教程
- 贝叶斯分析之利用线性回归模型理解并预测数据(三)
- Python 实现一个自动下载小说的简易爬虫
- 微型计算机存储容量2mb,在微型计算机中,存储容量为2MB是指
- 涉案资金超10亿,又一洗钱团伙被端,“二清”警钟不能忘
- Geometric Transformation(几何变换)
- 详解C++学习方向和就业方向!
- obj转stl_STL转STP的方法视频教程,OBJ格式转STP或者IGS开模具格式的过程,STL转STP软件介绍...
- Facebook广告投放:什么是Cloak,Cloak的原理以及主流Cloak程序介绍
- Nginx添加腾讯安全HTTPS证书
- win10打开蓝牙_双系统共用蓝牙键鼠(win10+macOS)
热门文章
- NLP数据增强;中文数据增强包;一键中文数据增强
- 关于HTML中常用选择器
- 二分法(yxc讲解+模板整理)
- aws云服务器会自动扣费吗,AWS云服务免费套餐竟然扣钱了?可能是因为你的region没管好...
- Git的4 个阶段的撤销更改(通俗易懂)
- 阻碍你成功的五个不良习惯
- Mac下解决v2端口被占用,shadowsocket(ss)程序残留问题
- ora.eons offline
- Ext3、Ext4、FAT、FAT32、NTFS、exFAT、Sparse、Raw
- Elasticsearch6.4专题之16:Ingest Node