最近因为项目需要,又重新学习了一下MyBatis,发现好多以前学的都忘得差不多了,而且以前的笔记也没有了,所以自己去网上找资料学习。并且整理下来发到这里,大家一起学习。
视频看的动力节点王鹤老师讲的MyBatis框架,堪称史上最细,老师条理很清晰,讲的真心不错,观看链接点下边
mybatis创建Dao接口的实现类对象, 完成对sql语句的执行。 mybatis创建一个对象代替你的 dao实现类功能。
1)mapper文件中的namespace 一定dao接口的全限定名称
2)mapper文件中 标签的id是dao接口方法名称
使用SqlSession对象的方法 getMapper(dao.class)
例如: 现在有 StudentDao接口。
SqlSession session = MyBatisUtils.getSqlSession(); StudentDao dao = session.getMapper(StudentDao.class); Student student = dao.selectById(1001); //上面代码中 StudentDao dao = session.getMapper(StudentDao.class); 等同于 StudentDao dao = new StudentDaoImpl();
理解参数是: 通过java程序把数据传入到mapper文件中的sql语句。 参数主要是指dao接口方法的形参
parameterType:表示参数的类型, 指定dao方法的形参数据类型。 这个形参的数据类型是给mybatis使用。 mybatis在给sql语句的参数赋值时使用。 PreparedStatement.setXXX( 位置, 值)
第一个用法: java类型的全限定类型名称 parameterType="java.lang.Integer" 第二个用法: mybatis定义的java类型的别名 parameterType="int" parameterType:mybatis通过反射机制可以获取 dao接口方法参数的类型, 可以不写 <select id="selectById" parameterType="integer" resultType="com.bjpowernode.domain.Student"> select id,name,email,age from student where id=#{studentId} </select>
//dao接口的方法形参是一个简单类型的 //简单类型: java基本数据类型和String Student selectByEmail(String email);
<!-- dao接口是一个简单类型的参数 mapper文件,获取这个参数值,使用#{任意字符} --> <select id="selectByEmail" resultType="com.bjpowernode.domain.Student"> select id,name,email,age from student where email=#{studentEmail} </select>
@Param: 命名参数, 在方法的形参前面使用的, 定义参数名。 这个名称可以用在mapper文件中。
dao接口,方法的定义
/* 多个简单类型的参数 使用@Param命名参数, 注解是mybatis提供的 位置:在形参定义的前面 属性:value 自定义的参数名称 */ List<Student> selectByNameOrAge(@Param("myname") String name, @Param("myage") Integer age);
mapper文件
<!-- 多个简单类型的参数. 当使用了@Param命名后,例如@Param("myname"). 在mapper中,使用#{命名的参数}, 例如 #{myname} --> <select id="selectByNameOrAge" resultType="com.bjpowernode.domain.Student"> select id,name,email,age from student where name=#{myname} or age=#{myage} </select>
方法的形参是一个java对象。这个java对象表示多个参数。使用对象的属性值作为参数使用
java对象
public class Student { private Integer id; private String name; private String email; private Integer age; //set|get方法 } public class QueryParam { private Object p1; private Object p2; //set|get方法 }
dao接口中的方法定义
/* * 一个java对象作为参数( 对象由属性, 每个属性有set,get方法) */ List<Student> selectByObject(Student student); List<Student> selectByQueryParam(QueryParam param);
mapper文件
<!-- 一个java对象作为方法的参数,使用对象的属性作为参数值使用 简单的语法: #{属性名} , mybatis调用此属性的getXXX()方法获取属性值 --> <select id="selectByObject" resultType="com.bjpowernode.domain.Student"> select id,name,email,age from student where name=#{name} or age=#{age} </select> <select id="selectByQueryParam" resultType="com.bjpowernode.domain.Student"> select id,name,email,age from student where name=#{p1} or age=#{p2} </select> <!--负责的语法格式: #{属性名,javaType=java类型的全限定名称,jdbcType=mybatis中定义列的数据类型}--> <select id="selectByObject" resultType="com.bjpowernode.domain.Student"> select id,name,email,age from student where name=#{name,javaType=java.lang.String,jdbcType=VARCHAR} or age=#{age,javaType=java.lang.Integer,jdbcType=INTEGER} </select>
参数位置: dao接口中方法的形参列表,从左往右,参数位置是 0 , 1, 2…
语法格式:#{arg0} ,#{arg1}
dao接口的方法
/* 使用位置,获取参数 */ List<Student> selectByPosition(String name,Integer age);
<!-- mybatis版本是 3.5.1 使用位置获取参数值, dao接口方法是多个简单类型的参数 语法: #{arg0}, #{arg1}.... --> <select id="selectByPosition" resultType="com.bjpowernode.domain.Student"> select id,name,email,age from student where name=#{arg0} or age=#{arg1} </select>
map作为dao接口的参数, 使用 key 获取参数值,mapper文件中,语法格式 #{key}
/* 使用Map作为参数 */ List<Student> selectStudentByMap(Map<String,Object> map);
mapper文件
<!-- 使用Map传递参数, 在mapper文件中,获取map的值,是通过key获取的,语法:#{key} --> <select id="selectStudentByMap" resultType="com.bjpowernode.domain.Student"> select id,name,email,age from student where name=#{myname} or age=#{myage} </select>
测试,调用方法的位置
@Test public void testSelectByMap(){ SqlSession sqlSession = MyBatisUtil.getSqlSession(); StudentDao dao = sqlSession.getMapper(StudentDao.class); //使用map传递参数 Map<String,Object> data = new HashMap<>(); data.put("myname", "李思思"); data.put("myage", 20); List<Student> students = dao.selectStudentByMap(data); students.forEach( stu-> System.out.println("stu="+stu)); sqlSession.close(); }
语法: #{字符}
mybatis处理#{} 使用jdbc对象是 PrepareStatment对象
<select id="selectById" parameterType="integer" resultType="com.bjpowernode.domain.Student"> select id,name,email,age from student where id=#{studentId} </select> mybatis出创建PrepareStatement对象,执行sql语句 String sql=" select id,name,email,age from student where id=?"; PrepareStatement pst = conn.prepareStatement(sql); pst.setInt(1,1001); //传递参数 ResultSet rs = pst.executeQuery(); //执行sql语句
#{}特点:
1)使用的PrepareStatement对象,执行sql语句,效率高。
2)使用的PrepareStatement对象,能避免sql语句, sql语句执行更安全。
3) #{} 常常作为 列值使用的, 位于等号的右侧, #{}位置的值和数据类型有关的。
语法 : ${字符}
mybatis执行${}占位符的sql语句
<select id="selectById" parameterType="integer" resultType="com.bjpowernode.domain.Student"> select id,name,email,age from student where id=${studentId} </select> ${} 表示字符串连接, 把sql语句的其他内容和 ${}内容使用 字符串(+) 连接的方式连在一起 String sql="select id,name,email,age from student where id=" + "1001"; mybatis创建Statement对象, 执行sql语句。 Statement stmt = conn.createStatement(sql); ResultSet rs = stmt.executeQuery();
${} 的特点
1)使用Statement对象,执行sql语句,效率低
2)${}占位符的值,使用的字符串连接方式, 有sql注入的风险。 有代码安全的问题
3 ) ${} 数据是原样使用的, 不会区分数据类型。
4)${} 常用作 表名或者列名, 在能保证数据安全的情况下使用 ${}
封装输出结果: MyBatis执行sql语句,得到ResultSet, 转为java对象。
讲两个 resultType, resultMap
resultType属性: 在执行select时使用, 作为标签的属性出现的。
resultType:表示结果类型 , mysql执行sql语句,得到java对象的类型。 它的值有两种
1) java类型的全限定名称 。
2)使用别名
1) resultType:表示java自定义对象
Student selectById(Integer id); <select id="selectById" parameterType="integer" resultType="com.bjpowernode.domain.Student"> select id,name,email,age from student where id=#{studentId} </select> resultType:现在使用java类型的全限定名称。 表示的意思 mybatis执行sql,把ResultSet中的数据转为Student类型的对象。 mybatis会做以下操作: 1. 调用com.bjpowernode.domain.Student的无参数构造方法,创建对象。 Student student = new Student(); //使用反射创建对象 2. 同名的列赋值给同名的属性。 student.setId( rs.getInt("id")); student.setName(rs.getString("name")); 3. 得到java对象, 如果dao接口返回值是List集合, mybatis把student对象放入到List集合。 所以执行 Student mystudent = dao.selectById(1001); 得到 数据库中 id=1001这行数据, 这行数据的列值, 付给了mystudent对象的属性。 你能得到mystudent对象。 就相当于是 id=1001这行数据。
2)resultType表示简单类型
dao方法
long countStudent();
mapper文件
<!-- 执行sql语句,得到是一个值(一行一列) --> <select id="countStudent" resultType="java.lang.Long"> select count(*) from student </select>
3) resultType:表示一个map结构
//查询结果返回是一个Map Map<Object,Object> selectMap(@Param("stuid") Integer id);
<!-- 执行sql得到一个Map结构数据, mybatis执行sql,把ResultSet转为map sql执行结果, 列名做map的key , 列值作为value sql执行得到是一行记录,转为map结构是正确的。 dao接口返回是一个map, sql语句最多能获取一行记录,多余一行是错误 --> <select id="selectMap" resultType="java.util.HashMap"> select id,name,email from student where id != #{stuid} </select>
练习题:
输入一个省份id ,得到 省份id ,省份name, 城市id,城市名称
例如输入 省份id=1
1 河北 1 石家庄
1 河北 2 秦皇岛
resultMap: 结果映射。 自定义列名和java对象属性的对应关系。 常用在列名和属性名不同的情况。
用法:
1.先定义 resultMap标签, 指定列名和属性名称对应关系
2.在select标签使用resultMap属性,指定上面定义的resultMap的id值
<!--使用resultMap定义列和属性的关系--> <!--定义resultMap id:给resultMap的映射关系起个名称,唯一值 type:java类型的全限定名称 --> <resultMap id="customMap" type="com.bjpowernode.vo.CustomObject"> <!--定义列名和属性名的对应--> <!--主键类型使用id标签--> <id column="id" property="cid" /> <!--非主键类型使用result标签--> <result column="name" property="cname" /> <!--列名和属性名相同不用定义--> <result column="email" property="email" /> <result column="age" property="age" /> </resultMap> <!--使用resultMap属性,指定映射关系的id resultMap和resultType 不能同时使用, 二选一。 --> <select id="selectById2" resultMap="customMap"> select id,name,email,age from student where id=#{stuid} </select>
mybatis提供的对java类型定义简短,好记名称。
自定义别名的步骤:
1)在mybatis主配置文件,使用 typeAliases标签声明别名
2)在mapper文件中, resultType=“别名”
声明别名(mybatis主配置文件)
<typeAliases> <!--第一种语法格式 type:java类型的全限定名称(自定义类型) alias:自定义别名 --> <typeAlias type="com.bjpowernode.domain.Student" alias="stu" /> </typeAliases>
mapper文件中使用
resultType="别名" <select id="selectById" parameterType="integer" resultType="stu"> select id,name,email,age from student where id=#{studentId} </select>
1) 使用resultMap: 自定义列名和属性名称对应关系
2)使用resultType: 使用列别名,让别名和java对象属性名称一样
第一种方式: 在java程序中,把like的内容组装好。 把这个内容传入到sql语句
//like第一种方式 List<Student> selectLikeOne(@Param("name") String name);
mapper
<!--like第一种方式--> <select id="selectLikeOne" resultType="com.bjpowernode.domain.Student"> select * from student where name like #{name} </select>
执行like
@Test public void testLikeOne(){ SqlSession sqlSession = MyBatisUtil.getSqlSession(); StudentDao dao = sqlSession.getMapper(StudentDao.class); String name="%李%"; List<Student> students = dao.selectLikeOne(name); sqlSession.close(); students.forEach( stu-> System.out.println(stu)); }
第二种方式: 在sql语句,组织like的内容。
sql语句like的格式: where name like “%“空格#{name}空格”%”
//like第二种方式 List<Student> selectLikeTwo(@Param("name") String name);
<!--like第二种方式--> <select id="selectLikeTwo" resultType="com.bjpowernode.domain.Student"> select * from student where name like "%" #{name} "%" </select>
@Test public void testLikeTwo(){ SqlSession sqlSession = MyBatisUtil.getSqlSession(); StudentDao dao = sqlSession.getMapper(StudentDao.class); String name="李"; List<Student> students = dao.selectLikeTwo(name); sqlSession.close(); students.forEach( stu-> System.out.println(stu)); }