Mybatis配置及使用

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

  • 4
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值