-
什么是mybatis
官网上介绍如下:MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。说简单点,mybatis支持了普通的SQL查询,存储过程和高级映射的持久层框架,mybatis消除了几乎所有的JDBC代码和参数的手工设置以及结果集的遍历和检索等。
mybatis使用XML或者注解用于配置原始映射,将借口和java的POJO(plain Ordinary Java Objects)实体类映射成数据库中的记录。
-
mybatis入门
- 使用mybatis需要将mybaits的jar包放入项目中,并且将jar包添加至classpath中,也就是build path。如果使用maven来构建管理项目,则只需要将dependency代码至于pom.xml文件中
- 每个基于mybatis的应用都是一个SqlSessionFactory的实例为中心的,SqlSessionFactory的实例可以通过SqlSessionFactoryBuilder获得,而SqlSessionFactoryBuilder则可以通过XML配置文件或者一个预先定制的Configuration的实例来构建出SqlSessionFactory的实例。
-
mybatis实现简单的增删查改
废话少说,先上代码,我这里直接创建的maven 的web项目方便,实现简单的数据操作
开发环境:idea 2018.2;mysql 8.0.12,jdk 1.8
需要的jar包:
jar包的说明:mysql-connector 是要根据mysql 版本来确定的,我这里使用的是mysql8。druid连接池是阿里开发的一款数据库连接池,该连接池在功能,性能,扩展性方面,都超过了其他数据库连接池,并且他可以监控数据库访问性能,内置提供了强大的StatFilter插件,能够详细统计SQL的执行性能,这对于线上分析数据库访问性能有帮助,并且可以扩展JDBC,如果对JDBC层有编程的需求,可以通过Druid提供的Filter机制,很方便编写JDBC的扩展插件。mybatis的jar包我使用的是3.4版本
先看项目结构:
根据一个普通的web项目一样,需要entity(pojo)层,dao层,service层,servlet层,resources文件夹里面放置了mybatis-config.xml;mapper文件,db.properties文件
先来说说mybatis-config.xml文件。这是一个mybatis的总配置文件,里面需要配置连接池需要的连接信息,日志打印,mapper文件映射,别名映射等等,如果没有这个配置文件,mybatis则无法运行。
先看代码:
数据库:teacher表
db.properties
#mysql8以上,将driver改为com.mysql.cj.jdbc.Driver,如果用的低版本,请继续使用#com.mysql.jdbc.Driver
driver=com.mysql.cj.jdbc.Driver
#mysql8使用的SSL加密,需要设置为true,否则容易出错,设置编码为utf8,时区为GMT
url=jdbc:mysql://localhost:3306/mybatisdemo?userSSL=true&useUnicode=true&characterEncoding=UTF8&serverTimezone=GMT
username=root
password=root
mybatis-cnfig.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>
<properties resource="properties/db.properties"/>
<settings>
<!--设置sql日志的输出,方便查阅,要求mybatis版本为3.3及其以上-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<typeAliases>
<!--typeAlias和package选一个使用,我这里使用package,package下的所有类名都会成为别名 -->
<!--<typeAlias type="com.yanyue.entity.Teacher" alias="_Teacher"/>-->
<package name="com.yanyue.entity"/>
</typeAliases>
<!--环境设置-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"></transactionManager>
<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文件映射,需要将mapper文件加载在这里-->
<mapper resource="mapper/TeacherDao.xml"/>
</mappers>
</configuration>
注意,mybatis-config.xml文件中,每个标签的位置顺序如图:其中environments是必须的,
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">
<!--mybatis入门,实现简单的增删查改-->
<!--mapper 的namespace需要与dao层的名字一致-->
<mapper namespace="com.yanyue.dao.TeacherDao">
<!-- 此处的id与TeacherDao的方法名一致,返回结果为Teacher实体类,如果使用了别名typeAlias
则需要用别名代替,例如这里我可以替换成Teacher-->
<select id="findAll" resultType="com.yanyue.entity.Teacher">
select * from teacher
</select>
<insert id="addTeacher" parameterType="com.yanyue.entity.Teacher">
insert into teacher (tname,tcourse) values (#{tname},#{tcourse})
</insert>
<update id="modTeacher" parameterType="com.yanyue.entity.Teacher">
UPDATE teacher set tcourse =#{tcourse} where tid=#{tid}
</update>
<delete id="delTeacher" parameterType="com.yanyue.entity.Teacher">
delete from teacher where tid=#{tid}
</delete>
</mapper>
mapper文件中,select,insert,delete,updata的参数说明:
id | 在命名空间中唯一的标识符,可以被用来引用这条语句。 |
parameterType | 将会传入这条语句的参数类的完全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过 TypeHandler 推断出具体传入语句的参数,默认值为 unset。 |
resultType | 从这条语句中返回的期望类型的类的完全限定名或别名。注意如果是集合情形,那应该是集合可以包含的类型,而不能是集合本身。使用 resultType 或 resultMap,但不能同时使用。 |
resultMap | 外部 resultMap 的命名引用。结果集的映射是 MyBatis 最强大的特性,对其有一个很好的理解的话,许多复杂映射的情形都能迎刃而解。使用 resultMap 或 resultType,但不能同时使用。 |
flushCache | 将其设置为 true,任何时候只要语句被调用,都会导致本地缓存和二级缓存都会被清空,默认值:false。 |
useCache | 将其设置为 true,将会导致本条语句的结果被二级缓存,默认值:对 select 元素为 true。 |
timeout | 这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为 unset(依赖驱动)。 |
fetchSize | 这是尝试影响驱动程序每次批量返回的结果行数和这个设置值相等。默认值为 unset(依赖驱动)。 |
statementType | STATEMENT,PREPARED 或 CALLABLE 的一个。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。 |
resultSetType | FORWARD_ONLY,SCROLL_SENSITIVE 或 SCROLL_INSENSITIVE 中的一个,默认值为 unset (依赖驱动)。 |
databaseId | 如果配置了 databaseIdProvider,MyBatis 会加载所有的不带 databaseId 或匹配当前 databaseId 的语句;如果带或者不带的语句都有,则不带的会被忽略。 |
resultOrdered | 这个设置仅针对嵌套结果 select 语句适用:如果为 true,就是假设包含了嵌套结果集或是分组了,这样的话当返回一个主结果行的时候,就不会发生有对前面结果集的引用的情况。这就使得在获取嵌套的结果集的时候不至于导致内存不够用。默认值:false。 |
resultSets | 这个设置仅对多结果集的情况适用,它将列出语句执行后返回的结果集并每个结果集给一个名称,名称是逗号分隔的。 |
在完成了mybatis-config.xml和mapper文件的配置,做个测试:
实体类:
Teacher.java,和以往的一样,无参构造,get和set方法,是必须的,有参构造和toString方法非必须
public class Teacher {
private int tid;//教师编号
private String tname;//教师姓名
private String tcourse;//教学课程
public int getTid() {
return tid;
}
public void setTid(int tid) {
this.tid = tid;
}
public String getTname() {
return tname;
}
public void setTname(String tname) {
this.tname = tname;
}
public String getTcourse() {
return tcourse;
}
public void setTcourse(String tcourse) {
this.tcourse = tcourse;
}
public Teacher() {
super();
}
public Teacher(int tid, String tname, String tcourse) {
this.tid = tid;
this.tname = tname;
this.tcourse = tcourse;
}
@Override
public String toString() {
return "Teacher{" +
"tid=" + tid +
", tname='" + tname + '\'' +
", tcourse='" + tcourse + '\'' +
'}';
}
}
mybatisTest.java
import com.yanyue.entity.Teacher;
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 java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class MybatisTest {
public static void main(String[] args) throws IOException {
//将mybatis-config.xml文件路径放入Resources
String resource="config/mybatis-config.xml";
//将mybatis-config.xml用Resources的Stream读取,再交给INputStream IO流
InputStream inputStream= Resources.getResourceAsStream(resource);
//mybatis核心,每个mybatis需要一个SqlSessionFactory,需要用SqlSessionFactoryBuilder实例化
SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(inputStream);
//SqlSession完全包含了面向数据库编程执行SQL命令所需的方法,参数true为sql语句自动提交
SqlSession sqlSession=factory.openSession(true);
//这里可以的参数为mapper文件的namespace.id组成
List<Teacher> list=sqlSession.selectList("com.yanyue.dao.TeacherDao.findAll");
System.out.println(list);
}
}
结果如下:
红色方框部分为mybaits-config.xml的setting的日志打印,如不需要,则可以删除setting部分
由此可见,mybatis已经成功使用上了,接下来一个util
MybatisUtil.java
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 java.io.IOException;
import java.io.InputStream;
public class MybatisUtil {
private static SqlSessionFactory sqlSessionFactory=null;
static {
try {
InputStream inputStream= Resources.getResourceAsStream("config/mybatis-config.xml");
sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
}catch (IOException e){
e.printStackTrace();
}
}
/**
* 获取SqlSession对象
* @param isCommit
* @return SqlSession
*/
public static SqlSession getSqlSession(boolean isCommit){
return sqlSessionFactory.openSession(isCommit);
}
public static void closeSqlSession(){
SqlSession sqlSession=getSqlSession(true);
if(sqlSession!=null){
sqlSession.close();
}
}
}
然后就是和以往一样,写dao,service,servlet层了,完了之后再前端通过ajax,看看mybatis入门demo是否成功了。
当dao层和MybatisUtil.java写完之后,我们在做一次测试,测试dao和MybatisUtil是否成功:
//getMapper自动装载TeacherDao这一个接口,注意接口的方法和mapper文件的id必须一致
TeacherDao teacherDao= MybatisUtil.getSqlSession(true).getMapper(TeacherDao.class);
list=teacherDao.findAll();
System.out.println(list);
这里,需要提醒的是,文件路径:mybaits-config.xml读取db.properties和mapper文件,MybatisUtil.java读取mybatis-config.xml文件,路径一定要对,文件路径从都是在main文件夹开始的,不管位置在哪,都是从这里开始的,在main文件中的绝对路径。
parameterType和ResultType都要注意,这是容易出错的地方,如果出现报错,需要检查这些地方。另外一定注意这一个
dao接口和mapper文件的id一定是一一对应的,getMpper加载dao接口之后,就会根据这样找到对应的dao接口方法。