Mybatis配置及使用

xiaoxiao2021-02-28  33

1、Mybatis与hibernate的区别

Mybatis技术特点:

1、  通过直接编写SQL语句,可以直接对SQL进行性能的优化;

2、  学习门槛低,学习成本低。只要有SQL基础,就可以学习mybatis,而且很容易上手;

3、  由于直接编写SQL语句,所以灵活多变,代码维护性更好。

4、  不能支持数据库无关性,即数据库发生变更,要写多套代码进行支持,移植性不好。

Hibernate技术特点:

1、 标准的orm框架,程序员不需要编写SQL语句。

2、  具有良好的数据库无关性,即数据库发生变化的话,代码无需再次编写。

3、  学习门槛高,需要对数据关系模型有良好的基础,而且在设置OR映射的时候,需要考虑好性能和对象模型的权衡。

4、  程序员不能自主的去进行SQL性能优化。

关于mybatis执行原理,网上一搜一大堆,此篇博客只讲述使用以及配置!!!!

2、Mybatis基本配置

在介绍配置之前,先来看看工程的目录图(此后的文件很多,如果对不上了来看看目录图)

再来看看mybatis遇到的jar包

其中junit为测试包,junit以上为mybatis必须的jar包

2.1 全局配置(SqlMapConfig.xml)

与hibernate类似,mybatis的配置也存在全局配置文件

<?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> <!-- mybatis的环境配置,此信息在开发中只需照搬即可 --> <environments default="development"> <environment id="development"> <!-- 配置JDBC事务,此事务由mybatis管理 --> <transactionManager type="JDBC"></transactionManager> <!-- 配置连接池,此连接池为mybatis连接池 --> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments> <!-- 映射文件 (加载所需要的局部配置) Mappers <mapper resource=’’/> 使用相对于类路径的资源 如:<mapper resource="sqlmap/User.xml" /> <mapper url=’’/> 使用完全限定路径 如:<mapper url="file:///D:\workspace_spingmvc\mybatis_01\config\sqlmap\User.xml" /> <mapper class=’’/> 使用mapper接口的全限定名 如:<mapper class="com.sjg.dao.UserMapper"/> 注意:此种方法要求mapper接口和mapper映射文件要名称相同,且放到同一个目录下; <package name=’’/>(推荐) 注册指定包下的所有映射文件 如:<package name="com.sjg.dao"/> 注意:此种方法要求mapper接口和mapper映射文件要名称相同,且放到同一个目录下; --> <mappers> <mapper resource="config/User.xml"/> <package name="com.sjg.dao"/> </mappers> </configuration>

<environment>是通用的“套路”,<mapper>是为了加载上面的局部配置

我们在测试类中使用mybatis时,通常使用以下的套路

