mybatis是一款优秀的持久层框架,它是半自动的、轻量级java框架,官方文档:mybatis-3(Spring整合可参考:mybatis-spring)
它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
mybatis是Apache开源的项目,原名ibatis,在2010年从apache software foundation迁移到google code,在2013年迁移到github。在github上不但能搜索到mybatis源码,还能找到一些对应的mybatis翻译、插件。
- 简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
- 灵活:mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql语句可以满足操作数据库的所有需求。
- 解除sql与程序代码的耦合:通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
- 提供映射标签,支持对象与数据库的orm字段关系映射
- 提供对象关系映射标签,支持对象关系组建维护
- 提供xml标签,支持编写动态sql。
Mybatis对新手来说,最强大的功能是动态sql(因为新手很难封装如此简化的工具)
Mybatis在设计方面:
- 使用XML:能实现解耦,但使用成本高
- 使用注解:并不能解耦,但能快速开发
此外,它非常灵活且易于扩展,它有很多插件,或者我们可以自己做插件,灵活扩展才是它真正的灵魂,也可以预见短时间内很难有好的框架取代它。
综上,Mybatis并非处处完美,相对也有缺点,但使用人数很多、公司使用的比较多,另外我们可以从Mybatis中吸收它设计的好的地方以便我们设计出更棒的框架,以上是我们为什么需要学习Mybatis的原因。
第一个mybatis项目
注释:第一个程序可参考mybatis官方文档:Mybatis-getting-start,mybatis不推荐使用注解,本程序基于xml。
首先,你需要创建数据库,本文使用mysql5.7。
create database mybatis;
use mybatis;
create table if not exists user(
id int(20) primary key auto_increment,
name varchar(30) default null,
pwd varchar(30) default null
)engine innodb default character set utf8;
insert into user(name,pwd) values('张三','123456'),('李四','123'),('王五','666');
select * from user;
使用maven创建项目时导入mybatis坐标以及mysql坐标:
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
此外,因为maven是约定大于配置,如果你想在java目录使用resources,需要编写以下build规则
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
核心配置文件
核心配置文件,也叫主配置文件,必须使用xml文件配置,通常在resource目录新建一个名为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.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost/mybatis?useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="mybatis"/>
<property name="password" value="YOUR_PASSWORD"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
</configuration>
创建一个MybatisUtil工具类,以快速获取SqlSession
public class MybatisUtil {
static SqlSessionFactory sqlSessionFactory;
static{
String resource = "mybatis-config.xml";
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
} catch (IOException e) {
e.printStackTrace();
}
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession(true); // 如果缺省参数,否则默认false,执行增、删、改后不会自动提交
}
}
创建User实体类,主要注意,必须符合ORM规则,类属性和表字段一一对应
public class User {
private int id;
private String name;
private String pwd;
public User() {
}
public User(int id, String name, String pwd) {
this.id = id;
this.name = name;
this.pwd = pwd;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", pwd='" + pwd + '\'' +
'}';
}
}
配置mapper
编写userMapper类,此类相当于jdbc的dao类,mybatis中一般不叫dao
import java.util.List;
public interface UserMapper {
List<User> getUser();
}
编写userMapper.xml,此文件相当于jdbc的daoImpl(注意resultType,因为是集合类型,这里返回集合包装的类型,解释请参阅官方文档:mybatis – MyBatis 3 | XML 映射器)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org/DTD Mapper 3.0" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="mapper.UserMapper">
<select id="getUser" resultType="domain.User">
select * from user;
</select>
</mapper>
编写测试类
public class Test {
public static void main(String[] args) {
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> users = mapper.getUser();
for (User user : users) {
System.out.println(user);
}
sqlSession.close();
}
}
运行程序,得到如下结果:
User{id=1, name='张三', pwd='123456'}
User{id=2, name='李四', pwd='123'}
User{id=3, name='王五', pwd='666'}
可能会遇到的错误:
- mapper未注册,每一个mapper.xml需要在主配置文件中注册
- 绑定接口错误,mapper.xml的namespace需要正确绑定mapper类
- 方法名不对,mapper.xml的select的id与方法名要匹配
- 返回类型不对,mapper.xml的resultType需要指定返回值类型
- maven导出资源问题,在java路径下的资源需要手动编写build规则
mybatis增删改查
以下对mapper的增删该查进行详细说明,此部分对应于官方文档:xml映射文件
select语句
在mapper类中,添加一个方法,通过ID查询用户
User getUserById(int id);
在mapper.xml中,添加一个select标签,内容如下:
<select id="getUserById" parameterType="int" resultType="domain.User">
select * from user where id = #{id};
</select>
这里的#{id}表示预处理语句参数,parameterType表示参数的类型
在test中,通过mapper对象,使用getUserById方法查询用户
System.out.println("********");
User userById = mapper.getUserById(2);
System.out.println(userById);
得到如下结果:
********
User{id=2, name='李四', pwd='123'}
insert, update 和 delete
与select不同的是,insert,update 和 delete必须提交事务。
数据变更语句 insert,update 和 delete 的实现非常接近,以下以insert示例。
在mapper类增加一个方法,使用int作为返回值,作为操作结果的判断标志
int addUser(User user);
在mapper.xml中,添加一个insert标签,内容如下:(注意name, pwd是怎么来的,它会自动检测参数实体类中对应属性)
<insert id="addUser" parameterType="domain.User">
insert into user(name,pwd) values(#{name},#{pwd});
</insert>
接着,在test中,使用mapper对象执行addUser方法
int addResult = mapper.addUser(new User(1, "哈哈", "123"));
if(addResult>0){
System.out.println("提交成功");
sqlSession.commit();
}
System.out.println("*********");
注意,你必须提交事务,否则不生效。
使用注解开发
在官方文档中并没有关于注解开发的案例,感兴趣的可以在其源码中找到所有的注解(大部分注解位于org.apache.ibatis.annotations
包下),以下均是一些经验与积累。
总体来说,这些常用注解分为三大类:SQL语句映射,结果集映射和关系映射。
基本的增删改查
使用注解开发比XML更简单,一般只需要以下三个步骤
一:在Mybatis主配置文件中映射指定的接口类
上面的例子我们已经映射了一个XML,在mappers标签中添加一个类似的标签,使用class属性指定一接口,这样该接口才会被mybatis调用
<mappers>
<mapper resource="xml/UserMapper.xml"/>
<mapper class="anno.UserMapper2"/>
</mappers>
二、编写该UserMapper2接口
public interface UserMapper2 {
@Select("select * from user")
List<User> getUser();
@Update("update user set name=#{name},pwd=#{pwd} where id=#{id}")
int updateUser(User user);
@Delete("delete from user where id=#{id}")
int deleteUser(int id);
@Insert("insert into user(id,name,pwd) values(#{id},#{name},#{pwd})")
int addUser(User user);
}
在接口对应方法中编写注解即可,不再需要编写XML。
三、测试调用:
public class TestAnno {
SqlSession sqlSession = MybatisUtil.getSqlSession();
UserMapper2 mapper = sqlSession.getMapper(UserMapper2.class);
// 测试查询
@org.junit.jupiter.api.Test
public void testSelect(){
List<User> users = mapper.getUser();
for (User user : users) {
System.out.println(user);
}
sqlSession.close();
}
// 测试更新
@org.junit.jupiter.api.Test
public void testUpdate(){
int i = mapper.updateUser(new User(7,"李2","222"));
System.out.println(i==0?"失败":"成功");
sqlSession.close();
}
// 测试删除
@org.junit.jupiter.api.Test
public void testDelete(){
int i = mapper.deleteUser(9);
System.out.println(i==0?"失败":"成功");
sqlSession.close();
}
// 新增用户
@org.junit.jupiter.api.Test
public void testInsert(){
int i = mapper.addUser(new User(10,"张","1111"));
System.out.println(i==0?"失败":"成功");
sqlSession.close();
}
}
SQL语句映射
SQL语句映射,用于编写SQL使用
@Param注解
此注解用于标识接口中传递的参数别名。
当接口中仅有一个数据时可以不使用此注解,比如 selectById(int id),那么在mapper中可以直接使用#{id}
而如果是 insert(String name, String pwd), 则在mapper中就无法直接使用#{name}和#{pwd},此时默认是#{param1}和#{param2}(或arg0和arg1),也就是说默认会根据顺序解析,可以使用arg或者param标识。
使用@param后,则可以指定参数别名传递给mapper,例如
public interface UserMapper {
List<User> select(@Param("name") String name,@Param("age") byte age);
}
如果不使用这种方式,可以使用对象或者map封装后,此时只需要传递一个参数。
使用对象的方式前面已经进行介绍,下面介绍map传递参数:
首先创建啊一个hashMap对象,泛型为<String, Object>,其中的key就是可以被识别的名称,而value就是传递的值
在接口中传递此参数后,需要在mapper中指定parameterType=map,例如以下例子:
//使用Map传参添加用户
int addUser2(Map<String,Object> map);
//使用Map传参修改用户信息
int updateUser2(Map<String,Object> map);
<insert id="addUser2" parameterType="map">
insert into mybatis.user (name, pwd) values(#{userName},#{passWorld}) ;
</insert>
<update id="updateUser2" parameterType="map">
update mybatis.user set name=#{userName},pwd=#{password} where id=#{userId} ;
</update>
增删改查注解
最基本的4个注解
注解 | 描述 |
---|---|
@Insert | 实现新增功能 |
@Select | 实现查询功能 |
@Update | 实现更新功能 |
@Delete | 实现删除功能 |
附加手册
typeAliases标签:指定一个类的别名,不区分大小写
package标签:指定一个包的别名,并且该包下所有类名均为其别名
properties标签:可以直接指定配置信息,或者使用resource属性指定外部properties文件地址,也可以使用url属性指定file协议地址。
本篇完,还有疑问?留下评论吧