![Java EE核心框架实战](https://wfqqreader-1252317822.image.myqcloud.com/cover/215/729215/b_729215.jpg)
第1章 MyBatis 3操作数据库
本章将和大家一起分享MyBatis 3框架,此框架的主要作用就是更加便携地操作数据库,比如将数据库返回的内容进行List或实体类的封装,将执行操作的SQL语句配置到XML文件中,这样做有利于代码的后期维护,使代码的分层更加明确。MyBatis框架还具有优化查询效率的缓存等功能。那么在本章中,读者应该着重掌握如下内容:
· 使用基于Eclipse的MyBatis插件执行CURD增删改查操作;
· 使用MyBatis操作常用数据库Oracle、MySQL、MsSQL;
· MyBatis框架中核心对象的生命周期;
· MyBatis结合ThreadLocal类进行CURD的封装。
1.1 MyBatis介绍
为什么要使用MyBatis框架呢?举一个最简单的例子,在使用传统的JDBC代码时,需要写上必要的DAO层代码,在DAO层代码中将数据表中的数据封装到自定义的实体类中。这给代码的维护带来了问题。但MyBatis和Hibernate解决了这样的问题,使用它们做查询时,可以自动地将数据表中的数据记录封装到实体或Map中,再将它们放入List中返回。这么常见的功能都可以由MyBatis和Hibernate自由方便地实现,可见,使用这两个框架开发应用软件会非常方便快捷。
MyBatis是一个持久化框架,它有不同的语言版本,比如.NET和Java都有MyBatis对应的类库;它有大多数ORM框架都具有的功能,比如程序员自定义的SQL语句、调用存储过程和一些高级的映射。但在这里需要说明的是,它是一种半自动化的ORM映射框架,所以使用方式和Hibernate有非常大的区别。它以SQL语句为映射基础,在使用MyBatis框架时,可以将SQL语句灵活多变的特性融入项目开发中。
另外,如果使用MyBatis这个框架,还可以省略大多数的JDBC代码,因为它把常用的JDBC操作都进行了封装,可以加快开发效率。MyBatis可以使用XML或Annotations注解的方式将数据表中的记录映射成一个Map或Java POJO实体对象,这也是现在流行ORM的技术方向。比如Hibernate和大多数JPA规范实现者都可以使用Annotations注解的方式来设计程序。
由于MyBatis框架是第三方软件,因此必须单独进行下载,下载的网址为:
http://code.google.com/p/mybatis/
打开网页后看到如图1-1所示的界面。
![](https://epubservercos.yuewen.com/193A2B/3731471403551601/epubprivate/OEBPS/Images/figure_0019_0001.jpg?sign=1739315246-O8iVoRfSFhfNfnQ41zSJPiDszBU2yCAR-0-e9f318168a25a7febf5447d008fbbf92)
图1-1 MyBatis官方网站
继续操作,单击Downloads链接,打开如图1-2所示的界面。
![](https://epubservercos.yuewen.com/193A2B/3731471403551601/epubprivate/OEBPS/Images/figure_0019_0002.jpg?sign=1739315246-W5prc9BQC8ANDznVzM93AukhQWraTtR4-0-72afca745c18d841b2ffa5834abdf476)
图1-2 准备下载MyBatis框架
此刻已经把MyBatis框架从官网下载到本地计算机中,然后就可以使用它的jar文件进行开发了。下载的zip文件包含开发PDF文档及源代码和jar文件。
1.2 MyBatis操作数据库的步骤
开门见山永远是快速学习一门技术最好的方式。
MyBatis框架的核心是SqlSessionFactory对象,从SqlSessionFactory类的名称来看,它是创建SqlSession对象的工厂。但SqlSessionFactory对象的创建来自于SqlSessionFactoryBuilder类,也就是使用SqlSessionFactoryBuilder类创建SqlSessionFactory对象。
使用SqlSessionFactoryBuilder类创建SqlSessionFactory对象的方式可以来自于一个XML配置文件,也可以来自于一个实例化的Configuration对象。
1.2.1 使用XML配置文件创建SqlSessionFactory对象
使用XML配置文件方式创建SqlSessionFactory对象的核心代码如下。
package test; import java.io.IOException; import java.io.InputStream; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; public class Test { public static void main(String[] args) { try { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder() .build(inputStream); System.out.println(sqlSessionFactory); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
上述代码的主要作用就是取得SqlSessionFactory工厂对象。下面测试代码是否能正常创建SqlSessionFactory类的实例。
其中mybatis-config.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="com.microsoft.sqlserver.jdbc.SQLServerDriver" /> <property name="url" value="jdbc:sqlserver://localhost:1079;databaseName=ghydb" /> <property name="username" value="sa" /> <property name="password" value="" /> </dataSource> </environment> </environments> </configuration>
配置文件mybatis-config.xml中主要定义的就是如何连接数据库,以及连接数据库所必备的username和password及url等参数。
项目结构如图1-3所示。
![](https://epubservercos.yuewen.com/193A2B/3731471403551601/epubprivate/OEBPS/Images/figure_0021_0001.jpg?sign=1739315246-HZx1BRqhAI6DKQWURIqVJgJvoMDRbcyN-0-5c807080d179156b7731d9a6834648c3)
图1-3 项目结构
加入当时最新版的MyBatis框架的jar包,如图1-4所示。
![](https://epubservercos.yuewen.com/193A2B/3731471403551601/epubprivate/OEBPS/Images/figure_0021_0002.jpg?sign=1739315246-2dOCDiY0E8mNMI2sAK9ZZVvDr1lJ8m5u-0-cc46b78d61497e016dbeb5e96b5dfe70)
图1-4 使用当前最新的MyBatis 3.2.2版本
运行程序后并没有出现异常,输出的信息如图1-5所示。
到此,SqlSessionFactory对象成功地从XML配置文件中创建。
![](https://epubservercos.yuewen.com/193A2B/3731471403551601/epubprivate/OEBPS/Images/figure_0021_0003.jpg?sign=1739315246-aFD7UokPQHSNViG665jvkYHKD45jFHA7-0-c6315c1473a3bdda4e6280df9b4737f9)
图1-5 输出sqlSessionFactory对象
1.2.2 SqlSessionFactoryBuilder和SqlSessionFactory类的结构
SqlSessionFactoryBuilder类的结构如图1-6所示。
![](https://epubservercos.yuewen.com/193A2B/3731471403551601/epubprivate/OEBPS/Images/figure_0021_0004.jpg?sign=1739315246-Tb4sreAnuJ1key1N82UJAoJfgTvSXHFu-0-11cc880aec48fe115244f0084cfc73d2)
图1-6 SqlSessionFactoryBuilder类的结构
SqlSessionFactory类的结构如图1-7所示。
![](https://epubservercos.yuewen.com/193A2B/3731471403551601/epubprivate/OEBPS/Images/figure_0022_0001.jpg?sign=1739315246-KjXNnqKLzZbcB3NvQ5guV73N2HEcHlfx-0-9a73b3240ce2dd148897a8f1f273a055)
图1-7 SqlSessionFactory类的结构
从图1-6和图1-7中可以看到,两者的类结构中基本上全是重载的方法,主要是为了取得SqlSessionFactory和SqlSession对象。
1.2.3 使用MyBatis Generator工具逆向
在ORM框架MyBatis中,实现数据表与JavaBean映射时,配置的代码比较复杂,这种情况也存在于Hibernate框架中,虽然MyBatis框架实现ORM的原理是使用SQL语句进行映射JavaBean,但映射的代码还是比较繁多,所以为了加快开发效率,MyBatis官方提供一个Eclipse插件,该插件主要的功能就是生成ORM映射所需要的文件,但在目前来看,此插件只支持eclipse-java-indigo-SR2以上的版本,所以笔者在这里下载了eclipse-java-indigo-SR2-win32,在线成功安装了MyBatis Generator插件,下一步就是使用此插件生成ORM映射文件了。
新建一个Java项目,然后在Java项目的src节点上右键单击,新建一个MyBatis生成ORM文件的配置文件,如图1-8所示。
![](https://epubservercos.yuewen.com/193A2B/3731471403551601/epubprivate/OEBPS/Images/figure_0022_0002.jpg?sign=1739315246-eLK2rgi5cRlxAzQmqC3vZGmml9uQVlrE-0-e104c2a48ba19182e20c99292c0c4d83)
图1-8 创建生成ORM的配置xml文件
单击Next按钮,出现如图1-9所示的界面。
在图1-9界面中,不需要更改配置,保持默认设置即可。单击Finish按钮完成配置文件的创建。
![](https://epubservercos.yuewen.com/193A2B/3731471403551601/epubprivate/OEBPS/Images/figure_0023_0001.jpg?sign=1739315246-XVyjOlioskXQdVjr1nGKdopv6zcLCBKC-0-e9bb365ff4982fe8b782f26acdd3e492)
图1-9 将文件放入src路径下即可
对生成的generatorConfig.xml配置文件代码进行如下更改。
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd" > <generatorConfiguration> <context id="generatorJava"> <jdbcConnection driverClass="com.microsoft.sqlserver.jdbc.SQLServerDriver" connectionURL="jdbc:sqlserver://localhost:1079;databaseName=ghydb" userId="sa" password="" /> <javaModelGenerator targetPackage="orm" targetProject="generatorJava" /> <sqlMapGenerator targetPackage="orm" targetProject="generatorJava" /> <javaClientGenerator targetPackage="orm" targetProject="generatorJava" type="XMLMAPPER" /> <table schema="dbo" tableName="userinfo"> </table> </context> </generatorConfiguration>
配置文件generatorConfig.xml是MyBatis Generator插件中必备的文件,通过此文件可以从数据表的结构逆向出对应的Java类,然后用MyBatis的API就可以对这些Java类进行操作,从而演变成对数据表的增删改查操作。
数据表userinfo的表结构如图1-10所示。
![](https://epubservercos.yuewen.com/193A2B/3731471403551601/epubprivate/OEBPS/Images/figure_0023_0002.jpg?sign=1739315246-NL1v5Z7iRhFjlNvqnIAt8xsmykCYwYbX-0-5f26e3c97e1db7275d8f8cf17203f4ae)
图1-10 userinfo数据表的结构
注意 需要在Java项目中添加sql驱动jar包。
准备就绪后,单击图1-11中的Generate My Batis/i BATIS Artifacts菜单。
![](https://epubservercos.yuewen.com/193A2B/3731471403551601/epubprivate/OEBPS/Images/figure_0024_0001.jpg?sign=1739315246-7jDbEd7zVbqvb3RsDtUoHuDSQzEyC1K0-0-75bcfbff44d48dfde29d99dc1363f09f)
图1-11 根据XML配置文件生成orm映射文件
成功生成orm映射文件后,项目结构如图1-12所示。
![](https://epubservercos.yuewen.com/193A2B/3731471403551601/epubprivate/OEBPS/Images/figure_0024_0002.jpg?sign=1739315246-KgNXQRO9aOc9v1qKH0q6QXoOev90XT1x-0-e6013e9996c7445661dacab360dc5a1c)
图1-12 成功生成orm映射文件
把orm包中的内容复制到MyEclipse中Web项目的src路径中,如图1-13所示。
![](https://epubservercos.yuewen.com/193A2B/3731471403551601/epubprivate/OEBPS/Images/figure_0024_0003.jpg?sign=1739315246-OZNuzTYJibon2qW8K4B4APuus5Y4xgXy-0-c9b1649ed6d264d081ffc6e15c9d0c94)
图1-13 MyEclipse中Web项目的结构
在Web项目中添加MyBatis需要的jar文件。
至此,MyBatis的基础类文件已经准备完毕。
1.2.4 使用SqlSession对象在MsSql数据库中新建记录
本节开始把一条记录插入userinfo数据表中。
在Web项目的src目录中创建mybatis-config.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="com.microsoft.sqlserver.jdbc.SQLServerDriver" /> <property name="url" value="jdbc:sqlserver://localhost:1079;databaseName=ghydb" /> <property name="username" value="sa" /> <property name="password" value="" /> </dataSource> </environment> </environments> <mappers> <mapper resource="orm/UserinfoMapper.xml" /> </mappers> </configuration>
Servlet核心代码如下。
package controller; import java.io.IOException; import java.io.InputStream; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import orm.Userinfo; public class test extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { Userinfo userinfo = new Userinfo(); userinfo.setUsername("usernameValue"); userinfo.setPassword("passwordValue"); String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder() .build(inputStream); SqlSession sqlSsession = sqlSessionFactory.openSession(); sqlSsession.insert("insert", userinfo); sqlSsession.commit(); sqlSsession.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
Servlet中的代码实现一个经典的insert数据表的功能,从代码中可以看到MyBatis用最精简的API就可以完全控制数据表中的记录,可见不管从学习、开发等方面MyBatis的成本都比较低。
运行程序后,在控制台输出如下异常信息:
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: 当IDENTITY_INSERT设置为OFF时,不能为表'userinfo'中的标识列插入显式值。
通过信息可以知道,MyBatis并没有识别userinfo数据表中主键id是自增的情况,解决办法很简单,回到eclipse,将generatorConfig.xml代码改成如下代码。
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd" > <generatorConfiguration> <context id="generatorJava"> <jdbcConnection driverClass="com.microsoft.sqlserver.jdbc.SQLServerDriver" connectionURL="jdbc:sqlserver://localhost:1079;databaseName=ghydb" userId="sa" password="" /> <javaModelGenerator targetPackage="orm" targetProject="generatorJava" /> <sqlMapGenerator targetPackage="orm" targetProject="generatorJava" /> <javaClientGenerator targetPackage="orm" targetProject="generatorJava" type="XMLMAPPER" /> <table schema="dbo" tableName="userinfo"> <generatedKey column="id" sqlStatement="sqlserver" identity="true" /> </table> </context> </generatorConfiguration>
这里添加了关键的配置代码:
<generatedKey column="id" sqlStatement="sqlserver" identity="true" />
定义主键值id是自增的。
将生成的orm包中所有内容再次复制到MyEclipse的Web项目中,再次运行Servlet,成功在数据表中添加了一条记录,如图1-14所示。
![](https://epubservercos.yuewen.com/193A2B/3731471403551601/epubprivate/OEBPS/Images/figure_0026_0001.jpg?sign=1739315246-NQTVi0HRq3zaIdlDSq5NkixWkP1Ta1vr-0-602c1853263a74fdd1406c3bdcb7c7a8)
图1-14 成功添加一条记录
1.2.5 使用SqlSession对象在Oracle数据库中新建记录
回到Eclipse,按照以下代码改动配置文件generatorConfig.xml的代码。
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd" > <generatorConfiguration> <context id="generatorJava"> <jdbcConnection driverClass="oracle.jdbc.driver.OracleDriver" connectionURL="jdbc:oracle:thin:@localhost:1522:accp11g" userId="ghy" password="123" /> <javaModelGenerator targetPackage="orm" targetProject="generatorJava" /> <sqlMapGenerator targetPackage="orm" targetProject="generatorJava" /> <javaClientGenerator targetPackage="orm" targetProject="generatorJava" type="XMLMAPPER" /> <table schema="ghy" tableName="userinfo"> <generatedKey column="id" sqlStatement="select idauto.nextval from dual" identity="false" /> </table> </context> </generatorConfiguration>、
关键配置是如下代码。
<generatedKey column="id" sqlStatement="select idauto.nextval from dual" identity="false" />
由于Oracle数据库使用序列来获取ID主键值,因此不配置上述代码在运行时会出现异常。
用Eclipse生成orm的映射文件,并复制到MyEclipse中的Web项目中,运行Servlet,在数据表中插入了新记录,并且id值由序列生成,结果如图1-15所示。
![](https://epubservercos.yuewen.com/193A2B/3731471403551601/epubprivate/OEBPS/Images/figure_0027_0001.jpg?sign=1739315246-lm73nsj5fh17kp1CQ38CV43BwIu1wYBh-0-e1a350e556cec0a6885c06f0ec079b62)
图1-15 Oracle数据表中的新记录
1.3 使用MyBatis针对3种数据库(Oracle、MSSQL和MySQL)实现CURD
前面都是使用MyBatis Generator工具生成实体和SQL映射文件,并不能从基础上讲述MyBatis框架的使用,本节将从零基础开始研究如何使用MyBatis框架针对3种主流数据库实现经典功能CURD。
1.3.1 针对Oracle的CURD
MyBatis框架针对每一种数据库的操作都大同小异,本节将用示例演示3种主流数据库的CURD操作。
1.创建userinfo数据表
创建userinfo数据表,表结构如图1-16所示。
![](https://epubservercos.yuewen.com/193A2B/3731471403551601/epubprivate/OEBPS/Images/figure_0028_0001.jpg?sign=1739315246-8zDkgEa87D0MDaKnfEriwrwdeqdyi4xC-0-d8671880a28d7a8ea7d9d0095157f36b)
图1-16 userinfo数据表的结构
2.从Eclipse产生逆向的实体类
在Eclipse中新建java项目,名称为oracleGenerator,添加MyBatis配置文件generator Config.xml,配置代码内容如下。
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd" > <generatorConfiguration> <context id="oracleGenerator"> <jdbcConnection driverClass="oracle.jdbc.driver.OracleDriver" connectionURL="jdbc:oracle:thin:@localhost:1522:accp11g" userId="ghy" password="123" /> <javaModelGenerator targetPackage="orm" targetProject="oracleGenerator" /> <sqlMapGenerator targetPackage="orm" targetProject="oracleGenerator" /> <javaClientGenerator targetPackage="orm" targetProject="oracleGenerator" type="XMLMAPPER" /> <table schema="ghy" tableName="userinfo"> <generatedKey column="id" sqlStatement="select idauto.nextval from dual" identity="false" /> </table> </context> </generatorConfiguration>
根据此配置文件会生成实体类Userinfo.java。
3.创建Web项目并配置基本开发环境
回到MyEclipse,创建一个Web项目,命名为mybatis_curd_oracle,将Eclipse项目oracle Generator中的orm包中的Userinfo.java复制到MyEclipse项目中的src路径下,如图1-17所示。
![](https://epubservercos.yuewen.com/193A2B/3731471403551601/epubprivate/OEBPS/Images/figure_0029_0001.jpg?sign=1739315246-O6vkRQRBu4dGrEDWJc6xQTmdDMLG1tZh-0-5001d1feadb35fc339333538d6f97057)
图1-17 MyEclipse中的orm包中有实体
实体类Userinfo.java的类结构如图1-18所示。
![](https://epubservercos.yuewen.com/193A2B/3731471403551601/epubprivate/OEBPS/Images/figure_0029_0002.jpg?sign=1739315246-qHiupP0M9D90QsxHE1ZRGZWIGiBWK3bV-0-9d8adb6e8b8001fa1ba6ec2377d985d4)
图1-18 Userinfo.java的类结构
在Web项目mybatis_curd_oracle中的src路径下创建连接数据库的配置文件mybatis-config. xml,代码如下。
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "mybatis-3-config.dtd"> <configuration> <environments default="development"> <environment id="development"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="oracle.jdbc.driver.OracleDriver" /> <property name="url" value="jdbc:oracle:thin:@localhost:1522:accp11g" /> <property name="username" value="ghy" /> <property name="password" value="123" /> </dataSource> </environment> </environments> <mappers> <mapper resource="userinfoMapping.xml" /> </mappers> </configuration>
其中userinfoMapping.xml映射文件的内容如下。
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "mybatis-3-mapper.dtd"> <mapper namespace="mybatis.testcurd"> <insert id="insertUserinfo" parameterType="orm.Userinfo"> <selectKey resultType="java.lang.Long" keyProperty="id" order="BEFORE"> select idauto.nextval from dual </selectKey> insert into userinfo(id,username,password,age,insertDate) values(#{id},#{username},#{password},#{age},#{insertdate}) </insert> <select id="getUserinfoById" parameterType="int" resultType="orm.Userinfo"> select * from userinfo where id=#{id} </select> <delete id="deleteUserinfoById" parameterType="int"> delete from userinfo where id=#{id} </delete> <select id="getAllUserinfo" resultType="orm.Userinfo"> select * from userinfo </select> <update id="updateUserinfoById" parameterType="orm.Userinfo"> update userinfo set username=#{username},password=#{password},age=#{age},insertDate=#{insertdate} where id=#{id} </update> </mapper>
需要特别说明的是,如果SQL语句有一些特殊字段,则必须按照如下格式使用SQL语句。
<![CDATA[ sql语句 ]]>
其中配置代码如下所示。
<selectKey resultType="java.lang.Long" keyProperty="id" order="BEFORE"> select idauto.nextval from dual </selectKey>
主要的功能是根据序列对象生成一个主键id值,并且此值还可以从代码中获取,也就是插入一条记录后代码就可以获取刚才插入记录的id值。
属性parameterType定义参数的类型,属性resultType定义返回值的类型。
继续创建测试用的Servlet对象,完整的项目结构如图1-19所示。
在图1-19中可以发现src路径下两2个dtd文件,这样为了在开发xml配置或xml映射文件时实现代码自动提示功能。
![](https://epubservercos.yuewen.com/193A2B/3731471403551601/epubprivate/OEBPS/Images/figure_0030_0001.jpg?sign=1739315246-rrV0ztqUxk9qN6o4PEvNO1QsXB1PxnzR-0-6a3bfb3de0d420234e4570410698b4af)
图1-19 完整的项目结构
4.创建获取SqlSession对象的工具类
获取SqlSession对象的工具类的核心代码如下。
package dbtools; import java.io.IOException; import java.io.InputStream; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; public abstract class GetSqlSession { public static SqlSession getSqlSession() throws IOException { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder() .build(inputStream); SqlSession sqlSsession = sqlSessionFactory.openSession(); return sqlSsession; } }
5.插入多条记录
创建Servlet,核心代码如下。
public class insertUserinfo extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { Userinfo userinfo = new Userinfo(); userinfo.setUsername("高洪岩"); userinfo.setPassword("岩洪高"); userinfo.setAge(100L); userinfo.setInsertdate(new Date()); SqlSession sqlSession = GetSqlSession.getSqlSession(); sqlSession.insert("mybatis.testcurd.insertUserinfo", userinfo); System.out.println(userinfo.getId()); sqlSession.commit(); sqlSession.close(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
变量sqlSession的insert方法的第一个参数是userinfoMapping.xml映射文件<insert>标签的id值,还要加上namespace命名空间的前缀,映射文件的部分代码如下。
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "mybatis-3-mapper.dtd"> <mapper namespace="mybatis.testcurd"> <insert id="insertUserinfo" ……>
在代码中可以看到获取已经插入数据表中记录的主键值。
执行Servlet后在控制台输出的结果如图1-20所示。
![](https://epubservercos.yuewen.com/193A2B/3731471403551601/epubprivate/OEBPS/Images/figure_0031_0001.jpg?sign=1739315246-rUMlnLuuHmOfFP6yxj3vjgWgTFCshVA3-0-ebea8f1ec3979aac36ba68e3dda801df)
图1-20 插入多条记录
Oracle数据库中userinfo数据表的内容如图1-21所示。
![](https://epubservercos.yuewen.com/193A2B/3731471403551601/epubprivate/OEBPS/Images/figure_0031_0002.jpg?sign=1739315246-OYcMwAfrTemw4hQ28wLKayjVlESSmmhc-0-f4a1be8633c08d207ab9f6001e3c207b)
图1-21 出现3条数据记录
6.根据id值查询记录
创建Servlet,核心代码如下。
public class getUserinfoById extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { SqlSession sqlSession = GetSqlSession.getSqlSession(); Userinfo userinfo = sqlSession.selectOne( "mybatis.testcurd.getUserinfoById", 7); System.out.println(userinfo.getId()); System.out.println(userinfo.getUsername()); System.out.println(userinfo.getPassword()); System.out.println(userinfo.getAge()); System.out.println(userinfo.getInsertdate().toLocaleString()); sqlSession.commit(); sqlSession.close(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
程序运行后的结果如图1-22所示。
![](https://epubservercos.yuewen.com/193A2B/3731471403551601/epubprivate/OEBPS/Images/figure_0032_0001.jpg?sign=1739315246-lHNtohBSL8ejdZy7IUCOCaDbey0vrOrF-0-3f1175dcbb115dc534c4e2ff052dd77f)
图1-22 输出id是7的信息
7.查询所有记录
创建Servlet,核心代码如下。
public class getAllUserinfo extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { SqlSession sqlSession = GetSqlSession.getSqlSession(); List<Userinfo> listUserinfo = sqlSession .selectList("mybatis.testcurd.getAllUserinfo"); for (int i = 0; i < listUserinfo.size(); i++) { Userinfo userinfo = listUserinfo.get(i); System.out.println(userinfo.getId() + " " + userinfo.getUsername() + " " + userinfo.getPassword() + " " + userinfo.getAge() + " " + userinfo.getInsertdate().toLocaleString()); } sqlSession.commit(); sqlSession.close(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
程序运行后输出3条记录,如图1-23所示。
![](https://epubservercos.yuewen.com/193A2B/3731471403551601/epubprivate/OEBPS/Images/figure_0033_0001.jpg?sign=1739315246-kOWLOEMDtpqZKnQYLnTSOfay54KVCIBG-0-73113bb4dfcc9e3ca1241bbdb4e68ee1)
图1-23 输出3条记录信息
8.更新记录
创建Servlet,核心代码如下。
public class updateUserinfoById extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { SqlSession sqlSession = GetSqlSession.getSqlSession(); Userinfo userinfo = sqlSession.selectOne( "mybatis.testcurd.getUserinfoById", 7); userinfo.setUsername("最新版高洪岩"); sqlSession.update("mybatis.testcurd.updateUserinfoById", userinfo); sqlSession.commit(); sqlSession.close(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
程序运行后数据表userinfo中的记录已更新,如图1-24所示。
![](https://epubservercos.yuewen.com/193A2B/3731471403551601/epubprivate/OEBPS/Images/figure_0033_0002.jpg?sign=1739315246-ydBpgToUKrd906Y2I2LvIT2iPRBAsPNc-0-f97f5f6a56af56ab476b2f46f2b9446d)
图1-24 userinfo数据表中内容已更新
9.删除记录
创建Servlet,核心代码如下。
public class deleteUserinfoById extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { SqlSession sqlSession = GetSqlSession.getSqlSession(); sqlSession.delete("mybatis.testcurd.deleteUserinfoById", 6); sqlSession.commit(); sqlSession.close(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
程序运行后,将id为6的记录删除了,如图1-25所示。
![](https://epubservercos.yuewen.com/193A2B/3731471403551601/epubprivate/OEBPS/Images/figure_0034_0001.jpg?sign=1739315246-zgN5rsBp9DoqCL7Jvn1xkGwd2vkebd46-0-8c871104d61b328d8b8f9094648a803a)
图1-25 无id为6的记录
到此,针对Oracle数据库的CURD操作到此结束。
1.3.2 针对MSSQL的CURD
操作MSSQL数据库和操作Oracle数据库的大体步骤相同,在SQL Server数据库中创建数据表,如图1-26所示。
![](https://epubservercos.yuewen.com/193A2B/3731471403551601/epubprivate/OEBPS/Images/figure_0034_0002.jpg?sign=1739315246-ybFZHksgAnwsggJitByxgEFu4BTLNZ5n-0-79620a59ecd9dd37d2ee4710755a9d08)
图1-26 数据表的结构
1.使用Eclipse逆向实体类
用相同的方法在Eclipse中创建Java项目,命名为mssqlGenerator,添加MyBatis生成文件,配置内容如下。
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd" > <generatorConfiguration> <context id="mssqlGenerator"> <jdbcConnection driverClass="com.microsoft.sqlserver.jdbc.SQLServerDriver" connectionURL="jdbc:sqlserver://localhost:1079;databaseName=ghydb" userId="sa" password="" /> <javaModelGenerator targetPackage="orm" targetProject="mssqlGenerator" /> <sqlMapGenerator targetPackage="orm" targetProject="mssqlGenerator" /> <javaClientGenerator targetPackage="orm" targetProject="mssqlGenerator" type="XMLMAPPER" /> <table schema="dbo" tableName="userinfo"> <generatedKey column="id" sqlStatement="sqlserver" identity="true" /> </table> </context> </generatorConfiguration>
关键代码如下。
<generatedKey column="id" sqlStatement="sqlserver" identity="true" />
它的作用是定义userinfo数据表中的id字段是自增的,不需要显式地设置值。
2.创建Web项目并搭建基本的开发环境
在MyEclipse中创建Web项目,复制Userinfo.java到Web项目中,并且创建一个连接数据库的配置文件mybatis-config.xml,代码如下。
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "mybatis-3-config.dtd"> <configuration> <environments default="development"> <environment id="development"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="com.microsoft.sqlserver.jdbc.SQLServerDriver" /> <property name="url" value="jdbc:sqlserver://localhost:1079;databaseName=ghydb" /> <property name="username" value="sa" /> <property name="password" value="" /> </dataSource> </environment> </environments> <mappers> <mapper resource="userinfoMapping.xml" /> </mappers> </configuration>
还要创建sql映射文件userinfoMapping.xml,代码如下。
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "mybatis-3-mapper.dtd"> <mapper namespace="mybatis.testcurd"> <insert id="insertUserinfo" parameterType="orm.Userinfo" useGeneratedKeys="true" keyProperty="id"> insert into userinfo(username,password,age,insertDate) values(#{username},#{password},#{age},#{insertdate}) </insert> <select id="getUserinfoById" parameterType="int" resultType="orm.Userinfo"> select * from userinfo where id=#{id} </select> <delete id="deleteUserinfoById" parameterType="int"> delete from userinfo where id=#{id} </delete> <select id="getAllUserinfo" resultType="orm.Userinfo"> select * from userinfo </select> <update id="updateUserinfoById" parameterType="orm.Userinfo"> update userinfo set username=#{username},password=#{password},age=#{age},insertDate=#{insertdate} where id=#{id} </update> </mapper>
3.添加记录并且返回主键值
创建Servlet对象,插入记录的代码和Oracle数据库对应的Servlet代码一致,运行后在控制台输出3条记录的主键ID值,结果如图1-27所示。
![](https://epubservercos.yuewen.com/193A2B/3731471403551601/epubprivate/OEBPS/Images/figure_0036_0001.jpg?sign=1739315246-r5OYgsfYPcRYPIzo5pkRIfYOMzmlstCh-0-e7d39a54492291a983844fd60288052d)
图1-27 向mssql数据库中插入3条记录
数据表userinfo中的内容如图1-28所示。
![](https://epubservercos.yuewen.com/193A2B/3731471403551601/epubprivate/OEBPS/Images/figure_0036_0002.jpg?sign=1739315246-GYsWYLZZcJaCZI5EkoPIvqszwDV8YTXi-0-fd045d5b50b8cadd9d0aae72965b56e8)
图1-28 userinfo数据表中的内容
4.其他业务方法的测试
其他业务方法的代码和操作Oracle数据库的大体一致,并且已经成功运行,具体的代码请参见本书中的源代码。
1.3.3 针对MySQL的CURD
在MySQL数据库中创建数据表userinfo,表结构如图1-29所示。
![](https://epubservercos.yuewen.com/193A2B/3731471403551601/epubprivate/OEBPS/Images/figure_0037_0001.jpg?sign=1739315246-xi17Emf7voB7SuNQJBYx3G9GF5tOJ7Wu-0-b915eeb6fa5aa1c96557dd08840d5468)
图1-29 userinfo数据表的结构
一定要勾选Auto Increment复选框,以使字段id值实现自增的效果。
1.使用Eclipse逆向实体类
在Eclipse中创建Java项目,添加逆向配置文件generatorConfig.xml,代码如下。
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd" > <generatorConfiguration> <context id="mysqlGenerator"> <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3307/ghydb" userId="root" password="123" /> <javaModelGenerator targetPackage="orm" targetProject="mysqlGenerator" /> <sqlMapGenerator targetPackage="orm" targetProject="mysqlGenerator" /> <javaClientGenerator targetPackage="orm" targetProject="mysqlGenerator" type="XMLMAPPER" /> <table schema="ghydb" tableName="userinfo"> <generatedKey column="id" sqlStatement="mysql" identity="true" /> </table> </context> </generatorConfiguration>
2.创建Web项目并搭建基本的开发环境
在MyEclipse中创建Web项目,命名为mybatis_curd_mysql,复制Userinfo.java实体类,并且创建一个连接数据库的配置文件mybatis-config.xml,代码如下。
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "mybatis-3-config.dtd"> <configuration> <environments default="development"> <environment id="development"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3307/ghydb" /> <property name="username" value="root" /> <property name="password" value="123" /> </dataSource> </environment> </environments> <mappers> <mapper resource="userinfoMapping.xml" /> </mappers> </configuration>
还要创建SQL映射文件userinfoMapping.xml,代码如下。
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "mybatis-3-mapper.dtd"> <mapper namespace="mybatis.testcurd"> <insert id="insertUserinfo" parameterType="orm.Userinfo" useGeneratedKeys="true" keyProperty="id"> insert into userinfo(username,password,age,insertDate) values(#{username},#{password},#{age},#{insertdate}) </insert> <select id="getUserinfoById" parameterType="int" resultType="orm.Userinfo"> select * from userinfo where id=#{id} </select> <delete id="deleteUserinfoById" parameterType="int"> delete from userinfo where id=#{id} </delete> <select id="getAllUserinfo" resultType="orm.Userinfo"> select * from userinfo </select> <update id="updateUserinfoById" parameterType="orm.Userinfo"> update userinfo set username=#{username},password=#{password},age=#{age},insertDate=#{insertdate} where id=#{id} </update> </mapper>
MySQL和MSSQL数据库生成主键的映射代码一致。
3.添加记录并且返回主键值
创建Servlet对象,插入记录的代码和Oracle数据库对应的Servlet代码一致,运行后在控制台输出3条记录的主键ID值,结果如图1-30所示。
![](https://epubservercos.yuewen.com/193A2B/3731471403551601/epubprivate/OEBPS/Images/figure_0039_0001.jpg?sign=1739315246-ROibJnKp4FRBSVQYLx2oeMfBlADvhr5b-0-f9189b03a2828109110eb09496904607)
图1-30 向mysql数据库中插入4条记录
数据表userinfo中的内容如图1-31所示。
![](https://epubservercos.yuewen.com/193A2B/3731471403551601/epubprivate/OEBPS/Images/figure_0039_0002.jpg?sign=1739315246-Jl9DVqVBbrNo3u6Pjj5ww40lQk8t0nHF-0-65b699ef104456117f34773044445ca8)
图1-31 数据表userinfo中的4条记录
4.其他业务方法的测试
其他业务方法的代码和操作Oracle数据库的大体一致,并且已经成功运行,具体的代码请参见本书中的源代码。
1.4 MyBatis核心对象的生命周期与封装
在前面对3种数据库实现基本的CURD后,读者应该了解了MyBatis核心对象的使用,本节将会继续介绍这些核心对象的生命周期。
对象的生命周期也就是对象从创建到销毁的过程,但在此过程中,如果实现的代码质量不佳,那么很容易造成程序上的错误或效率的降低。
(1)SqlSessionFactoryBuilder对象可以被JVM虚拟机所实例化、使用或者销毁。一旦使用SqlSessionFactoryBuilder对象创建SqlSessionFactory后,SqlSessionFactoryBuilder类就不需要存在了,也就是,不需要保持此对象的状态,可以随意地任由JVM销毁。因此SqlSession FactoryBuilder对象的最佳使用范围是方法之内,也就是说,可以在方法内部声明SqlSessionFactoryBuilder对象来创建SqlSessionFactory对象。
(2)SqlSessionFactory对象由SqlSessionFactoryBuilder对象创建。一旦创建SqlSessionFactory类的实例,该实例应该在应用程序执行期间都存在,根本不需要每一次操作数据库时都重新创建它,所以应用它的最佳方式就是写一个单例模式,或使用Spring框架来实现单例模式对SqlSessionFactory对象进行有效的管理。
(3)SqlSession对象由SqlSessionFactory类创建,需要注意的是,每个线程都应该有它自己的SqlSession实例。SqlSession的实例不能共享,它也是线程不安全的,所以千万不要在Servlet中声明该对象的一个实例变量。因为Servlet是单例的,声明成实例变量会造成线程安全问题,也绝不能将SqlSession实例的对象放在一个类的静态字段甚至是实例字段中,还不可以将SqlSession实例的对象放在任何类型的管理范围中,比如Servlet对象中的HttpSession会话。在接收到HTTP请求时,可以打开一个SqlSession对象操作数据库,然后返回响应,就可以关闭它。关闭SqlSession很重要,应该确保使用finally块来关闭它。下面的示例就是一个确保SqlSession对象正常关闭的基本模式代码。
public class insertUserinfo extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { SqlSession sqlSession = GetSqlSession.getSqlSession(); try { // sqlSession curd code sqlSession.commit(); } catch (Exception e) { e.printStackTrace(); } finally { sqlSession.close(); } } }
1.4.1 创建GetSqlSessionFactory.java类
根据前面学习过的生命周期的知识,在后面的章节中将对MyBatis核心代码进行封装,这样更有助于对数据执行CURD操作。创建Web项目,命名为mybatis_threadlocal。
创建GetSqlSessionFactory.java类,完整代码如下。
package dbtools; import java.io.IOException; import java.io.InputStream; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; public class GetSqlSessionFactory { private static SqlSessionFactory sqlSessionFactory; private GetSqlSessionFactory() { } synchronized public static SqlSessionFactory getSqlSessionFactory() { try { if (sqlSessionFactory == null) { String resource = "mybatis-config.xml"; InputStream inputStream = Resources .getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder() .build(inputStream); } else { } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return sqlSessionFactory; } }
在GetSqlSessionFactory.java类中使用单例的设计模式来获取SqlSessionFactory对象。
1.4.2 创建GetSqlSession.java类
创建GetSqlSession.java类的核心代码如下。
package dbtools; import org.apache.ibatis.session.SqlSession; public class GetSqlSession { private static ThreadLocal<SqlSession> tl = new ThreadLocal<SqlSession>(); public static SqlSession getSqlSession() { SqlSession sqlSession = tl.get(); if (sqlSession == null) { sqlSession = GetSqlSessionFactory.getSqlSessionFactory() .openSession(); tl.set(sqlSession); } else { } System.out.println("获得的sqlSession对象的hashCode:" + sqlSession.hashCode()); return sqlSession; } public static void commit() { if (tl.get() != null) { tl.get().commit(); tl.get().close(); tl.set(null); System.out.println("提交了"); } } public static void rollback() { if (tl.get() != null) { tl.get().rollback(); tl.get().close(); tl.set(null); System.out.println("回滚了"); } } }
1.4.3 创建DBOperate.java类
创建DBOperate.java类的核心代码如下。
package dbtools; import java.util.List; import java.util.Map; import org.apache.ibatis.session.SqlSession; public class DBOperate { public int insert(String sql, Map valueMap) { SqlSession sqlSession = GetSqlSession.getSqlSession(); return sqlSession.insert(sql, valueMap); } public int delete(String sql, Map valueMap) { SqlSession sqlSession = GetSqlSession.getSqlSession(); return sqlSession.delete(sql, valueMap); } public int update(String sql, Map valueMap) { SqlSession sqlSession = GetSqlSession.getSqlSession(); return sqlSession.update(sql, valueMap); } public List<Map> select(String sql, Map valueMap) { SqlSession sqlSession = GetSqlSession.getSqlSession(); return sqlSession.selectList(sql, valueMap); } }
所有CURD的参数值都用Map对象进行封装,所以要查看SQL映射文件中的代码。
1.4.4 创建userinfoMapping.xml映射文件
创建userinfoMapping.xml映射文件的代码如下。
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "mybatis-3-mapper.dtd"> <mapper namespace="mybatis.testcurd"> <insert id="insertUserinfo" parameterType="map" useGeneratedKeys="true" keyProperty="id"> insert into userinfo(username,password,age,insertDate) values(#{username},#{password},#{age},#{insertdate}) </insert> <select id="getUserinfoById" parameterType="map" resultType="map"> select * from userinfo where id=#{id} </select> <delete id="deleteUserinfoById" parameterType="map"> delete from userinfo where id=#{id} </delete> <select id="getAllUserinfo" resultType="map"> select * from userinfo </select> <update id="updateUserinfoById" parameterType="map"> update userinfo set username=#{username},password=#{password},age=#{age},insertDate=#{insertdate} where id=#{id} </update> </mapper>
1.4.5 创建连接数据库的mybatis-config.xml配置文件
创建连接数据库的mybatis-config.xml配置文件,代码如下。
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "mybatis-3-config.dtd"> <configuration> <environments default="development"> <environment id="development"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="com.microsoft.sqlserver.jdbc.SQLServerDriver" /> <property name="url" value="jdbc:sqlserver://localhost:1079;databaseName=ghydb" /> <property name="username" value="sa" /> <property name="password" value="" /> </dataSource> </environment> </environments> <mappers> <mapper resource="userinfoMapping.xml" /> </mappers> </configuration>
1.4.6 创建名为test的Servlet对象
该对象的主要作用就是测试在一个请求中多次获取的SqlSession对象是不是同一个,核心代码如下。
public class test extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { GetSqlSession.getSqlSession(); GetSqlSession.getSqlSession(); GetSqlSession.getSqlSession(); GetSqlSession.getSqlSession(); GetSqlSession.getSqlSession(); } }
运行程序后,在控制台输出的信息如图1-32所示。
![](https://epubservercos.yuewen.com/193A2B/3731471403551601/epubprivate/OEBPS/Images/figure_0044_0001.jpg?sign=1739315246-18NAnyLoShiaAmfK85p0Gsn47Yaj9sLD-0-c7238df84d80eb33fd270354513669ce)
图1-32 获得的SqlSession对象是同一个
1.4.7 添加记录及异常回滚的测试
添加记录及异常回滚的测试,核心代码如下。
public class insert extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { HashMap valueMap1 = new HashMap(); valueMap1.put("username", "高洪岩今天1"); valueMap1.put("password", "高洪岩明天1"); valueMap1.put("age", 100); valueMap1.put("insertdate", new Date()); HashMap valueMap2 = new HashMap(); valueMap2.put("username", "高洪岩今天2"); valueMap2.put("password", "高洪岩明天2"); valueMap2.put("age", 100); valueMap2.put("insertdate", new Date()); DBOperate dbo = new DBOperate(); dbo.insert("insertUserinfo", valueMap1); dbo.insert("insertUserinfo", valueMap2); } catch (Exception e) { e.printStackTrace(); GetSqlSession.rollback(); } finally { GetSqlSession.commit(); } } }
运行程序后,在控制台输出的信息如图1-33所示。
![](https://epubservercos.yuewen.com/193A2B/3731471403551601/epubprivate/OEBPS/Images/figure_0045_0001.jpg?sign=1739315246-55r1ktMXQMDZ55rUHYNLDWe5HxWUB4oF-0-1ed230f6d58c4f6291d2d206e997954f)
图1-33 控制台输出的信息
数据表中的数据如图1-34所示。
![](https://epubservercos.yuewen.com/193A2B/3731471403551601/epubprivate/OEBPS/Images/figure_0045_0002.jpg?sign=1739315246-JN7GegJrasAkk4Tg1Uil5m7zHSTg6H0S-0-98db831105ac9a1e8dae5b1e70d28beb)
图1-34 成功添加两条记录
上面的步骤证明添加多条记录成功,userinfo数据表中有两条记录。再来测试异常回滚的情况,更改部分的代码如下。
HashMap valueMap2 = new HashMap(); valueMap2.put("username", "高洪岩今天2_123456789_123456789_123456789_123456789_123456789"); valueMap2.put("password", "高洪岩明天2"); valueMap2.put("age", 100); valueMap2.put("insertdate", new Date());
运行程序后,在控制台输出的异常信息如下。
获得的sqlSession对象的hashCode:24442607 获得的sqlSession对象的hashCode:24442607 org.apache.ibatis.exceptions.PersistenceException: ### Error updating database. Cause: com.microsoft.sqlserver.jdbc.SQLServerException: 将 截断字符串或二进制数据。 ### The error may involve mybatis.testcurd.insertUserinfo-Inline ### The error occurred while setting parameters ### SQL: insert into userinfo(username,password,age,insertDate) values(?,?,?,?) ### Cause: com.microsoft.sqlserver.jdbc.SQLServerException: 将截断字符串或二进制数据。 at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory. java:23) at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession. java:147) at org.apache.ibatis.session.defaults.DefaultSqlSession.insert(DefaultSqlSession. java:134) at dbtools.DBOperate.insert(DBOperate.java:12) at controller.insert.doGet(insert.java:36) at javax.servlet.http.HttpServlet.service(HttpServlet.java:690) rotocol.java:624) at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:445) at java.lang.Thread.run(Thread.java:619) Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: 将截断字符串或二进制数据。 at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession. java:145) ... 17 more 回滚了
通过上面的信息可以得知,程序出现异常,并且已经回滚,那userinfo数据表中是否还存在两条记录呢?查看userinfo数据表,其内容如图1-35所示。
![](https://epubservercos.yuewen.com/193A2B/3731471403551601/epubprivate/OEBPS/Images/figure_0046_0001.jpg?sign=1739315246-BJ7bu6drCRb9oduBAulXBuyAo1V7pmKT-0-1065c2213389ca90ab9cb695721d9ce4)
图1-35 成功回滚后还是两条记录
在userinfo数据表中多添增几条记录,便于后面的测试,新增的记录如图1-36所示。
![](https://epubservercos.yuewen.com/193A2B/3731471403551601/epubprivate/OEBPS/Images/figure_0046_0002.jpg?sign=1739315246-1yZcBvNw06SaPtAzO5KX6Yp762aItyjX-0-bd659b6535b7c1d53995410988750c4f)
图1-36 userinfo表中的多条记录
1.4.8 删除记录
删除记录,核心代码如下。
public class delete extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { HashMap valueMap1 = new HashMap(); valueMap1.put("id", 44); DBOperate dbo = new DBOperate(); dbo.delete("deleteUserinfoById", valueMap1); } catch (Exception e) { e.printStackTrace(); GetSqlSession.rollback(); } finally { GetSqlSession.commit(); } } }
运行程序后,userinfo数据表中的记录如图1-37所示。
![](https://epubservercos.yuewen.com/193A2B/3731471403551601/epubprivate/OEBPS/Images/figure_0047_0001.jpg?sign=1739315246-ftRZK5vmLfhXXdO7hEH2J9VsJN5VmEnL-0-4b7c348d24fe871dc532a8a33f279c3d)
图1-37 成功删除id为44的记录
1.4.9 更改记录
更改记录,核心代码如下。
public class update extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { HashMap valueMap1 = new HashMap(); valueMap1.put("id", 45); valueMap1.put("username", "高洪岩今天3new"); valueMap1.put("password", "高洪岩明天3new"); valueMap1.put("age", 100); valueMap1.put("insertdate", new Date()); DBOperate dbo = new DBOperate(); dbo.update("updateUserinfoById", valueMap1); } catch (Exception e) { e.printStackTrace(); GetSqlSession.rollback(); } finally { GetSqlSession.commit(); } } }
运行程序后,userinfo表中的数据如图1-38所示。
![](https://epubservercos.yuewen.com/193A2B/3731471403551601/epubprivate/OEBPS/Images/figure_0048_0001.jpg?sign=1739315246-gGgBs5vSom2JZMlP6S8VjnmUAgzVr2h1-0-ad6d2aaf9b85940555887c996b9eb0b4)
图1-38 userinfo表中的记录
1.4.10 查询单条记录
查询单条记录,核心代码如下。
public class getUserinfoById extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { HashMap valueMap1 = new HashMap(); valueMap1.put("id", 39); DBOperate dbo = new DBOperate(); List<Map> list = dbo.select("getUserinfoById", valueMap1); for (int i = 0; i < list.size(); i++) { Map rowMap = list.get(i); System.out.println(rowMap.get("id") + "_" + rowMap.get("username") + "_" + rowMap.get("password") + "_" + rowMap.get("age") + "_" + rowMap.get("insertDate")); } } catch (Exception e) { e.printStackTrace(); GetSqlSession.rollback(); } finally { GetSqlSession.commit(); } } }
运行程序后,在控制台输出如图1-39所示的结果。
![](https://epubservercos.yuewen.com/193A2B/3731471403551601/epubprivate/OEBPS/Images/figure_0048_0002.jpg?sign=1739315246-dLH1F3jfOHOnrvYJ7JwgNoYmzWMlZiJg-0-3fb6d4727fc3ff528866c8a5bb3d2d1c)
图1-39 控制台输出的信息
1.4.11 查询多条记录
查询多条记录,核心代码如下。
public class getAllUserinfo extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { DBOperate dbo = new DBOperate(); List<Map> list = dbo.select("getAllUserinfo", null); for (int i = 0; i < list.size(); i++) { Map rowMap = list.get(i); System.out.println(rowMap.get("id") + "_" + rowMap.get("username") + "_" + rowMap.get("password") + "_" + rowMap.get("age") + "_" + rowMap.get("insertDate")); } } catch (Exception e) { e.printStackTrace(); GetSqlSession.rollback(); } finally { GetSqlSession.commit(); } } }
运行程序后,控制台的输出如图1-40所示。
![](https://epubservercos.yuewen.com/193A2B/3731471403551601/epubprivate/OEBPS/Images/figure_0049_0001.jpg?sign=1739315246-tT4uSDTV5bqtITm6N8QiTOH1YCqMpE52-0-44ebc0738fa16b8de19452d9fb877719)
图1-40 控制台输出的多条记录信息
ORM框架MyBatis介绍到这里,读者应该能熟练地使用它进行数据库的CURD操作,并且对核心API在使用上有一个了解。