java mybatis教程(JavaEE核心框架实战MyBatis的基本使用步骤)
java mybatis教程(JavaEE核心框架实战MyBatis的基本使用步骤)也就是在使用MyBatis框架时 可以将Java类转化成数据表中的记录 或者将数据表中的记录转化成Java类 内部的技术原理其实就是JDBC 反射。这些功能都是由ORM框架来进行处理的 MyBatis可以实现这样的功能。MyBatis有不同的语言版本 比如.Net和Java都有对应的类库 它有大多数ORM框架都具有的功能 比如可以自定义SQL语句、调用存储过程、进行高级映射等。从小的方面来说 1个类中的属性对应1个表中的列。为什么要使用MyBatis框架呢?这个答案真的有很多 作者认为其中最具有代表性的就是在使用传统的JDBC代码时 需要写上必要的DAO层代码 在DAO层的查询代码中将数据表中的数据封装到自定义的实体类中。这样的代码写法在软件开发的过程中非常不便 因为大部分的代码都是重复冗余的 几乎每个DAO类都在做同样的事情 但MyBatis解决了这类问题。使用MyBatis做查询时可以
本章讲解的是MyBatis 3框架 此框架的主要作用就是更加便携地操作数据库 比如可以将ResultSet对象返回的数据自动封装进Entity实体类或List中 可以把SQL语句配置到XML文件中 也就是将SQL语句与*Java文件进行分离 有利于代码的后期维护 也使代码的分层更加明确。另外由于mybatis框架是使用SQL语句对数据库进行操作的 所以可以单独对SQL语句进行优化 以提高查询效率 这点与使用Hibernate框架相比有很大的优势 这也是为什么现阶段大部分的软件企业逐步用MyBatis替换掉Hibernate框架的主要原因。
MyBatis是一个操作数据库的框架 那什么是框架?框架就是软件功能的半成品。框架提供了一个软件项目中通用的功能 将大多数常见的功能进行封装 无需自己重复开发 框架增加了开发及运行效率。
需要说明的是 MyBatis并不是一个独立的技术 它内部操作数据库的原理还是使用JDBC 只是对JDBC进行了轻量级的封装 便于程序员更方便地设计代码去操作数据库。
1.1 MyBatis介绍
为什么要使用MyBatis框架呢?这个答案真的有很多 作者认为其中最具有代表性的就是在使用传统的JDBC代码时 需要写上必要的DAO层代码 在DAO层的查询代码中将数据表中的数据封装到自定义的实体类中。这样的代码写法在软件开发的过程中非常不便 因为大部分的代码都是重复冗余的 几乎每个DAO类都在做同样的事情 但MyBatis解决了这类问题。使用MyBatis做查询时可以自动将数据表中的数据记录封装到实体类或Map中 再将它们放入List进行返回 这么常见而且有利于提高开发效率的功能MyBatis都可以自由方便地处理。从此观点来看 使用MyBatis框架去开发应用软件是非常方便快捷 MyBatis框架很有使用的必要性。
MyBatis是一个“持久化ORM框架" 持久化是指内存中的数据保存到硬盘上。ORM是对象关系映射(Object Relation Mapping ) ORM的概念可以从2个方面来介绍:
从大的方面来说 1个类对应表中的1行;
从小的方面来说 1个类中的属性对应1个表中的列。
也就是在使用MyBatis框架时 可以将Java类转化成数据表中的记录 或者将数据表中的记录转化成Java类 内部的技术原理其实就是JDBC 反射。这些功能都是由ORM框架来进行处理的 MyBatis可以实现这样的功能。MyBatis有不同的语言版本 比如.Net和Java都有对应的类库 它有大多数ORM框架都具有的功能 比如可以自定义SQL语句、调用存储过程、进行高级映射等。
下面来看一下ORM框架的技术原理 使用如下的代码进行实现。
创建类Userinfo.java代码如下:
package entity;
public class Userinfo {
private long id;
private string username;
private string password;
public Userinfo(){
}
public Userinfo(long id String username string password) {
super();
this.id = id;
this.username =username;
this.password = password;
}
//get和set方法忽略
}
运行类代码如下:
package test;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import entity.Userinfo;
public class Test {
public static void main(String[] args) throws IllegalArgumentException IllegalAccessException{
Userinfo userinfo = new Userinfo();
userinfo.setId(100);
userinfo.setusername ("中国");
userinfo.setPassword("大中国");
List valuelist = new ArrayList();
string sq1 ="insert into ";
sq1 =sql userinfo.getClass().getSimpleName().toLowerCase();
string colsql="";
string valuesql="";
Field[] fieldArray = userinfo.getclass() .getDeclaredFields();
for (int i =0; i < fieldArray.length; i ) {
Field eachField = fieldArray[i];
eachField.setAccessible(true);
string fieldName = eachField.getName();
co1Sq1 =colsq1 "," fieldName;
valuesql = valuesql ",?";
Obiect value =fieldArray [i].get (userinfo);
valuelist. add(value);
}
colSql = colSql.substring(1);
valueSql =valueSql.substring(1);
colSql = "(" colSql ")";
valuesql = "(" valuesql ")";
sq1=sq1 colsql "" valuesql;
System.out.println(sql);
System.out.println();
for (int i=0; i < valuelist.size(); i ){
Obiect value = valueList. get(i);
System.out.printin(value);
}
}
}
程序运行后在控制台打印信息如下”
insertintouserinfo(id username password) (? ? ?)
100
中国
大中国
这就是将一个Userinfo.java对象转成添加到userinfo数据表的SQL语句 也是ORM框架的原理。
但更严格来讲 MyBatis是一种“半自动化"的ORM映射框架 它应该算作SQL映射框架(SQL mapperframework) 官方也是这么介绍的 将MyBatis称为“半自动化的ORM框架"。这是因为MyBatis操作数据库时还是使用原始的SQL语句 这些SQL语句还是需要程序员自己来进行设计 这就是半自动化 只不过把重复的JDBC代码进行了封装与简化。在使用的方式上和全自动的ORM框架Hibernate有着非常大的区别
MyBatis是以SQL语句为映射基础 而Hibernate是彻底的基干实体类与表进行映射 基本是属千全自动化的ORM映射框架。但正是MyBatis属于半自动化的ORM映射框架这个特性 所以可以将SQL语句灵活多变的特性溶入到项目开发中。
另外 如果使用MyBatis框架 还可以省略大多数的JDBC代码 因为它把常用的JDBC操作都进行了封装 进而可以加快开发效率。MyBatis可以使用XML或Annotations注解的方式将数据表中的记录映射成1个Map或Java POJOs实体对象。但还是推荐使用XML的方式 该方式也是MyBatis官方推荐的。
由于MyBatis是第三方的框架 javaee.jar中并不包含它的API 所以得单独进行下载。
打开网页后看到的界面如图1-1所示:
图1-1 MyBatis官方网站
继续操作,单击Download Lates链接后打开的界面如图1-2所示。
图1-2 准备下载MyBatis框架
到这一步已经把MyBatis框架从官网下载到本地,然后就可以使用它的jar文件进行开发了。下载的zip压缩文件中包含开发时要用到的PDF文档、source源代码和jar文件等资源。
1.2 MyBatis基本使用
开门见山永远是快速学习一门技术最好的方式。
MyBatis框架的核心是SqlSessionFactory对象 从SqlSessionFactory类的名称来看 它是创建SqlSession对象的工厂。但SqlSessionFactory对象的创建来自于SqlSessionFactoryBuilder类 也就是使用SqlSessionFactoryBuilder类创建出SqlSessionFactory对象。
这3者之间的创建关系为: SqlSessionFactoryBuilder创建出SqlSessionFactory SqlSessionFactory创建出SqlSession。
使用SqlSessionFactoryBuilder类创建SqlSessionFactory对象的方式可以来自于1个XML配置文件 还可以来自于1个实例化的configuration对象 由于使用XML方式创建SqlSessionFactory对象在使用上比较广泛 所以在下面的小节就介绍这些内容。
1.2.1使用XML配置文件创建SqlSessionFactory对象
创建名称为mybatis1的Web项目。
想要使用MyBatis实现CURD的操作 必须先要创建出SqISessionFactory对象。
根据XML文件中的配置创建SqISessionFactory对象的核心Test.java类的代码如下。
packagetest;
importjava.io.IOException;
importjava.io.InputStream;
importorg.apache.ibatis.io.Resources;
importorg.apache.ibatis.session.SqlSessionFactory;
importorg.apache.ibatis.session.SqlSessionFactoryBuilder;
publicclassTest{
publicstaticvoidmain(String[] args) {
try{
Stringresource = "mybatis-config.xml";
InputStreaminputStream = Resources.getResourceAsStream(resource);
SqlSessionFactorysqlSessionFactory = newSqlSessionFactoryBuilder()
.build(inputStream);
System.out.println(sqlSessionFactory);
} catch(IOExceptione) {
// TODOAuto-generated catch block
e.printStackTrace();
}
}
}
上面代码的主要作用就是取得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>
<environmentsdefault="development">
<environmentid="development">
<transactionManagertype="JDBC"/>
<dataSourcetype="POOLED">
<propertyname="driver"value="${driver}"/>
<propertyname="url"value="${url}"/>
<propertyname="username"value="${username}"/>
<propertyname="password"value="${password}"/>
</dataSource>
</environment>
</environments>
</configuration>
配置文件mybatis-config.xml主要作用就是如何连接数据库 包含连接数据库所用到的username和password及url等参数 但并没有实质的属性值 而是使用${xxxx}做为替代。因为在获取SqlSessionFactory工厂对象时 不需要提供这些具体的参数值。
添加最新版的jar包的项目结构如图1-3所示。
图1-3 项目结构
来测试一下代码是否能正确创建出SqlSessionFactory类的实例,运行程序后并没有出现异常,输出信息如图1-4所示。
图1-4 输出SqlSessionFactory对象
DefaultSqlSessionFactory.java是SqlSessionFactory.java接口的实现类,具有实现关系,效果如图1-5所示。
图1-5 实现关系
到此,SqlSessionFactory对象来自于XML配置文件创建成功。
1.2.2 SqlSessionFactoryBuilder和SqlSessionFactory类信息
虽然现在正在学习新的知识 包括要熟悉新的类名 新的方法名称 新的包名等,但MyBatis在API的设计结构上是相当简洁的 大部分都是重载的方法。我们来看一看SqlSessionFactoryBuilder类的结构 效果如图1-6所示。
图1-6 SqlSessionFactoryBuilder类结构
SqlSessionFactory类的结构如图1-7所示。
图1-7 SqlSessionFactory类结构
从图1-6和图1-7可以看到 两者的类结构中基本全是重载的方法 主要就是通过build()方法取得SqlSessionFactory对象 使用openSession()方法取得SqlSession对象 对象SqlSession主要的作用是对数据库进行CURD操作。
1.2.3使用MyBatis Generator工具逆向操作Oracle数据库
使用MyBatis实现操作数据库要使用到SQL映射文件 但该文件的配置代码比较复杂 这种情况也存在于Hibernate框架中 所以为了加快开发效率 MyBatis官方提供1个Eclipse插件 名称为MyBatis Generator 该插件主要的功能就是生成SQL映射文件。此插件需要在Eclipse中在线安装 安装的过程请参考搜索引擎提供的资料 下面来看此插件的使用。
新建名为GeneratorOracle的Web项目 然后在Java项目的src结点下单击鼠标右键新建1个MyBatis的Generator配置文件 如图1-8所示。
图1-8 创建生成ORM的配置XML文件
单击"Next"按钮出现如图1-9所示界面。
在图1-9界面中不需要更改配置 保持默认设置即可 单击"Finish"按钮完成Generator配置文件的创建。
图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>
<contextid="context1">
<jdbcConnectionconnectionURL="jdbc:oracle:thin:@localhost:1521:orcl"driverClass="oracle.jdbc.OracleDriver"password="123"userId="y2"/>
<javaModelGeneratortargetPackage="sqlmapping"
targetProject="GeneratorOracle"/>
<sqlMapGeneratortargetPackage="sqlmapping"
targetProject="GeneratorOracle"/>
<javaClientGeneratortargetPackage="sqlmapping"
targetProject="GeneratorOracle"type="XMLMAPPER"/>
<tableschema="y2"tableName="userinfo">
</table>
</context>
</generatorConfiguration>
配置文件generatorConfig.xml是MyBatis Generator插件中必备的文件 通过此文件可以将数据表的结构逆向出对应的Java类以及存储SQL语句的SQL映射文件 然后用MyBatis的API就可以对这些Java类进行操作 从而演变成对数据表的增删改查操作。
数据表userinfo的表结构如图1-10所示。
图1-10 userinfo数据表结构
配置文件generatorConfig.xml准备就绪后单击图1-11中的菜单。
图1-11 根据XML配置文件生成ORM映射文件
这里却出现了异常情况,效果如图1-12所示。
图1-12 找不到JDBC驱动
下一步就要在Run As中添加JDBC驱动,单击如图1-13所示的菜单。
图1-13 在Run As中配置JDBC驱动
弹出配置界面如图1-14所示,按(1)、(2)、(3)、(4)的步骤将ojdbc6.jar添加到classpath中。
图1-14 添加驱动jar包
驱动jar包添加成功后单击右下角的 Run按钮开始逆向,逆向后的项目结构如图1-15所示。
图1-15 成功生成ORM映射文件
文件UserinfoMapper.java中出现了异常,原因是并没有添加MyBatis的jar包,添加成功后java文件不再出现红叉,如图1-16所示。
图1-16 MyEclipse中Web项目结构
至此MyBatis操作数据库的基础文件已经准备完毕。
下面开始在Oracle数据库的userinfo数据表中添加1条记录。
在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>
<environmentsdefault="development">
<environmentid="development">
<transactionManagertype="JDBC"/>
<dataSourcetype="POOLED">
<propertyname="driver"value="oracle.jdbc.OracleDriver"/>
<propertyname="url"value="jdbc:oracle:thin:@localhost:1521:orcl"/>
<propertyname="username"value="y2"/>
<propertyname="password"value="123"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapperresource="sqlmapping/UserinfoMapper.xml"/>
</mappers>
</configuration>
注意:在mybatis-config.xml配置文件中添加如下配置。
<mappers>
<mapperresource="sqlmapping/UserinfoMapper.xml"/>
</mappers>
文件UserinfoMapper.xml中存储着SQL语句,所以在配置文件中需要关联。
创建Test.java运行类代码如下。
packagetest;
importjava.io.IOException;
importjava.io.InputStream;
importorg.apache.ibatis.io.Resources;
importorg.apache.ibatis.session.SqlSession;
Importorg.apache.ibatis.session.SqlSessionFactory;
importorg.apache.ibatis.session.SqlSessionFactoryBuilder;
importsqlmapping.Userinfo;
publicclassTest{
publicstaticvoidmain(String[] args) {
try{
Userinfo userinfo = newUserinfo();
userinfo.setUsername("usernameValue");
userinfo.setPassword("passwordValue");
userinfo.setAge(100L);
Stringresource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = newSqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
sqlSession.insert("insert" userinfo);
sqlSession.commit();
sqlSession.close();
} catch(IOException e) {
// TODOAuto-generated catch block
e.printStackTrace();
}
}
}
方法main()中的代码是一个经典的insert数据表的功能 从代码中可以看到MyBatis用最精简的API就可以完全地控制数据表中的记录 可见MyBatis不管是在学习还是开发等方面成本都是比较低的。
程序运行后在控制台打印出的异常信息如下。
Caused by: java.sql.SQLException: Error setting driver on UnpooledDataSource. Cause:
java.lang.ClassNotFoundException: Cannot find class: oracle.jdbc.OracleDriver。
异常信息提示该项目中并没有添加JDBC的驱动jar文件 添加ojdbc6jar并将其添加进classpath中再运行Test.java时依然出现了异常提示 如图1-17所示。
图1-17不能对id主键列赋nu1l值
Oracle数据库的主键并不是自增的 在insert语句中需要结合序列来实现添加记录的功能 逆向生成错误的insert语句如图1-18所示。
图1-18 SQL语句中没有使用序列
这说明sqlmapping包中的文件都是错误的 所以需要连同sqlmapping包与下面的所有文件一同进行删除 因为要重新进行逆向了。
在逆向之前需要更改generatorConfig.xml配置文件中的配置 添加<generatedKey>标签后的配置代码如下。
<?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>
<contextid="context1">
<jdbcConnectionconnectionURL="jdbc:oracle:thin:@localhost:1521:orcl"driverClass="oracle.jdbc.OracleDriver"password="123"userId="y2"/>
<javaModelGeneratortargetPackage="mapping"
targetProject="GeneratorOracle"/>
<sqlMapGeneratortargetPackage="mapping"
targetProject="GeneratorOracle"/>
<javaClientGeneratortargetPackage="mapping"
targetProject="GeneratorOracle"type="XMLMAPPER"/>
<tableschema="y2"tableName="userinfo">
<generatedKeycolumn="id"sqlStatement="select idauto.nextval from dual"
identity="false"/>
</table>
<tableschema="y2"tableName="A">
<generatedKeycolumn="id"sqlStatement="select idauto.nextval from dual"
identity="false"/>
</table>
<tableschema="y2"tableName="B">
<generatedKeycolumn="id"sqlStatement="select idauto.nextval from dual"
identity="false"/>
</table>
</context>
</generatorConfiguration>
配置文件generatorConfig.xml准备结束后重新进行逆向操作 在sqlmapping包中生成最新版正确的.java和xml文件 最新版的insert语句如图1-19所示。
图1-19 新版的insert语句
再次运行Test.java类,成功在数据表中添加了1条记录,如图1-20所示。
图1-20 成功添加1条记录
1.2.4使用MyBatis Generator工具逆向操作MySQL数据库
MySQL数据库中的userinfo数据表结构如图1-21所示。
图1-21 数据表userinfo结构
创建名称为GeneratorMySQL的项目,更改配置文件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>
<contextid="context1">
<jdbcConnectionconnectionURL="jdbc:mysql://localhost:3306/y2"driverClass="com.mysql.jdbc.Driver"password="123"userId="root"/>
<javaModelGeneratortargetPackage="sqlmapping"
targetProject="GeneratorMySQL"/>
<sqlMapGeneratortargetPackage="sqlmapping"
targetProject="GeneratorMySQL"/>
<javaClientGeneratortargetPackage="sqlmapping"
targetProject="GeneratorMySQL"type="XMLMAPPER"/>
<tableschema="y2"tableName="userinfo">
<generatedKeycolumn="id"sqlStatement="mysql"identity="true"/>
</table>
</context>
</generatorConfiguration>
对generatorConfig.xml文件进行逆向。
在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>
<environmentsdefault="development">
<environmentid="development">
<transactionManagertype="JDBC"/>
<dataSourcetype="POOLED">
<propertyname="driver"value="com.mysql.jdbc.Driver"/>
<propertyname="url"value="jdbc:mysql://localhost:3306/y2"/>
<propertyname="username"value="root"/>
<propertyname="password"value="123"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapperresource="sqlmapping/UserinfoMapper.xml"/>
</mappers>
</configuration>
运行Test.java类代码如下。
packagetest;
importjava.io.IOException;
importjava.io.InputStream;
importorg.apache.ibatis.io.Resources;
importorg.apache.ibatis.session.SqlSession;
importorg.apache.ibatis.session.SqlSessionFactory;
importorg.apache.ibatis.session.SqlSessionFactoryBuilder;
importsqlmapping.Userinfo;
publicclassTest{
publicstaticvoidmain(String[] args) {
try{
Userinfo userinfo = newUserinfo();
userinfo.setUsername("usernameValue");
userinfo.setPassword("passwordValue");
userinfo.setAge(888);
Stringresource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = newSqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
sqlSession.insert("insert" userinfo);
sqlSession.commit();
sqlSession.close();
} catch(IOException e) {
// TODOAuto-generated catch block
e.printStackTrace();
}
}
}
运行Test.java类后在userinfo数据表添加了新的记录,效果如图1-22所示。
图1-22 数据表userinfo中的新纪录
本文节选自《Java EE核心框架实战(第2版)》
本书基于MyBatis3 Hibernate5 Struts2 Spring4MVC Spring4,融合了作者多年软件开发和培训的经验,面向实战,通过丰富且有参考价值的案例,展现了JavaEE开发领域中最核心、最实用的开发技术,帮助读者全面提升开发技能。