MyBatis
来源:互联网 发布:linux查看ssh端口号 编辑:程序博客网 时间:2024/05/22 23:26
简介
MyBatis曾被称为iBatis.
iBatis是apache的一个开源项目,2010年迁移到google code,并且改名为MyBatis。
MyBatis是一个支持普通SQL查询、存储过程和高级映射的优秀持久层框架。MyBatis消除了绝大部分的JDBC代码,简化了手工设置SQL参数,以及对结果集的检索进行了封装。 MyBatis可以使用简单的XML或注解的方式来配置映射,将POJO(普通的Java对象,实体对象)映射成数据库中的记录。
MyBatis
① 获取MyBatis驱动包
官网http://blog.mybatis.org/或https://github.com/mybatis/mybatis-3/releases中下载MyBatis的资源文件mybatis-3.x.x.zip,解压后可得到如下文件:
② 创建一个普通的Java项目(项目名MyBatisDemo),并在该项目的src目录下,创建一个libs目录(new → Folder)并存放mybatis-3.x.x.jar和ojdbc6.jar(oracle驱动包),再将这两个jar包设置为构建目录(Build Path),如图,
③ 创建(或使用之前已有的)“学生表”,各字段及类型如下:
创建完毕后,加入一些数据:
④ 创建与学生表对应的实体类,如下,
package org.lzy.entity;public class Student{ //学号 private int stuNo; //姓名 private String stuName; //年龄 private int stuAge; //年级名称 private String graName; //省略无参、各种带参的构造方法//省略setter、getter //为了方便的输出对象中的内容,重写toString()方法 @Override public String toString() { return "学号:"+this.stuNo+"\t姓名:"+this.stuName+"\t年龄:"+this.stuAge+"\t年级:"+this.graName; }}
⑤ 创建学生表与学生类的映射关系文件:
org/lzy/entity/studentMapper.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="org.lanqiao.entity.studentMapper"> <select id=" queryStudentByNo" parameterType="int" resultType="org.lzy.entity.Student"> select * from student where stuNo=#{stuNo} </select></mapper>
ps:在SQL映射文件中,SQL语句的最后没有分号
⑥ 创建MyBatis的配置文件,如下,
<?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> <environments default="development"> <environment id="development"> <transactionManager type="JDBC" /> <!-- 配置数据库连接信息 --> <dataSource type="POOLED"> <property name="driver" value="oracle.jdbc.OracleDriver" /> <property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:XE" /> <property name="username" value="system" /> <property name="password" value="sa" /> </dataSource> </environment> </environments> <!-- 在配置文件(conf.xml)中注册SQL映射文件(studentMapper.xml)--> <mappers> <mapper resource="org/lanqiao/entity/studentMapper.xml" /> </mappers></configuration>
说明:配置文件以conf.xml以及映射文件studentMapper.xml中的头信息、约束、子元素等,不必我们自己手写。可以再之前的mybatis-3.x.x.pdf,此向导文件中就有MyBatis的配置以及映射模板,只需要复制粘贴,然后修改相关属性值即可。
⑦ 编写测试类:执行SQL映射文件中定义的select语句
package org.lzy.test;//省略importpublic class TestMyBatis{ public static void main(String[] args) throws IOException { String resource = "conf.xml"; // 加载mybatis 的配置文件 Reader reader = Resources.getResourceAsReader(resource); // 创建sqlSession 的工厂 SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader); // 创建能够执行SQL映射文件中sql语句的sqlSession对象 SqlSession session = sessionFactory.openSession(); // 指定sql语句对应的标识字符串:namespace+id String statement = "org.lzy.entity.studentMapper" + ". queryStudentByNo "; // 执行查询,返回一个学号为32的Student对象 Student student = session.selectOne(statement, 32); System.out.println(student); session.close(); }}
测试类中,statement变量指向了SQL映射文件中id为getStudentByNo的select标签, 并通过SqlSession对象的selectOne()方法,将“32”传入该select标签中,最后select标签中的SQL语句通过#{stuNo}将“32”赋值给了stuNo。
整体思路
MyBatis应用程序根据XML配置文件(conf.xml)创建SqlSessionFactory,再由SqlSessionFactory创建一个SqlSession对象。SqlSession对象包含了执行SQL所需要的所有方法,可以直接运行映射的SQL语句,完成对数据的增删改查等操作。其中映射的SQL语句存放在一个SQL映射文件中(如studentMapper.xml),应用程序可以通过SQL映射文件中的namespace+id找到对应的SQL语句。
其中,SqlSession对象的常用方法如下:
方法中的参数:
statement:代表即将执行的sql语句,该sql语句是由sql映射文件中的namespace和标签元素的id值指定。
paramter:sql语句的参数值,参数类型通过SQL映射文件中的parameterType属性指定,并通过“#{}”取得。如果参数是简单类型(基本数据类型或String类型),直接使用“#{参数名}”取得;如果参数是对象类型,则需要使用“#{对象的属性名}”来获取。
MyBatis配置文件
官方MyBatis配置文件conf.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"><configuration> <environments default="development"> <environment id="development"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="${driver}" /> <property name="url" value="${url}" /> <property name="username" value="${username}" /> <property name="password" value="${password}" /> </dataSource> </environment> </environments> <mappers> <mapper resource="org/mybatis/example/BlogMapper.xml" /> </mappers></configuration>
(1)多环境配置
default:指定默认environment的id值
environments:MyBatis允许配置多种不同的数据库环境,如开发环境、测试环境、工作环境等。因此在MyBatis中,我们可以使用相同的SQL映射来操作不同的数据库。但要注意,虽然允许配置多种不同的环境,但在使用时,environments只能选择唯一的一个环境,即通过environments元素的default属性来指定默认使用的environment的id值。这样可以方便开发者快速的在不同数据库环境之间切换。此外,每个数据库环境(environment元素),在程序中对应着一个SqlSessionFactory对象。
之前在测试类TesMyBatis.java中,通过配置文件(conf.xml)创建的SqlSessionFactory对象,就是根据数据库环境environment元素的内容产生的。具体代码如下:
String resource = "conf.xml"; // 加载mybatis 的配置文件 Reader reader = Resources.getResourceAsReader(resource); // 创建sqlSession 的工厂 SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
以上,是根据environments元素中default属性指定的数据库环境而产生的SqlSessionFactory对象。我们也可以在Java代码中显示的指定数据库环境,如下:
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader,"development");
即通过build()方法的第二个参数,将数据库的环境指定为id值为”development”所代表的environment。
(2)具体环境配置
environments的子元素,表示每一个具体的数据库环境。
id:数据库环境的id值
(3)事务管理器
<transactionManager type="JDBC" />
type: 指定事务管理器类型。在MyBatis中有两种事务管理器类型,JDBC和MANAGED
<transactionManager type="MANAGED"> <property name="closeConnection" value="false"/> </transactionManager>
(4)数据源
<dataSource type="POOLED">
type: 指定数据源类型
MyBatis中有三种数据源类型,UNPOOLED、 POOLED和JNDI:
① UNPOOLED :每次被请求时简单打开和关闭连接,需要配置的以下属性:
② POOLED:简单的数据库连接池类型,它使得数据库连接可被复用,不必在每次请求时都去创建一个物理的连接。
③ JNDI :从tomcat等容器中获取数据源
(5)映射文件
<mappers> <mapper resource="org/mybatis/example/BlogMapper.xml" /></mappers>
mappers:用于配置SQL映射文件
mapper的resource属性:SQL映射文件(XxxMapper.java)的相对路径。
SQL映射文件
SQL映射文件(XxxMapper.java)基础模板如下:
<?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="{namespace }"> <select id="{id}" parameterType="{ptype}" resultType="${rtype}"> SQL语句,例如:select * from student where stuNo=#{stuNo} </select></mapper>
(1)命名空间
<mapper namespace="{namespace }">
给此映射文件设置一个命名空间,程序需要根据命名空间,找到某一个具体的映射文件。
(2)查询标签
<select id="{id}" parameterType="{ptype}" resultType="{rtype}"> SQL语句,例如:select * from student where stuNo=#{stuNo}</select>
id:唯一标识符,程序可以通过“命名空间+唯一标识符”(即namespace+id)来定位此select标签中的SQL语句。
parameterType:传入“SQL语句”中的参数类型。例如,SQL语句中“stuNo=#{stuNo}”表示需要传入一个int型的stuNo,就可以通过parameterType=”int”将输入参数的类型设置为int。
resultType : SQL语句的返回类型。例如,“select * from student …”返回的是一个学生的全部信息,可以用学生对象来保存,所以返回类型可以是Student类型,即resultType=”org.lzy.entity.Student”
使用MyBatis实现CRUD
CRUD是指create、read、upadate和delete。
SQL映射文件:org/lzy/entity/studentMapper.xml
<mapper namespace="org.lzy.entity.studentMapper"> <!-- 增加一个学生 --> <insert id="addStudent" parameterType="org.lzy.entity.Student"> insert into student(stuNo,stuName,stuAge,graName) values(#{stuNo},#{stuName},#{stuAge},#{graName}) </insert> <!-- 根据学号,删除一个学生 --> <delete id="deleteStudentByNo" parameterType="int"> delete from student where stuNo=#{stuNo} </delete> <!-- 根据学号,修改学生信息 --> <update id="updateStudentByNo" parameterType="org.lzy.entity.Student"> update student set stuName=#{stuName},stuAge=#{stuAge},graName=#{graName} where stuNo=#{stuNo} </update> <!-- 根据学号,查询一个学生 --> <select id=" queryStudentByNo " parameterType="int" resultType="org.lzy.Student"> select * from student where stuNo=#{stuNo} </select> <!-- 查询全部学生 --> <select id=" getAllStudents " resultType="org.lzy.entity.Student"> select * from student</select></mapper>
测试类org.lzy.test.TestMyBatis.java
public class TestMyBatis{ // 增加一个学生 public static void testAdd() throws IOException { … // 指定sql语句对应的标识字符串:namespace+id String statement = "org.lzy.entity.studentMapper" + ".addStudent"; Student stu = new Student(7, "路人甲", 22, "一年级"); session.insert(statement, stu); session.commit(); session.close(); } // 根据学号,删除一个学生 public static void testDeleteByNo() throws IOException { … String statement = "org.lzy.entity.studentMapper" + ".deleteStudentByNo"; session.delete(statement, 7); session.commit(); session.close(); } // 根据学号,修改学生信息 public static void testUpdate() throws IOException { … String statement = "org.lzy.entity.studentMapper" + ".updateStudentByNo"; Student stu = new Student(7, "路人乙", 33, "二年级"); session.update(statement, stu); session.commit(); session.close(); } // 根据学号查询一个学生 public static void testQueryStudentByNo () throws IOException { … String statement = "org.lzy.entity.studentMapper" + ".queryStudentByNo "; // 执行查询,返回一个学号为32的Student对象 Student student = session.selectOne(statement, 32); System.out.println(student); session.close(); } // 查询全部学生 public static void testQueryAll() throws IOException { String statement = "org.lzy.entity.studentMapper" + ".queryAllStudents"; // 执行查询,返回一个学号为32的Student对象 List<Student> students = session.selectList(statement); System.out.println(students); session.close(); } public static void main(String[] args) throws IOException { testQueryStudentByNo ();//根据学号,查询一个学生 testAdd();//增加一个学生 testUpdate();//根据学号,修改一个学生 testDeleteByNo();//根据学号,删除一个学生 testQueryAll();//查询全部学生 }}
ps:在执行增insert()、删delete()、改update()操作后,必须再执行commit()方法进行数据库提交,否则不会对数据库表中的数据产生影响。
使用Mapper动态代理优化
有一条软件设计范式称为“约定优于配置”,就是说如果有一些值没被配置的话,那么程序就会使用默认值(即“约定”)。换句话说,如果能按照“约定”去开发程序,就不需要配置了。
我们之前开发的“MyBatisDemo”项目,在测试类(TestMyBatis.java)里,每执行一个数据库操作(增、删、改、查),都必须通过statement变量来指向SQL映射文件(studentMapper.xml)中某一个标签的id值(即通过namespace+id的方式指定,例如用String statement = “org.lanqiao.entity.studentMapper” + “.addStudent”来指定“增加”所需要的SQL语句)。可以发现,这种使用硬编码的方式来指定SQL语句,开发起来比较繁琐,因此我们可以使用“约定优于配置”来简化:使用“约定”来省略statement变量的配置。具体实现步骤如下:
(1)在之前的“MyBatisDemo”项目上二次开发。其中,学生表、学生实体类(Student.java)都与之前的完全一样。
(2)新建接口,在接口中定义操作数据库的方法,并给方法增加一些“约定”。其中,“约定”需要参照SQL配置文件(studentMapper.xml)中的各个标签(如<select>
),如下:
<!-- 根据学号,查询一个学生 --><select id=" queryStudentByNo" parameterType="int" resultType="org.lzy.entity.Student"> select * from student where stuNo=#{stuNo} </select>
接口中方法的具体“约定”:
① 方法名和SQL配置文件(studentMapper.xml)中相关方法的id值相同。例如,SQL配置文件中“查询一个学生”的标签的id值是“queryStudentByNo”,那么在接口中“查询一个学生”的方法名就也必须是queryStudentByNo ()。
②方法的输入参数类型,和SQL配置文件中“parameterType”的类型相同。例如,SQL配置文件中“查询一个学生”的“parameterType”类型是int,则在接口中“查询一个学生”方法的输入参数类型就必须是int,即getStudentByNo(int stuNo)。特殊情况:如果SQL配置文件中不存在“parameterType”,则表示是一个无参方法。
③方法的返回值类型,和SQL配置文件中“resultType”的类型相同。例如,SQL配置文件中“查询一个学生”的“resultType”类型是“org.lanqiao.entity.Student”,则在接口中“查询一个学生”方法的返回值类型就必须是“org.lzy.entity.Student(或简写为Student)”,即Student getStudentByNo(int stuNo){ … }。
特殊情况:
①如果SQL配置文件中不存在“resultType”,则表示是方法的返回值为void。
②如果方法的返回值是一个集合类型(例如,返回类型是List<Student>
),但在SQL配置文件中的“resultType”却不能集合类型,而应该是集合中的元素类型(例如,配置文件中要使用resultType=”org.lzy.entity.Student“来表示返回值类型List<Student>
)。
有了上述三条“约定”,MyBatis就能将接口中的方法和数据库标签(如、等)一一对应起来,而不再需要使用statement变量来指定.
org.lzy.mapper.IStudentMapper.java
package org.lzy.maper;import java.util.List;import org.lzy.entity.Student;public interface IStudentMapper{ //按照“约定”编写的“根据学号,查询一个学生”的接口方法 public abstract Student queryStudentByNo (int stuNo); //按照“约定”编写的“查询全部学生”的接口方法 public abstract List<Student> queryAllStudents (); //按照“约定”编写的“增加一个学生”的接口方法 public abstract void addStudent(Student student); //按照“约定”编写的“根据学号,删除一个学生”的接口方法 public abstract void deleteStudentByNo(int stuNo); //按照“约定”编写的“根据学号,修改一个学生”的接口方法 public abstract void updateStudentByNo(int stuNo);}
(3) 修改的SQL映射文件studentMapper.xml:将mapper的namespace值修改为接口IStudentMapper.java的“包名+接口名”,如下,
<mapper namespace="org.lzy.mapper.IStudentMapper">…</mapper>
MyBatis通过namespace的值来定位接口的路径,并在接口编写方法的月的约定来将SQL映射文件中的各个数据库标签(如、等)与接口中的方法一一对应的。有了接口方法和数据库标签的一一对应关系,也就可以直接通过接口中方法名来定位数据库标签,而不用再使用statement变量来定位数据库标签。
(4) 习惯上,我们在使用此种基于约定的“Mapper动态代理方式”实现MyBatis时,会把SQL映射文件和接口放在同一个包下。因此需要将项目中studentMapper.xml移动到接口所在包 “org.lzy.mapper”中。移动完后,注意要修改MyBatis配置文件(conf.xml)中的SQL配置文件路径,如下,
conf.xml
<configuration> … <mappers> <mapper resource="org/lzy/mapper/studentMapper.xml" /> </mappers></configuration>
(5)在测试类中编写测试代码
采用Mapper动态代理方式,还需要借助于SqlSession接口中getMapper()方法,
public class TestMyBatis{… // 根据学号查询一个学生 public static void testQueryByNoWothMapper() throws IOException { String resource = "conf.xml"; Reader reader = Resources.getResourceAsReader(resource); SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader); SqlSession session = sessionFactory.openSession();// 传入IStudentMapper接口,返回该接口的mapper代理对象studentMapper IStudentMapper studentMapper = session.getMapper(IStudentMapper.class); //通过mapper代理对象studentMapper,来调用IStudentMapper接口中的方法 Student student = studentMapper.getStudentByNo(31); System.out.println(student); session.close(); } public static void main(String[] args) throws IOException { testQueryByNoWothMapper(); … }}
使用mapper代理的方法来开发MyBatis,开发者只需要按照一定的“约定”编写接口及接口中的方法,并且不用写接口的实现类,然后就可以直接通过接口中的方法来执行SQL映射文件中的SQL语句。在MyBatis官方文档中,也是推荐使用此种方式来开发程序。
- MyBatis
- MyBatis
- Mybatis
- myBatis
- mybatis
- MyBatis
- mybatis
- Mybatis
- MyBatis
- Mybatis
- mybatis
- MyBatis
- MyBatis
- mybatis
- MyBatis
- mybatis
- mybatis
- mybatis
- Asp.Net开发中未整理的资料
- python求数独全解
- BZOJ 4430 赌骆驼
- 几个常用创建型设计模式总结
- [Android Memory] 手动回收ImageVIew的图片资源
- MyBatis
- JAVA工程师面试题
- SQL学习—SELECT语句
- LinuxStudyNote(45)-管道符 | 的使用与解析、| 与 grep的使用
- HSL and HSV
- 前端之路——第一篇:认识前端简单的基础知识
- 最邻近规则分类(K-Nearest Neighbor)KNN算法
- XOR usage
- linux中wget 、apt-get、yum 这三种安装方式的区别是什么?