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,解压后可得到如下文件:

文件名 简介 mybatis-3.x.x.jar MyBatis的类库 mybatis-3.x.x-javadoc.jar Mybatis的API帮助文档 mybatis-3.x.x-sources.jar Mybatis的源代码 mybatis-3.x.x.pdf MyBatis的开发向导

② 创建一个普通的Java项目(项目名MyBatisDemo),并在该项目的src目录下,创建一个libs目录(new → Folder)并存放mybatis-3.x.x.jar和ojdbc6.jar(oracle驱动包),再将这两个jar包设置为构建目录(Build Path),如图,
这里写图片描述
③ 创建(或使用之前已有的)“学生表”,各字段及类型如下:

字段名 类型 字段名 类型 stuNo number stuAge number stuName nvarchar2(50) garName nvarchar2(50)

创建完毕后,加入一些数据:
这里写图片描述
④ 创建与学生表对应的实体类,如下,

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对象的常用方法如下:

方法 简介 int insert(String statement, Object parameter) 执行数据库的“增加”操作。如果SQL语句中没有参数,可以使用重载方法int insert(String statement)。返回值表示实际增加了几条数据。 int delete(String statement,Object parameter) 执行数据库的“删除”操作。如果SQL语句中没有参数,可以使用重载方法int delete(String statement)。返回值表示实际删除了几条数据。 int update(String tatement, Object parameter) 执行数据库的“修改”操作。如果SQL语句中没有参数,可以使用重载方法 int delete(String statement)。返回值表示实际修改了几条数据。 T selectOne(String statement,Object parameter); 执行数据库中的“查询单个结果集”操作。如果SQL语句中没有参数,可以使用重载方法 T selectOne(String statement)。返回值表示查询到的结果,返回值类型通过SQL映射文件中的resultType属性指定。 List selectList(String statement, Object parameter); 执行数据库中的“查询多行结果(结果集)”操作,如select * from student。如果SQL语句中没有参数,可以使用重载方法 List selectList(String statement)。返回值表示查询结果的集合对象,集合元素的类型通过SQL映射文件中的resultType属性指定。 void commit() 事务的提交语句,会提交数据库的连接。需要注意的是,在执行增删改(insert()、delete()、update())命令后,必须执行commit()提交事务,否则数据库表中的数据不会发生任何变化。

方法中的参数:
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

类型 简介 JDBC 使用JDBC的提交和回滚来管理事务,即利用java.sql.Connection对象完成对事务的提交(commit())、回滚(rollback())、关闭(close())等 MANAGED MyBatis自身不会去管理事务,而是把事务交给容器托管(比如Spring、JBOSS、Weblogic容器)。默认情况会关闭连接,若不想关闭则需要如下配置:<transactionManager type="MANAGED"> <property name="closeConnection" value="false"/> </transactionManager>

(4)数据源

<dataSource type="POOLED">

type: 指定数据源类型
MyBatis中有三种数据源类型,UNPOOLED、 POOLED和JNDI:

① UNPOOLED :每次被请求时简单打开和关闭连接,需要配置的以下属性:

属性名 简介 driver JDBC驱动的Java全类名 url 数据库的JDBC URL地址 username 登陆数据库的用户名 password 登陆数据库的密码 defaultTransactionIsolationLevel 默认的连接事务隔离级别

② 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()方法,

方法 简介 T getMapper(Class type) 传入一个接口类型(接口.class)的对象,返回该接口的mapper代理对象。可以通过此mapper代理对象,来调用传入的那个接口对象中的所有方法。
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官方文档中,也是推荐使用此种方式来开发程序。

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 孩子吃了防潮剂怎么办 2k15打开闪退怎么办 辐射4空间满了怎么办 辐射4容积满了怎么办 辐射4装甲没电了怎么办 sim卡pin码忘了怎么办 安卓的se已禁用怎么办 刚拿到驾照没车怎么办 驾驶证过期了6年怎么办 驾驶证过期7个月怎么办 驾驶换证过期了怎么办 和喜欢的人聊天冷场怎么办 老公和小三有了小孩怎么办 战网账号忘记了怎么办 战网邮箱忘了怎么办 捷信分期逾期了怎么办 欠捷信7万还不了怎么办 苹果6s阴阳屏怎么办 碰到碰瓷的人怎么办 如果遇到碰瓷的怎么办 对交通事故责任认定书不服怎么办 违停15天没处理怎么办 衣服反光条掉了怎么办 脸过敏起小疙瘩怎么办 过敏怎么办怎么好得快 眉毛在眉骨下面怎么办 踩到地雷怎么办知乎 在边境踩到地雷怎么办 插在花泥里的花怎么办 瓶插绣球花蔫了怎么办 水养绣球花蔫了怎么办 鲜切绣球花蔫了怎么办 崩坏2仓库满了怎么办 dnf88级没任务了怎么办 0号柴油冻住了怎么办 不小心喝了生水怎么办 不小心吃了蟑螂怎么办 以租代购还不起怎么办 孩子被教官打了怎么办 三岁宝宝叛逆期怎么办 三岁宝宝很叛逆怎么办