简介
什么是 MyBatis?
MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
优点:
1、简单易学
mybatis本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
2、灵活
mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql基本上可以实现我们不使用数据访问框架可以实现的所有功能,或许更多。
3、解除sql与程序代码的耦合
通过提供DAL层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
4、提供映射标签,支持对象与数据库的orm字段关系映射
5、提供对象关系映射标签,支持对象关系组建维护
6、提供xml标签,支持编写动态sql。
缺点:
1、编写SQL语句时工作量很大,尤其是字段多、关联表多时,更是如此。
2、SQL语句依赖于数据库,导致数据库移植性差,不能更换数据库。
3、框架还是比较简陋,功能尚有缺失,虽然简化了数据绑定代码,但是整个底层数据库查询实际还是要自己写的,工作量也比较大,而且不太容易适应快速数据库修改。
4、二级缓存机制不佳
Mybatis使用详解
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!-- sql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!-- mybatis-->
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.4</version>
</dependency>
resources目录下新建mybatis.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="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="org/mybatis/example/BlogMapper.xml"/>
</mappers>
</configuration>
url,username,password为自己的信息;比如
有时候url后面还会加上一些时区,编码等设置 百度即可
<?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>
<settings>
<setting name="" value=""/>
</settings>
<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:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
</mappers>
</configuration>
我的目录结构
java目录下新建mybatis工具类
package com.jiu.utils;
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 factory = null;
static{
/*
1.
*每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心的。SqlSessionFactory 的实例可以
* 通过 SqlSessionFactoryBuilder 获得。
* 而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先配置的 Configuration(就是前面resources目录下的mybatis.xml) 实例来构建出
* SqlSessionFactory 实例。
* date 2021/5/7 0:10
* @author JiuZhou
* since JDK 1.8
**/
String config = "mybatis.xml";
try {
InputStream in = Resources.getResourceAsStream(config);
factory = new SqlSessionFactoryBuilder().build(in);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
2.
* 既然有了 SqlSessionFactory,顾名思义,我们可以从中获得 SqlSession 的实例。
* SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。
* 你可以通过 SqlSession 实例来直接执行已映射的 SQL 语句
* date 2021/5/7 0:13
* @author JiuZhou
* since JDK 1.8
**/
public static SqlSession getSqlSeeion(){
SqlSession sqlSession = null;
if(factory != null){
sqlSession = factory.openSession();//非自动提交事务
}
return sqlSession;
}
}
五,数据库建表,创建实体类
java目录下新建pojo包,创建一个类名与数据库相同,属性名和数据库字段名相同的pojo对象。
创建mybatis的数据库,添加数据
实体类User(idea alt+insert 快速生成构造,get,set,tostring)
创建实体类,养成get, set , 构造方法, toString生成的习惯
package com.jiu.pojo;
public class User {
private int id;
private String name;
private int age;
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public User(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
}
六,定义数据库操作接口,这里需要注意的是,mybatis以此接口为调用入口,通过此接口对应的方法来检查并对应mapper.xml文件中的增删改查
public interface UserDao {
// 方法名、参数类型、返回类型要和mapper.xml文件中的id相同
List<User> selectUser();
}
七,数据库映射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">
//<!-- namespace一般定义为 包名+文件名 注意对应关系-->
<mapper namespace="com.jiu.dao.UserDao">
//id就是接口中的方法名
<select id="selectUser" resultType="com.gxa.pojo.User">
select * from user;
</select>
</mapper>
<mappers>
<!-- 映射文件方式1,一个一个的配置
<mapper resource="com/jiu/dao/UserDao.xml"/>-->
<!-- 映射文件方式2,自动扫描包内的dao(Mapper)接口与配置文件 -->
<package name="com.jiu.dao"/>
</mappers>
Idea默认找不到对应的xml配置路径,在pom文件的build标签中,加入resource标签如下代码:
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
八,简单使用
在java目录下建一个test包, 或者在双人床目录下新建test包有就不用建立,新建test1类
两种处理操作数据库的方式
(1).通过session得到对应的Mapper接口对象,然后由此对象调用对应的操作方法(此方法有很多优势,首先它不依赖于字符串字面值,会更安全一点;其次,如果你的 IDE 有代码补全功能,那么代码补全可以帮你快速选择到映射好的 SQL 语句)
import java.util.List;
public class test1 {
public static void main(String[] args) {
SqlSession sqlSession = MybatisUtil.getSqlSeeion();
UserDao userDao = sqlSession.getMapper(UserDao.class);
List<User> userList = userDao.selectUser();
System.out.println(userList);
sqlSession.close();
}
}
(2) 通过session直接调用接口中对应的操作方法,用全限定名com.jiu.dao.UserDao.selectUser来调用映射语句了
//尽量全限定
List<User> userList = sqlSession.selectList("com.jiu.dao.UserDao.selectUser");
结果![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/3d93d3ee05ddfef3de9b9002bf2bc9f8.png)
九,mybatis的部分详解
namespace:命名空间
命名空间的作用有两个,一个是利用更长的全限定名来将不同的语句隔离开来,同时也实现了你上面见到的接口绑定。就算你觉得暂时用不到接口绑定,你也应该遵循这里的规定,以防哪天你改变了主意。 长远来看,只要将命名空间置于合适的 Java 包命名空间之中,你的代码会变得更加整洁,也有利于你更方便地使用 MyBatis。
命名解析:为了减少输入量,MyBatis 对所有具有名称的配置元素(包括语句,结果映射,缓存等)使用了如下的命名解析规则。
全限定名(比如 “com.mypackage.MyMapper.selectAllThings)将被直接用于查找及使用。
短名称(比如 “selectAllThings”)如果全局唯一也可以作为一个单独的引用。 如果不唯一,有两个或两个以上的相同名称(比如 “com.foo.selectAllThings” 和 “com.bar.selectAllThings”),那么使用时就会产生“短名称不唯一”的错误,这种情况下就必须使用全限定名。
<select id="selectPerson" parameterType="int" resultType="hashmap">
SELECT * FROM PERSON WHERE ID = #{id}
</select>
这个语句名为 selectPerson,接受一个 int(或 Integer)类型的参数,并返回一个 HashMap 类型的对象,其中的键是列名,值便是结果行中的对应值。
注意参数符号:#{id}
<insert id="insertAuthor">
insert into Author (id,username,password,email,bio)
values (#{id},#{username},#{password},#{email},#{bio})
</insert>
<update id="updateAuthor">
update Author set
username = #{username},
password = #{password},
email = #{email},
bio = #{bio}
where id = #{id}
</update>
<delete id="deleteAuthor">
delete from Author where id = #{id}
</delete>
在项目中,多参数传递更多的是基于pojo对象,或者map结构传递,但是也可能有需要多个形式参数传递,比如这样:
public List queryParamListEmp (String ename,String job);
public List queryParamListEmp (String job,double sal);
public List queryParamListEmp (Map map);
public List queryParamListEmp (Etity etity);
如上第二种方式的解决方案:
public List<Emp> queryParamListEmp (@Param("job ") String job, @Param("sal ") double sal);
注意:@Param("字段名称 ") 字段的名称必须和sql语句中变量保持一致
如上第三种方式的解决方案:
<select id="queryParamListEmp" parameterType="java.util.Map" resultType="XXXXX.Emp">
select * from emp where job=#{job} and sal > #{sal}
</select>
如上第四种方式的解决方案
<select id="queryParamListEmp" parameterType="XXXXX.Emp" resultType="XXXXX.Emp">
select * from emp where job=#{job} and sal > #{sal}
</select>
<resultMap id="emp2" type="XXXXXX.Emp2">
<id property="no" column="empno"></id>
<id property="name" column="ename"></id>
<id property="job" column="job"></id>
<id property="mgr" column="mgr"></id>
<id property="hiredate" column="hiredate"></id>
<id property="sal" column="sal"></id>
<id property="comm" column="comm"></id>
<id property="deptno" column="deptno"></id>
</resultMap>
<!--当出现表中的字段名和实体中的属性不一致的时候:返回的结果类型就应该用resultMap来进行封装-->
<select id="selectListEmp" resultMap="emp2">
select * from emp
</select>
<select id="selectUser" resultType="XXXXXX.User" parameterType="XXXXXX.User">
select * from user
<if test="username != null">
where username=#{username}
</if>
</select>
在配置文件中添加动态的if语句,如果传递过来的user对象中,username不等于null,那么追加条件查询
<select id="selectUser" resultType="XXXXXXXX.User" parameterType="com.gxa.jiu.User">
select * from user
<where>
<if test="username != null">
username=#{username}
</if>
<if test="password != null">
and password=#{password}
</if>
</where>
</select>
可以看到,where包含了两个if,而第一个if中没有and,where标签会自动检查状态,如果标签返回的第一个匹配内容是以 and或or 开头的,则会自动删除and或者or ,然后再追加where