public static void main(String[] args) throws Exception { //获取xml文件的路径 String resource = "config/SqlMapConfig.xml"; //配置路径 InputStream inputStream = Resources.getResourceAsStream(resource); //创建SqlSessionFactory SqlSessionFactory sqlFactory = new SqlSessionFactoryBuilder().build(inputStream); //创建SqlSession SqlSession sqlSession = sqlFactory.openSession(); /* * 你想做的操作 * */ sqlSession.close(); }

2.2 Mybatis开发dao(dao包下的局部配置)

在介绍dao之前,必须先引入User的model(省略set/get方法)和数据表字段

package com.sjg.model; import java.util.Date; public class User { private Integer id; private String username; private String sex; private Date birthday; private String address;

在了解了基本的model和数据表之后,直接上相应的xml配置文件和相应的dao(也就是所谓的mapper映射文件)

UserMapper.xml

<?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接口(UserMapper类)的全限定名要和mapper映射文件的namespace值一致。 --> <mapper namespace="com.sjg.dao.UserMapper"> <!-- mapper接口的方法名称要和mapper映射文件的statement的id一致。 mapper接口的方法参数类型要和mapper映射文件的statement的parameterType的值一致,而且它的参数是一个。 mapper接口的方法返回值类型要和mapper映射文件的statement的resultType的值一致。 --> <select id="getUserById" parameterType="int" resultType="com.sjg.model.User"> SELECT * FROM USER WHERE id =#{id} </select> <!-- 添加用户 --> <!-- selectKey:查询主键,在标签内需要输入查询主键的sql --> <!-- order:指定查询主键的sql和insert语句的执行顺序,相当于insert语句来说,对于 此时先进行插入,再获得主键,逻辑上也是成立的 --> <!-- LAST_INSERT_ID:该函数是mysql的函数,获取自增主键的ID,它必须配合insert语句一起使用 --> <insert id="insertUser" parameterType="com.sjg.model.User"> <selectKey keyProperty="id" resultType="int" order="AFTER"> SELECT LAST_INSERT_ID() </selectKey> INSERT INTO USER (username,birthday,sex,address) VALUES(#{username},#{birthday},#{sex},#{address}) </insert> <!--  #{}和${} #{}表示占位符?,#{}接收简单类型的参数时,里面的名称可以任意 ${}表示拼接符,${}接收简单类型的参数时,里面的名称必须是value ${}里面的值会原样输出,不加解析(如果该参数值是字符串,有不会添加引号) ${}存在sql注入的风险,但是有些场景下必须使用,比如排序后面会动态传入排序的列名 --> </mapper>

UserMapper

package com.sjg.dao; import com.sjg.model.User; //注意定义的是接口,此类为所谓的Mapper接口 public interface UserMapper { //插入一个学生的信息,方法名要与UserMapper.xml中的insert标签的id相一致 void insertinsertUser(); //查询某个学生的信息,方法名要与UserMapper.xml中的select标签的id相一致 User getUserById(); }

测试类

public static void main(String[] args) throws Exception { //获取xml文件的路径 String resource = "config/SqlMapConfig.xml"; //配置路径 InputStream inputStream = Resources.getResourceAsStream(resource); //创建SqlSessionFactory SqlSessionFactory sqlFactory = new SqlSessionFactoryBuilder().build(inputStream); //创建SqlSession SqlSession sqlSession = sqlFactory.openSession(); //获得相应的mapper映射文件 UserMapper dao = sqlSession.getMapper(UserMapper.class); //取得id为1的用户信息 User user = dao.getUserById(1); System.out.println(user); /*id=1, username=jack, sex=1, * birthday=Wed Apr 25 00:00:00 CST 2018, address=政府 */ User user1 = new User(); user1.setUsername("eee"); dao.insertUser(user1); //提交事务 sqlSession.commit(); sqlSession.close(); } }

在数据库中也是成功插入了,在此就不截图了。

如果想进行更多的基本操作,只需要仿照xml中的配置,写入相应的select或者insert等等语句,进行测试和使用

3.Mybatis的一对一、一对多、多对多

与hibernate一样,持久层的框架都离不开上述三个关系,mybatis给出了一个特别好的解决办法,就是在xml文件中加入<resultMap>标签,这个标签十分强大,利用xml文件具有标签中套有标签,层次性非常强的特点,将上述三种关系完美的表达出来,具体使用在例子中进行详细的讲解。

3.1 一对一

我们举个例子,学生和学生对应的学生号,是一一对应的。当然,在讲述之前,先列出model(无set/get)和数据表

StudentInfo(model)

package com.sjg.model; public class StudentInfo { private Integer studentId; private String card;

student_info(表)

Student(model)

package com.sjg.model; import java.util.List; public class Student { private Integer studentId; private String studentName; private Integer age; private Integer classId; private StudentInfo stuInfo;//此为一对一的关键

student(表)

重点在于两个xml配置文件

StudentDao.xml

<?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.sjg.dao.StudentDao"> <!-- id:这个resultMap的id,便于其他标签引用 type:输入指定的model全限定名(student中的字段包含了studentInfo) 那么以student为主,自然type填写student --> <resultMap type="com.sjg.model.Student" id="StudentMap"> <!-- id标签为相应的id字段 result为model对应的属性名称 property:model中的字段 column:数据表中的对应字段 --> <id property="studentId" column="student_id"/> <result property="studentName" column="stu_name"/> <result property="age" column="age"/> <result property="classId" column="class_id"/> <!-- association标签表示一对一引用的另一个对象 即student这个model中的stuInfo字段要对应的内容 resultMap:引用了StudentInfoDao.xml中的StudentInfoMap这个resultMap --> <association property="stuInfo" resultMap="com.sjg.dao.StudentInfoDao.StudentInfoMap"></association> </resultMap> <!-- resultMap:引用了上面的resultMap,与其id对应 其他的已经解释过,sql语句不解释 --> <select id="selectAllStudent" resultMap="StudentMap"> SELECT t.student_id, t.stu_name, t.age, t.class_id, t2.card FROM student t LEFT JOIN student_info t2 ON t.student_id = t2.student_id </select> </mapper>

StudentInfo.xml

<?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.sjg.dao.StudentInfoDao"> <resultMap id="StudentInfoMap" type="com.sjg.model.StudentInfo"> <id property="studentId" column="student_id"/> <result property="card" column="card"/> </resultMap> <select id="getStudentInfo" parameterType="java.lang.Integer" resultMap="StudentInfoMap"> SELECT t.student_id t.card FROM student_info t WHERE t.student_id = #{studentId} </select> </mapper>

最后,列出相应的dao文件

StudentDao

package com.sjg.dao; import java.util.List; import com.sjg.model.Student; public interface StudentDao { //方法名与StudentDao.xml中select标签的id一致,此后不再提示 List<Student> selectAllStudent(); }

测试类

public static void main(String[] args) throws Exception { //获取xml文件的路径 String resource = "config/SqlMapConfig.xml"; //配置路径 InputStream inputStream = Resources.getResourceAsStream(resource); //创建SqlSessionFactory SqlSessionFactory sqlFactory = new SqlSessionFactoryBuilder().build(inputStream); //创建SqlSession SqlSession sqlSession = sqlFactory.openSession(); //获得相应的mapper映射文件 StudentDao dao = sqlSession.getMapper(StudentDao.class); //取得id为1的用户信息 List<Student> list = dao.selectAllStudent(); System.out.println(list); /* * [ studentId=10001, studentName=张三, age=20, classId=1001, stuInfo=studentId=10001, card=12345 , studentId=10002, studentName=李四, age=21, classId=1001, stuInfo=studentId=10002, card=54321 , studentId=10003, studentName=王五, age=22, classId=1002, stuInfo=studentId=10003, card=23233 ] * */ sqlSession.close(); } }

可以看出,我们查出了StudentInfo中的card

3.2 一对多

我们假设一个同学只能选择一门课程,那么对于课程来说,就是“一”,而学生就是“多”

Classes(model)

package com.sjg.model; import java.util.List; public class Classes { private Integer classId; private String className; private List<Student> studentList;//一对多的关键

classes(表)

student的model和表参考上面给出的

重点依旧是xml文件的配置

ClassesDao.xml

<?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.sjg.dao.ClassesDao"> <!-- collection : 用于一对多和多对多 association : 用于一对一   其他属性都一致,仔细观察就能发现collection与Student的model中的字段一致   在这里就能很明显的看出,利用xml文件的层次结构体现了一对多以及下面会出现的多对多 的关系 --> <resultMap type="com.sjg.model.Classes" id="ClassesMap"> <id property="classId" column="class_id"/> <result property="className" column="class_name"/> <!-- ofType:collection标签内的model类全限定名 studentList里面当时就是student类型咯 column="关联主键ID(用于嵌套查询SQL语句传入参数,多个用逗号分开)"  --> <collection property="studentList" ofType="com.sjg.model.Student" column="classesId"> <id property="studentId" column="student_id"/> <result property="studentName" column="stu_name"/> <result property="age" column="age"/> <result property="classId" column="class_id"/> <association property="stuInfo"  resultMap="com.sjg.dao.StudentInfoDao.StudentInfoMap"> </association> </collection> </resultMap> <select id="selectAllClasses" resultMap="ClassesMap"> SELECT           t.student_id,           t.stu_name,           t.age,           t.class_id,           t2.class_name          FROM student t           LEFT JOIN classes t2 ON t.class_id = t2.class_id </select> </mapper>

测试类

public static void main(String[] args) throws Exception { //获取xml文件的路径 String resource = "config/SqlMapConfig.xml"; //配置路径 InputStream inputStream = Resources.getResourceAsStream(resource); //创建SqlSessionFactory SqlSessionFactory sqlFactory = new SqlSessionFactoryBuilder().build(inputStream); //创建SqlSession SqlSession sqlSession = sqlFactory.openSession(); //获得相应的mapper映射文件 ClassesDao dao = sqlSession.getMapper(ClassesDao.class); //取得id为1的用户信息 List<Classes> list = dao.selectAllClasses(); System.out.println(list); /* * [classId=1001, className=语文, studentList=[ studentId=10001, studentName=张三, age=20, classId=1001, stuInfo=studentId=10001, card=null , studentId=10002, studentName=李四, age=21, classId=1001, stuInfo=studentId=10002, card=null ], classId=1002, className=数学, studentList=[ studentId=10003, studentName=王五, age=22, classId=1002, stuInfo=studentId=10003, card=null ]] * */ sqlSession.close(); } }

结果与数据库结果相一致

3.3 多对多

一个老师可以有多个学生,一个学生也可以有多个老师,体现多对多的关系,中间还需要一个中间表

在多对多先列出数据表

teacher(表)

ts_relation(关系表)

student的依旧参考上面的

认清了表之后,我们来看一下model

Teacher(model)

package com.sjg.model; import java.util.List; public class Teacher { private Integer teacherId; private String teacherName; private List<Student> stuList;//多对多TSRelation(model)

package com.sjg.model; public class TSRelation { private Teacher teacher; private Student student;Student(model) package com.sjg.model; import java.util.List; public class Student { private Integer studentId; private String studentName; private Integer age; private Integer classId; private StudentInfo stuInfo; private List<Teacher> teacherList;//多对多可以看到,多对多就是在一对多的基础上,在“一”的那一方加入了相应的集合元素 重点还是在xml

TeacherDao.xml

<?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.sjg.dao.TeacherDao"> <resultMap type="com.sjg.model.Teacher" id="TeacherMap"> <id property="teacherId" column="teacher_id"/> <result property="teacherName" column="tea_name"/> <collection property="stuList" ofType="com.sjg.model.Student"> <id property="studentId" column="student_id"/> <result property="studentName" column="stu_name"/> <result property="age" column="age"/> <result property="classId" column="class_id"/> <association property="stuInfo" resultMap="com.sjg.dao.StudentInfoDao.StudentInfoMap"> </association> </collection> </resultMap> <select id="selectAllTeacher" resultMap="TeacherMap"> select t.teacher_id, t.tea_name, s.student_id, s.stu_name, s.class_id, s.age from teacher t, student s, ts_relation ts where t.teacher_id = ts.tea_id and s.student_id = ts.stu_id </select> </mapper>

和一对多很相似,那么接下来进行测试

测试类

public static void main(String[] args) throws Exception { //获取xml文件的路径 String resource = "config/SqlMapConfig.xml"; //配置路径 InputStream inputStream = Resources.getResourceAsStream(resource); //创建SqlSessionFactory SqlSessionFactory sqlFactory = new SqlSessionFactoryBuilder().build(inputStream); //创建SqlSession SqlSession sqlSession = sqlFactory.openSession(); //获得相应的mapper映射文件 TeacherDao dao = sqlSession.getMapper(TeacherDao.class); //取得id为1的用户信息 List<Teacher> list = dao.selectAllTeacher(); System.out.println(list); /* * [teacherId=1, teachername=张老师, stuList=[ studentId=10001, studentName=张三, age=20, classId=1001, stuInfo=studentId=10001, card=null , studentId=10002, studentName=李四, age=21, classId=1001, stuInfo=studentId=10002, card=null , studentId=10003, studentName=王五, age=22, classId=1002, stuInfo=studentId=10003, card=null ], teacherId=2, teachername=李老师, stuList=[ studentId=10001, studentName=张三, age=20, classId=1001, stuInfo=studentId=10001, card=null , studentId=10003, studentName=王五, age=22, classId=1002, stuInfo=studentId=10003, card=null ]] * */ sqlSession.close(); } }

此时输出结果以老师的角度来看各个老师又多少个学生,如果想从学生的角度来看有多少老师,只需要更改一下xml文件中的resultMap标签中的内容即可

修改后的Teacher.xml

<?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.sjg.dao.TeacherDao"> <resultMap type="com.sjg.model.Student" id="TeacherMap"> <id property="studentId" column="student_id"/> <result property="studentName" column="stu_name"/> <result property="age" column="age"/> <result property="classId" column="class_id"/> <collection property="teacherList" ofType="com.sjg.model.Teacher"> <id property="teacherId" column="teacher_id"/> <result property="teacherName" column="tea_name"/> </collection> </resultMap> <select id="selectAllTeacher" resultMap="TeacherMap"> select t.teacher_id, t.tea_name, s.student_id, s.stu_name, s.class_id, s.age from teacher t, student s, ts_relation ts where t.teacher_id = ts.tea_id and s.student_id = ts.stu_id </select> </mapper>

测试类

public static void main(String[] args) throws Exception { //获取xml文件的路径 String resource = "config/SqlMapConfig.xml"; //配置路径 InputStream inputStream = Resources.getResourceAsStream(resource); //创建SqlSessionFactory SqlSessionFactory sqlFactory = new SqlSessionFactoryBuilder().build(inputStream); //创建SqlSession SqlSession sqlSession = sqlFactory.openSession(); //获得相应的mapper映射文件 TeacherDao dao = sqlSession.getMapper(TeacherDao.class); //取得id为1的用户信息 List<Teacher> list = dao.selectAllTeacher(); System.out.println(list); /* * [ studentId=10001, studentName=张三, age=20, classId=1001, stuInfo=null ,teacherList=[teacherId=1, teachername=张老师, stuList=null, teacherId=2, teachername=李老师, stuList=null], studentId=10002, studentName=李四, age=21, classId=1001, stuInfo=null ,teacherList=[teacherId=1, teachername=张老师, stuList=null], studentId=10003, studentName=王五, age=22, classId=1002, stuInfo=null ,teacherList=[teacherId=2, teachername=李老师, stuList=null, teacherId=1, teachername=张老师, stuList=null] ] */ sqlSession.close(); } }

4.总结

至此,mybatis最基本的使用和配置已经介绍完毕了,mybatis的使用和细节还有很多,在实际开发中遇到了才会知道。关于mybatis的缓存,有精力了再往下写一些,本篇侧重于最基本的使用和配置。

如需转载请注明出处。

Mybatis官方技术文档:点击打开链接

 http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html
转载请注明原文地址: https://www.6miu.com/read-2250396.html

最新回复(0)