MyBatis学习笔记
1.框架概述
MVC模式(Model–view–controller)是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller)。
1.1 目前一般采用以下三层架构
- 界面层: 和用户打交道的, 接收用户的请求参数, 显示处理结果的。在实现代码中,界面层的代码一般放置于controller包中。
- 业务逻辑层: 接收了界面层传递的数据,计算逻辑,调用数据库,获取数据。在实现代码中,业务逻辑层的代码一般放置于service包中(XXXService类)。
- 数据访问层(持久层): 就是访问数据库, 执行对数据的查询,修改,删除等等的。在实现代码中,数据访问层的代码一般放置于dao包中(XXXDao类)。
1.2 三层中各个类的交互方式
用户使用界面层 --> 业务逻辑层 ---> 数据访问层(持久层)--> 数据库(mysql)
1.3 三层对应的处理框架
- 界面层---springmvc(框架)
- 业务逻辑层---service类--spring(框架)
- 数据访问层---dao类--mybatis(框架)
这三层对应的框架便是非常著名的SSM三件套。利用SpringMVC接收用户请求,响应结果。利用Spring管理service类。利用mybatis代替jdbc访问数据库,所以mybatis可以看成是功能更加完善的jdbc。
1.4 三个框架简介
MyBatis框架:
MyBatis是一个优秀的基于java的持久层框架,内部封装了jdbc,开发者只需要关注sql语句本身,而不需要处理加载驱动、创建连接、创建statement、关闭连接,资源等繁杂的过程。MyBatis通过xml或注解两种方式将要执行的各种sql语句配置起来,并通过java对象和sql的动态参数进行映射生成最终执行的sql语句,最后由 mybatis框架执行sql并将结果映射为java对象并返回。开发人员使用MyBatis的流程如下:
开发人员提供sql语句 ---> mybatis处理sql ---> 开发人员得到List集合或java对象(表中的数据)
Spring框架:
Spring框架为了解决软件开发的复杂性而创建的。Spring使用的是基本的JavaBean来完成以前非常复杂的企业级开发。Spring解决了业务对象,功能模块之间的耦合,不仅在javase,web中使用,大部分Java应用都可以从Spring中受益。Spring是一个轻量级控制反转(IoC)和面向切面(AOP)的容器。
SpringMVC框架
SpringMVC属于SpringFrameWork 3.0 版本加入的一个模块,为Spring框架提供了构建Web应用程序的能力。现在可以Spring框架提供的SpringMVC模块实现web应用开发,在web项目中可以无缝使用Spring和SpringMVC框架。
1.5 MyBatis功能
MyBatis是一个sql映射框架,提供对数据库的操作能力。可以理解为是增强的JDBC。其主要有两个功能
sql mapper
:sql映射功能,可以把数据库表中的一行数据映射为一个java对象。操作这个对象,就相当于操作表中的数据Data Access Objects(DAOs)
: 数据访问功能, 可以对数据库进行增删改查等操作。
2.MyBatis框架快速入门
2.1 MyBatis查询数据库操作
MyBatis的基本使用步骤如下:
-
1.在数据库中新建student表
-
2.在Maven中加入mybatis和mysql的相关依赖
-
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>5.3.8</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.3.8</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.7</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>2.0.6</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.25</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.1</version> </dependency>
-
-
3.创建实体类:student,用于保存数据库中student表中对应的一行数据。一般实体类在实现代码中都放在entity包中。
-
4.创建持久层的dao接口,定义操作数据库的方法(只需要声明方法即可)
-
package com.sysu.dao; import com.sysu.entity.Student; import java.util.List; public interface StudentDao { public List<Student> selectStudents(); }
-
-
5.创建一个mybatis使用的配置文件:sql映射文件(一个xml文件,文件内容如下),然后在映射文件中写sql语句,一般一个表对应一个sql映射文件。
-
xml文件应该创建在接口所在的目录中,同时最好保证文件名称和接口名字一致。
-
<!-- sql映射文件:用于写sql语句的,mybatis会执行这些sql语句。 1.指定约束文件 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:命名空间,namespace对应的值必须使用dao接口的全限定名称 <mapper namespace="dao接口对应的全限定名称"> 4.在xml文件中,可以使用特定的标签来表示数据库中的特定操作。 <select>:表示执行查询操作 <select id = "接口中对应的方法名称" resultType="sql语句执行结果的对象类型对应的全限定名称"> <update>:表示更新数据库的操作 <insert>:表示插入 <delete>:表示删除 5.namespace与id就是帮助MyBatis框架定位sql语句对应的方法,所以需要使用dao接口的全限定名。 --> <?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.sysu.dao.StudentDao"> <select id="selectStudents" resultType="com.sysu.domain.Student"> select id,name,email,age from student order by id </select> </mapper>
-
-
6.创建mybatis的主配置文件:主配置文件提供了数据库的连接信息和sql映射文件的位置信息,一般一个项目对应一个主配置文件。配置文件内容如下:
-
<!-- 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>根标签,该标签通常包括两部分: <environments>:数据库的连接信息 <mappers>:sql映射文件的位置(相对于main/java而言) --> <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!-- environments是复数,表示可以管理多个数据库的连接信息,所以default的值必须与其中一个的<environment id="">相同--> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <!-- transactionManager用于定义提交事务、回滚事务的方式。type有两种取值: (1)JDBC:表示mybatis底层调用JDBC中的Connection对象进行事务的处理 (2)MANAGED:将mybatis的事务处理委托给其他容器(例如spring等)--> <dataSource type="POOLED"> <!-- type:指定数据连接的类型 (1)POOLED:使用连接池 (2)UNPOOLED:不使用连接池,每次执行sql语句都新建连接,执行完sql语句后在关闭连接。--> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/ssm"/> <property name="username" value="root"/> <property name="password" value="123456"/> <!-- 通常情况下需要把数据库的连接信息放到一个单独的文件中,这个文件一般称为属性配置文件。--> </dataSource> </environment> </environments> <mappers> <!-- 相对于main/java 以及 main/resouces的路径 --> <!-- https://www.cnblogs.com/zhangxiaolei0/p/14370656.html --> <mapper resource="com/sysu/dao/StudentDao.xml"/> </mappers> </configuration>
-
-
7.获取SqlSession对象,通过它的方法执行sql语句。
-
public class myapp { public static void main(String[] args) throws IOException { //1.定义mybatis主配置文件的名称,从类路径开始(target/classes),如果target/classes路径下没有mybatis.xml,则说明mvn compile命令执行不完善,可以手动将mybatis.xml文件复制一份到target/classes目录下。 //通常情况下都会把12345这五个步骤封装至utils中。 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.从SqlSessionFactory对象中获取SqlSession对象,可以根据openSession()传入的参数自定义是否自动提交事务,openSession(true)表示自动提交事务。 SqlSession sqlSession = factory.openSession(); //67本质是StudentDao接口中selectStudents()方法的实现,该部分代码在后期可以省略,因为根据MyBatis动态代理可以达到同样的效果。 //6.【自定义】指定要执行的sql语句标识 String sqlId = "com.bjpowernode.dao.StudentDao.selectStudents"; //7.【自定义】执行sql语句,得到执行结果 List<Student> studentList = sqlSession.selectList(sqlId); for(Student st : studentList) System.out.println(st); sqlSession.close(); //上述代码执行查询操作,当执行insert、update、delete等操作时候一定要主动提交事务,否则数据库中的数据不改变. //sqlSession.commit(); ------------------------------------------------------------------------------ //动态代理的实现方式如下: //StudentDao dao = sqlSession.getMapper(StudentDao.class); //List<Student> students = dao.selectStudents(); //for(Student student : students) System.out.println(student); } }
-
第七个步骤 “获取SqlSession对象,通过它的方法执行sql语句",该步骤有两种实现方式:
- 传统Dao开发模式:实现StudentDao接口中的方法,并使用这些方法对数据库进行操作。
- MyBatis动态代理模式(必须掌握):MyBatis动态代理可以让我们省去实现StudentDao接口中的方法这一步骤,它会直接定位到映射文件 mapper 中的相应 SQL 语句,对DB进行操作。底层是通过反射进行实现的。
//动态代理的实现方式如下:
获取SqlSession对象
SqlSession sqlSession = factory.openSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
List<Student> students = dao.selectStudents();
for(Student student : students) System.out.println(student);
2.2 MyBatis Insert操作(使用动态代理)
MyBatis初始化的时候比较麻烦,日后在和数据库打交道就比较简单了。
- 1.在dao接口中定义操作数据库的方法(只需要声明方法即可)
package com.sysu.dao;
import com.sysu.entity.Student;
import java.util.List;
public interface StudentDao {
public List<Student> selectStudents();
//定义insert插入方法,该方法只有一个参数Student,所以在sql映射文件中不需要写parameterType=”“参数
//如果方法中有多个参数需要使用@Param命名参数(见3.3.2)
public int insertStudent(Student student);
}
- 2.在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.sysu.dao.StudentDao">
<select id="selectStudents" resultType="com.sysu.entity.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>
- 3.获取SqlSession对象,通过MyBatis动态代理实现对数据库的访问与操作。
package com.sysu;
import com.sysu.entity.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 {
//通常把下面4个步骤封装至utils包中,用于获取SqlSession对象
String config = "mybatis.xml";
InputStream in = Resources.getResourceAsStream(config);
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
//获取SqlSession对象
SqlSession sqlSession = factory.openSession();
//创建需要插入的student对象
Student student = new Student();
student.setId(1003);
student.setName("王五");
student.setEmail("ddd@qq");
student.setAge(35);
//Mybatis动态代理
StudentDao dao = sqlSession.getMapper(StudentDao.class);
int ans = dao.insertStudent(student);
System.out.println(ans);
}
}
3.MyBatis框架Dao代理(※)
3.1 实现步骤
实现步骤见2.1和2.2。或者见下图
3.2 实现原理
动态代理。
有关动态代理的内容见链接:动态代理
https://www.cnblogs.com/jia0504/p/13811424.html
3.3 MyBatis相关参数的理解
(1)parameterType
<?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.sysu.dao.StudentDao">
<select id="selectStudentById" parameterType="int" resultType="com.sysu.entity.Student">
select id,name,email,age from student where id = #{id}
</select>
</mapper>
parameterType表示StudentDao接口中方法参数的数据类型。parameterType不是强制的,mybatis通过反射机制能够发现接口参数的数据类型。所以可以没有。一般我们也不写。
例如StudentDao接口中存在方法:public Student selectStudentById(Integer id)
,则 parameterType="int"
在sql映射文件中,可以通过#{“任意字符”}获取简单类型的一个参数的值。例如通过#{id}获取selectStudentById(Integer id)方法中传入的id值。
实现原理如下:首先需要知道MyBatis就是对JDBC的一个封装
(1) MyBatis创建Connection以及PreparedStatement对象
String sql = “select id,name,email,age from student where id = ?”
PreparedStatement pst = conn.preparedStatement(sql);
// 一个问好就相当于一个占位符,setInt传入第一个参数
pst.setInt(1,1001);
(2) 执行sql封装为Student对象。
Resultset rs = ps.executeouery();student student = null;
while(rs.next()){
//从数据库取表的一行数据,存到一个java对象属性中ltudent = new student();
student.setId(rs.getInt("id));
student.setName(rs.getstring( "name" ));
student.setEmail(rs.getstring( "email"));
student.setAge(rs.getInt("age"));
}
return sfudent;
当我们在sql映射文件中写sql语句时,底层的实现原理就如(1)(2)两个步骤,所以可以认为MyBatis就是对JDBC进行了封装。
(2)@Param命名参数
在sql映射文件中,有两种常用的方法可以获取多个参数的值。
-
@Param
命名参数获取多个参数的值使用方法:在dao接口声明的方法中加入@Param(“自定义参数名称”),然后在sql映射文件使用#{“自定义参数名称”}。
例如dao接口存在selectMulitParam()方法:
步骤一:public ListselectMulitParam(@Param("myname") String name, @Param("myage") Integer age)
步骤二:对应sql映射文件为:
-
通过传递类型为Java对象的参数来获取多个参数的值(其实insert的sql语句就是采用这种方式)
使用方法:在dao接口声明的方法中加入Java对象,然后在sql映射文件使用#{“对象的属性名”}。
步骤一:public List<Student> selectMulitParam(Student)
步骤二:对应sql映射文件为:
<select>
select * from student where name=#{name} or age=#{age}
</select>
3.4 #和$的区别
首先需要明白:在sql映射文件中无论是使用“#”还是“$",都能正常工作!!
#:占位符,告诉mybatis使用实际的参数值代替。并使用PrepareStatement对象执行sql语句,#{"自定义字符"}代替 sql 语句的“?”。
这样做更安全,更迅速,通常也是首选做法。
sql映射文件
<select id="selectById" resultType = "com.sysu.entiy.Student">
select id,name,email,age from student where id = #{studentId}
</select>
转为 MyBatis 的执行是:
String sql=” select id,name,email,age from student where id = ?”;
PreparedStatement ps = conn.prepareStatement(sql);
ps.setInt(1,1005);
where id=? 就是 where id = #{studentId}
ps.setInt(1,1005) , 1005 会替换掉 #{studentId}
$:主要用于替换表名或者列名。具体实例如下:
1.dao接口文件中声明方法:
List<Student> selectUse$Order(@Param("colName") String colName);
2.sql映射文件写sql语句
<select id="selectUse$Order" resultType = "com.sysu.entiy.Student">
select * from student order by ${colName}
</select>
3.MyBatis动态代理实现与数据库的交互
SqlSession sqlSession = MyBatisUtils.getSqlSesson();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
// 根据name这一列的属性值进行排序
List<Student> students = dao.selectUse$Order("name")
两者的区别如下:
1. #使用?在sql语句中做占位符, 使用PreparedStatement执行sql,效率高。能避免sql注入,更安全。
2. $不使用占位符,表示字符串的连接,使用Statement对象执行sql,效率低。有sql注入的风险,缺乏安全性。
3. $主要用于替换表名或者列名,一般在数据需要根据某个列属性进行排序的场景下使用。
3.5 MyBatis的输出结果
MyBatis的输出结果为Java对象,MyBatis通过使用resultType以及resultMap两种参数让MyBatis明白sql语句执行结果需要转换的对象类型。
(1) resultType
表示sql语句的执行结果需要转换的Java对象类型。
public Student selectStudentById(@Param("id") Integer id);
<!-- resultType=Student,表示sql语句的执行结果需要转换为Student对象 -->
<select id="selectStudentById" parameterType="int" resultType="com.sysu.entity.Student(Student类型的全限定名称)">
select id,name,email,age from student where id = #{id}
</select>
- resultType的值可以看成是dao接口中方法的返回类型。它的值有两种:1. 类型的全限定名称(推荐)。 2. 类型的别名, 例如 java.lang.Integer别名是int
- 实现原理:把同名列的值赋给resultType中指定对象的同名属性,例如:查询结果id列的值赋给Student中的id属性,name列的值赋给Student中的name属性。这一过程是通过对象的get、set方法实现的,因此对象中一定要实现get、set方法。
public List<Student> selectStudents();
<select id="selectStudents" parameterType="int" resultType="com.sysu.entity.Student">
select id,name,email,age from student
</select>
这种情况下resultType不能等于List,因为列值id,name,email,age这些是Student对象的属性,而不是List对象的属性。
(2) resultMap
MyStudent类的定义
class MyStudent{
Integer Myid;
String Myname;
String Myemail;
Integer Myage;
}
dao接口中定义的方法:public List<MyStudent> selectStudents();
sql映射文件:
<select id="selectStudents" parameterType="int" resultType="com.sysu.entity.MyStudent">
select id,name,email,age from student
</select>
当列名(id,name,email,age)和对象中的属性名(Myid、Myname、Myemail、Myage)不一样时,使用resultType将会得到null的对象,解决方案:
- 使用别名
修改sql映射文件
<select id="selectStudents" parameterType="int" resultType="com.sysu.entity.MyStudent">
select id as Myid, name as Myname, email as Myemail, age as Myage from student
</select>
- 使用resultMap
resultMap可以自定义sql执行结果的列名和 对象中的属性名之间映射关系。常用在列名和 java 对象属性名不一样的情况。
使用方式:
1.在sql映射文件中定义resultMap,指定列名和属性的对应关系。
<!-- 创建 resultMap
id:自定义的唯一名称,在<select>使用
type:期望转为的 java 对象的全限定名称或别名
-->
<resultMap id="MyStudentMap" type="com.sysu.entity.MyStudent">
<!-- 主键字段使用 id -->
<!-- 将id列的值映射至对象中的Myid属性 -->
<id column="id" property="Myid" />
<!--非主键字段使用 result-->
<!-- 将name列的值映射至对象中的Myname属性 -->
<result column="name" property="Myname"/>
<result column="email" property="Myemail"/>
<result column="age" property="Myage" />
</resultMap>
2.在中把 resultType 替换为 resultMap。
<!--resultMap: resultMap 标签中的 id 属性值-->
<select id="selectUseDiffResultMap" resultMap="MyStudentMap">
select id,name,email,age from student where name=#{queryName} or age=#{queryAge}
</select>
3.6 like模糊查询
MyBatis有两种方式实现like模糊查询
- 1. java代码中给查询数据加上“%” (最常用)
接口方法:
List<Student> selectLikeFirst(String name);
sql映射文件(mapper文件):
<select id="selectLikeFirst" resultType="com.sysu.entity.Student">
<!-- #{}:表示dao接口中对应的方法需要传入一个参数 -->
select id,name,email,age from student where name like #{studentName}
</select>
测试方法:
@Test
public void testSelectLikeOne(){
String name="%李%";
List<Student> stuList = studentDao.selectLikeFirst(name);
for(Student stu : stuList) ystem.out.println(stu);
}
- 2.在mapper文件sql语句的条件位置加上“%”
接口方法:
List<Student> selectLikeSecond(String name);
mapper 文件:
<select id="selectLikeSecond" resultType="com.sysu.entity.Student">
select id,name,email,age from student where name like "%" #{studentName} "%"
</select>
测试方法:
@Test
public void testSelectLikeSecond(){
String name="李";
List<Student> stuList = studentDao.selectLikeSecond(name);
for(Student stu : stuList) ystem.out.println(stu);
}
4.MyBatis框架动态SQL(※)
动态sql: sql的内容是变化的,可以根据条件获取到不同的sql语句。主要是where部分发生变化。MyBatis主要通过这三个常用标签实现动态sql:<if>
、<where>
、<foreach>
4.1 if 标签
<if>
标签用于条件判断,当条件判断为true时,会将其包含的sql片段拼接到其所在的sql语句中。
<if test = "条件">
部分sql语句
</if>
1.dao接口声明的方法如下:
public List<Student> selectStudentIf(Student student);
2.sql映射文件内容如下:
<!--
<if test = "使用参数Java对象的属性值作为判断条件,所以要使用动态sql,dao接口方法中传入的参数必须是Java对象">
-->
<select id = "selectStudentIf" resultType = "com.sysu.entity.Student">
select id,name,email,age from student
where 1 = 1(防止出现语法错误)
<if test = "name != null and name != ''">
name = #{name}
</if>
<if test = "age > 0">
or age > #{age}
</if>
</select>
3.test测试
@Test
public void testSelectStudentIf(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
Student dao = sqlSession.getMapper(StudentDao.class);
Student student = new Student();
student.setName("abc");
student.setAge(18);
List<Student> students = dao.selectStudentIf(student);
for(Student stu:students) System.out.println(stu);
}
此代码段的含义为:在数据中查找所有名字为“abc”或者年龄大于18的数据。
4.2 where标签
<if>
标签的中存在一个比较麻烦的地方:需要在 where 后手工添加 1=1 的子句。因为,若where后的所有条件均为 false,而 where 后若又没有 1 = 1 子句,则 SQL 中就会只剩下一个空的 where,SQL出错。所以,在where后,需要添加永为真子句1 = 1,以防止这种情况的发生。但当数据量很大时,会 严重影响查询效率。- 通过使用
<where>
标签可以避免产生此类问题,<where>
标签通常用来包含多个<if>
标签,当多个<if>
标签中有一个成立的,<where>
会自动增加一个where关键字,并去掉<if>
标签中sql语句多余的and ,or等。当没有<if>
标签成立,则不会添加where子句。
<where>
<if test=""></if>
<if test=""></if>
</where>
dao接口声明的方法:
List<Student> selectStudentWhere(Student student);
sql映射文件
<select id="selectStudentWhere" resultType="com.sysu.entity.Student">
select id,name,email,age from student
<where>
<if test = "name != null and name != ''">
name = #{name}
</if>
<if test = "age > 0">
or age > #{age}
</if>
</where>
</select>
测试方法:
@Test
public void testSelectWhere() throws IOException {
SqlSession sqlSession = MyBatisUtils.getSqlSession();
Student dao = sqlSession.getMapper(StudentDao.class);
Student param = new Student();
param.setName("abc");
param.setAge(18);
List<Student> studentList = studentDao.selectStudentWhere(param);
for(Student stu:students) System.out.println(stu);
}
此代码段的含义为:在student表中查找所有名字为“abc”或者年龄大于18的数据。如果两个条件都不满足,则输出student表中的全部数据。
4.3 foreach标签
<foreach>
标签用于实现对于数组与集合的遍历,一般用于dao接口文件中声明的方法的传入参数为数组或者集合。- 主要用在sql的in语句中。
select * from student where id in (1001,1002,1003)
使用语法:
<foreach collection="" item="" open="" close="" separator="">
#{item的值}
</foreach>
collection:表示接口中的方法参数的类型,如果是数组使用array, 如果是list集合使用list,集合的大小用 list.size()表示。
item:自定义的,表示数组和集合成员的变量
open:循环开始的字符
close:循环结束的字符
separator:集合成员之间的分隔符
因为foreach一般用于sql中的in语句,所以open="(" close=")" separator=","
遍历List<简单类型>
需求:输出学生id为1002,1005,1006的学生信息。
接口方法:
List<Student> selectStudentForList(List<Integer> idList);
sql映射文件
<select id = "selectStudentForList" resultType = "com.sysu.entity.Student">
select id,name,email,age from student
<if test="list != null and list.size() > 0">
where id in
<foreach collection="list" item="stu" open="(" close=")" separator=",">
#{stu}
</foreach>
</if>
</select>
测试方法:
@Test
public void testSelectForList() {
SqlSession sqlSession = MyBatisUtils.getSqlSession();
Student dao = sqlSession.getMapper(StudentDao.class);
List<Integer> list = new ArrayList<>();
list.add(1002);
list.add(1005);
list.add(1006);
List<Student> studentList = studentDao.selectStudentForList(list);
for(Student stu:students) System.out.println(stu);
}
遍历List<对象类型>
需求:输出学生id为1002,1005的学生信息。
接口方法:
List<Student> selectStudentForList(List<Student> idList);
sql映射文件
<select id = "selectStudentForList" resultType = "com.sysu.entity.Student">
select id,name,email,age from student
<if test="list != null and list.size() > 0">
where id in
<foreach collection="list" item="stu" open="(" close=")" separator=",">
#{stu.id}
</foreach>
</if>
</select>
测试方法:
@Test
public void testSelectForList() {
SqlSession sqlSession = MyBatisUtils.getSqlSession();
Student dao = sqlSession.getMapper(StudentDao.class);
List<Student> list = new ArrayList<>();
Student s1 = new Student();
s1.setId(1002)
list.add(s1);
s1 = new Student();
s1.setId(1005);
list.add(s1);
List<Student> studentList = studentDao.selectStudentForList(list);
for(Student stu:students) System.out.println(stu);
}
4.4 sql标签
<sql>
标签用于定义 SQL 片断,以便其它SQL标签可以复用定义好的片段。- 其它标签使用该 SQL 片断,需要使用
<include>
标签。 <sql>
标签可以定义 SQL 语句中的任何部分,所以子标签可以放在动态 SQL 的任何位置。
先定义:<sql id="自定义名称唯一"> 可以是sql语句、表名、字段名等 </sql>
再使用:<include refid="id的值"/>
接口方法:
List<Student> selectStudentSqlFragment(List<Student> stuList);
sql映射文件:
<!--创建 sql 片段 id:片段的自定义名称-->
<sql id="studentSql">
select id,name,email,age from student
</sql>
<select id="selectStudentSqlFragment" resultType="com.sysu.entity.Student">
<!-- 引用 sql 片段 -->
<include refid="studentSql"/>
<if test="list !=null and list.size > 0 ">
where id in
<foreach collection="list" open="(" close=")" item="stuobject"separator=",">
#{stuobject.id}
</foreach>
</if>
</select>
测试方法:
@Test
public void testSelectForList() {
SqlSession sqlSession = MyBatisUtils.getSqlSession();
Student dao = sqlSession.getMapper(StudentDao.class);
List<Student> list = new ArrayList<>();
Student s1 = new Student();
s1.setId(1002)
list.add(s1);
s1 = new Student();
s1.setId(1005);
list.add(s1);
List<Student> studentList = studentDao.selectStudentForList(list);
for(Student stu:students) System.out.println(stu);
}
借助sql标签输出学生id为1002,1005的学生信息。
5.MyBatis配置文件(了解)
MyBatis有两种配置文件:主配置文件以及sql映射文件(mapper文件)
5.1 主配置文件
<!--
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>根标签,该标签通常包括两部分:
<environments>:数据库的连接信息
<mappers>:sql映射文件的位置(相对于main/java而言)
-->
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- environments是复数,表示可以管理多个数据库的连接信息,所以default的值必须与其中一个的<environment id="">相同-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<!-- transactionManager用于定义提交事务、回滚事务的方式。type有两种取值:
(1)JDBC:表示mybatis底层调用JDBC中的Connection对象进行事务的处理
(2)MANAGED:将mybatis的事务处理委托给其他容器(例如spring等)-->
<dataSource type="POOLED">
<!-- type:指定数据连接的类型
(1)POOLED:使用连接池
(2)UNPOOLED:不使用连接池,每次执行sql语句都新建连接,执行完sql语句后在关闭连接。-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/ssm"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
<!-- 通常情况下需要把数据库的连接信息放到一个单独的文件中,这个文件一般称为属性配置文件。-->
</dataSource>
</environment>
</environments>
<mappers>
<!--加载sql映射文件,方式一(主流):-->
<mapper resource="com/sysu/dao/StudentDao.xml"/>
<!--方式二(了解):可以加载com.sysu.dao包中的所有sql映射文件-->
<packge name="com.sysu.dao"/>
</mappers>
</configuration>
主配置文件一般放在resourcs
目录下,且命名为xxx.xml
。主配置文件的具体内容可以见2.1
主配置文件特点:
-
主配置文件中
<configuration>
之间的标签都是有序的,且<configuration>
为根标签-
<property>
:指定属性配置文件的位置 -
<typeAliases>
:配置别名 -
<plugins>
:配置插件 -
<environments>
:定义数据源 -
<mappers>
:定义sql映射文件的位置
-
-
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"
属性配置文件的书写
数据库的属性配置文件: 把数据库连接信息放到一个单独的文件中。 和mybatis主配置文件分开。目的是便于修改,保存,处理多个数据库的信息。
(1) 在resources目录中定义一个属性配置文件,xxxx.properties,例如 jdbc.properties。在属性配置文件中进行数据的定义,格式是key = value。
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql//.....
jdbc.username=root
jdbc.password=123456
(2) 在mybatis的主配置文件中,使用<property>指定属性配置文件的位置,然后在需要使用的地方利用${key}进行值的引入。
5.2 sql映射文件
详细内容见2.1即可。