一、概念
前身叫做iBatis
什么是MyBatis,为什么要用MyBatis
MyBatis是一个支持定制化sql,存储过程,高级映射的优秀持久层框架,我们使用MyBatis可以避免所有的JDBC
代码,以及手动设置参数,结果集的遍历等问题。而且MyBatis支持动态sql,多表联查的结果集封住。
MyBatis可以使用配置,或注解来完成model与数据库表的关系映射。实现sql语句与java代码的解耦。
传统JDBC开发的问题:
1:数据库的连接频繁创建于销毁。
2:sql语句实际上就是一个Java代码的字符串,修改sql等于修改Java代码(硬编码)不利于维护
3:使用占位符传参的时候存在硬编码的问题,因为where后面的条件是不固定的(有可能是一个1个,或2个...)
有多少查询条件,就需要有多少条sql
4:对于结果集的解析存在硬编码,sql改变了结果集也需要对应的改变,不利于维护。
MyBatis中的配置文件分为两种:
一:总配置文件MyBatisConfig 配置数据库环境,MaBatis的配置,小Mapper文件的加载。
二:小配置文件XXXmapper 每一个配置文件对应于数据库中的一张表。
总配置文件MyBatisConfig中的值:
properties 加载属性文件,使用${属性文件中的key}来取值
typeAliases 指定类型别名,减少mapper文件中的代码
environments 配置数据库环境集合
environment 配置数据库环境
transactionManager 指定事务管理器
dataSource 配置数据库连接池
mappers 用来加载mapper文件
小配置文件XXXmapper中的值:
namespace: 用来确定mapper文件的唯一标识符,根据这个值可以定位到这个文件
insert: 用来编写插入的sql
delete: 用来编写删除的sql
update: 用来编写修改的sql
select: 里面编写查询的sql
id: sql的唯一表示符,在一个文件内不能重复
parameterType: 用来指定当前sql中需要使用的参数类型,如果传入的是model,在sql中就可以使用#{属性名}来进行取值的操作,
如果传入的是一个字符串货基本数据类型,可以使用#{任意字符}来进行取值,一般情况下,我们可以默认省略掉参数类型,但是开发之中
建议不要省略。
resultType 用来指定查询语句的结果集类型,如果查询出来时多条记录,它会自动包装为对应的list集合,要求model
的属性名要与数据库的列名一致(同名匹配原则),如果不一致,不会报错,但不会有值。
resultMap 当数据库列名与Model的属性名不一致的时候,查询语句可以使用resultMap来自定义返回结果集,在其指定的数据库中列对应与Model
中的属性名
statementID: mapper文件的namespace+sql语句的ID组成,通过statementID就能定位到具体的哪一条sql
例如:session.insert("uusermapping.add",user)
使用statementID执行sql存在的问题:
1、由于statementID是我们自定义的一个字符串,在编译期间如果写错了,只能等运行期间才能发现问题
2、使用statementID来执行sql的话,如果参数传入错误在编译期间无法发现,只有程序运行时才能发现问题。
解决statementID引出的问题
使用接口映射方式来解决。
使用接口映射方式的时候,当我们将接口的class对象传给MyBatis之后,MyBatis会自动的替我们创建一个Proxy对象,然后里面
有封装好的JDBC方法,我们直接使用即可,我们可以通过操控代理类对象来完成对数据库的操作。
使用接口映射的注意点:
1:保持接口的全限定名与mapper中namespace一致。
2:接口中的方法名与mapper中ID要保持一致
3:方法中参数需要与parameType一致
4:方法中的返回值需要与resultType或者resultMap一致。
具体代码实现
首先我建立的是一个Maven的jar项目,需要junit测试。
一、下载jar包 pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zhiyou</groupId>
<artifactId>MyBatis_1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.1</version>
</dependency>
<!-- mysql驱动包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.4</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
配置文件 db.properties:
driver=com.mysql.jdbc.Driver
url=jdbc:mysql:///text11
username=root
password=123456
model类User:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private Integer id;
private String name;
private String password;
private String money;
private Date date;
}
Mapper接口UserMapper:
public interface UserMapper {
void add(User user);
void delete(int id);
void update(User user);
List<User> selectAll();
List<User> selectAllMap();
}
总配置文件MyBatisConfig.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="db.properties"/>
<!-- 指定类型别名 -->
<typeAliases>
<!-- user就代表了com.zhiyou.model.User -->
<typeAlias type="com.zhiyou.model.User" alias="user"/>
</typeAliases>
<!-- 配置数据库环境,可以配置多个,并指定默认使用哪一个环境 -->
<environments default="A">
<environment id="A">
<!-- 配置事务管理器 -->
<transactionManager type="org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory"/>
<!-- 配置数据库连接池,这个连接池是MaBatis自带的 -->
<dataSource type="org.apache.ibatis.datasource.pooled.PooledDataSourceFactory">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<!-- 引入其他的mapper文件 -->
<mappers>
<mapper resource="mapper/usermapper.xml"/>
</mappers>
</configuration>
user的配置文件usermapper.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文件的东西,不能与其他mapper的namespace重复 -->
<mapper namespace="com.zhiyou.mapper.UserMapper">
<!-- <mapper namespace="usermapping"> -->
<!-- id 用来配合namespace来定位sql语句的,在同一个mapper中不能重复
resultType 用来指定查询语句的结果集类型,如果查询出来时多条记录,它会自动包装为对应的list集合,要求model
的属性名要与数据库的列名一致(同名匹配原则),如果不一致,不会报错,但不会有值。
resultMap 当数据库列名与Model的属性名不一致的时候,查询语句可以使用resultMap来自定义返回结果集,在其指定的数据库中列对应与Model
中的属性名
parameterType 用来指定当前sql中需要使用的参数类型,如果传入的是model,在sql中就可以使用#{属性名}来进行取值的操作,
如果传入的是一个字符串货基本数据类型,可以使用#{任意字符}来进行取值,一般情况下,我们可以默认省略掉参数类型,但是开发之中
建议不要省略。
-->
<insert id="add" parameterType="user">
insert into user
values(#{id},#{name},#{password},#{money},#{date});
</insert>
<delete id="delete" parameterType="int">
delete from user where id=#{idadfa};
</delete>
<update id="update" parameterType="user">
update user set name=#{name},password=#{password},money=#{money},date=#{date}
where id=#{id};
</update>
<resultMap type="user" id="userMap">
<id column="id" property="id" />
<result column="username" property="name" />
<result column="password" property="password" />
<result column="money" property="money" />
<result column="date" property="date" />
</resultMap>
<select id="selectAllMap" resultMap="userMap">
select * from user;
</select>
<select id="selectAll" resultType="user">
select * from user;
</select>
</mapper>
测试类:
package com.zhiyou;
import java.io.IOException;
import java.sql.Date;
import java.util.List;
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 org.junit.Test;
import com.zhiyou.mapper.UserMapper;
import com.zhiyou.model.User;
public class MainClass {
@Test
public void add() throws IOException{
//获得数据库会话工厂
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsReader("MyBatisConfig.xml"));
//获得数据库连接对象
SqlSession session = factory.openSession();
//根据mappernamespace+id来决定执行的sql new Date(System.curr....)sql的date
User user =new User(111, "王佳琪", "123456", "2W",new Date(System.currentTimeMillis()));
session.insert("usermapping.add",user);
session.commit();
session.close();
}
@Test
public void updata() throws IOException{
//获得数据库会话工厂
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsReader("MyBatisConfig.xml"));
//获得数据库连接对象
SqlSession session = factory.openSession();
//根据mappernamespace+id来决定执行的sql new Date(System.curr....)sql的date
User user =new User(111, "王佳琪是谁", "123456", "2W",new Date(System.currentTimeMillis()));
session.insert("usermapping.update",user);
session.commit();
session.close();
}
@Test
public void delete() throws IOException{
//获得数据库会话工厂
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsReader("MyBatisConfig.xml"));
//获得数据库连接对象
SqlSession session = factory.openSession();
//根据mappernamespace+id来决定执行的sql new Date(System.curr....)sql的date
session.delete("usermapping.delete",111);
session.commit();
session.close();
}
@Test
public void select() throws IOException{
//获得数据库会话工厂
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsReader("MyBatisConfig.xml"));
//获得数据库连接对象
SqlSession session = factory.openSession();
//根据mappernamespace+id(statement)来决定执行的sql new Date(System.curr....)sql的date
List<User> list = session.selectList("usermapping.selectAllMap");
System.out.println(list);
session.commit();
session.close();
}
//主要使用这一种,上面的不使用了。
@Test
public void method() throws IOException{
//获得数据库会话工厂
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsReader("MyBatisConfig.xml"));
//获得数据库连接对象
SqlSession session = factory.openSession();
UserMapper mapper = session.getMapper(UserMapper.class);
mapper.add(new User(112, "王佳琪", "123456", "2W",new Date(System.currentTimeMillis())));
List<User> list = mapper.selectAllMap();
System.out.println(list);
session.commit();
session.close();
}
}