什么是mybatis?
(MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。)
Mybatis它是个高轻量级的半自动的持久层框架,它更加关注原生sql的编写。所以在实际项目中mybatis可以实现代码和sql的完全解耦。Mybatis还提供了强大的基于OGNL的动态sql语句编写。它支持定制化 SQL、存储过程以及高级映射。所以深受广大程序员的喜爱。
Mybatis架构图
Mybatis学习利器
中文API: https://mybatis.org/mybatis-3/zh/getting-started.html
下载地址:https://github.com/mybatis/mybatis-3/releases
(解压以后导入对应的jar包~不过直接git下载还是比较慢……)
搭建mybatis的环境
新建Maven项目 和前几个项目一样
1、导入相关的依赖
第一项,配置pom文件,需要加入两个maven包,一个是数据库连接驱动,一个是mybatis
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.0</version>
</dependency>
2、resources目录下面 新建一个配置mybatis.xml文件,对应将自己的数据库放到链接池里面,并且可以设置映射的xml文件,有两种方式,mapper要每个文件都写上,package自动扫描包内的Mapper接口与配置文件。
<?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>
<!--当返回行的所有列都是空时,MyBatis默认返回null-->
<setting name="returnInstanceForEmptyRow" value="true"/>
<!--显示sql语句-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<environments default="development">
<environment id="development">
<!--使用了 JDBC 的提交和回滚设置,它依赖于从数据源得到的连接来管理事务作用域-->
<transactionManager type="JDBC"/>
<!-- mybatis提供了3种数据源类型,分别是:POOLED,UNPOOLED,JNDI -->
<!-- POOLED 表示支持JDBC数据源连接池 -->
<!-- UNPOOLED 表示不支持数据源连接池 -->
<!-- JNDI 表示支持外部数据源连接池 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/gxa"/>
<property name="username" value="root"/>
<property name="password" value="root1234"/>
</dataSource>
</environment>
</environments>
<mappers>
<!-- 映射文件方式1,一个一个的配置
<mapper resource="com/gxa/mapper/UserMapper.xml"/>-->
<!-- 映射文件方式2,自动扫描包内的Mapper接口与配置文件 -->
<package name="com.gxa.mapper"/>
</mappers>
</configuration>
3、新建pojo对象
package com.gxa.pojo;
import java.math.BigDecimal;
import java.util.Date;
public class Emp {
private int emp_id;//变量名称与数据库的一致
private String emp_name;
private String emp_job;
private int emp_mgr;
private Date emp_hiredate;
private BigDecimal emp_sal;
private BigDecimal emp_comm;
private int emp_deptno;
public int getEmp_id() {
return emp_id;
}
public void setEmp_id(int emp_id) {
this.emp_id = emp_id;
}
public String getEmp_name(String mty) {
return emp_name;
}
public void setEmp_name(String emp_name) {
this.emp_name = emp_name;
}
public String getEmp_job() {
return emp_job;
}
public void setEmp_job(String emp_job) {
this.emp_job = emp_job;
}
public int getEmp_mgr() {
return emp_mgr;
}
public void setEmp_mgr(int emp_mgr) {
this.emp_mgr = emp_mgr;
}
public Date getEmp_hiredate() {
return emp_hiredate;
}
public void setEmp_hiredate(Date emp_hiredate) {
this.emp_hiredate = emp_hiredate;
}
public BigDecimal getEmp_sal() {
return emp_sal;
}
public void setEmp_sal(BigDecimal emp_sal) {
this.emp_sal = emp_sal;
}
public BigDecimal getEmp_comm() {
return emp_comm;
}
public void setEmp_comm(BigDecimal emp_comm) {
this.emp_comm = emp_comm;
}
public int getEmp_deptno() {
return emp_deptno;
}
public void setEmp_deptno(int emp_deptno) {
this.emp_deptno = emp_deptno;
}
@Override
public String toString() {
return "Emp{" +
"emp_id=" + emp_id +
", emp_name='" + emp_name + '\'' +
", emp_job='" + emp_job + '\'' +
", emp_mgr=" + emp_mgr +
", emp_hiredate=" + emp_hiredate +
", emp_sal=" + emp_sal +
", emp_comm=" + emp_comm +
", emp_deptno=" + emp_deptno +
'}';
}
public Emp(int emp_id, String emp_name, String emp_job, int emp_mgr, Date emp_hiredate, BigDecimal emp_sal, BigDecimal emp_comm, int emp_deptno) {
this.emp_id = emp_id;
this.emp_name = emp_name;
this.emp_job = emp_job;
this.emp_mgr = emp_mgr;
this.emp_hiredate = emp_hiredate;
this.emp_sal = emp_sal;
this.emp_comm = emp_comm;
this.emp_deptno = emp_deptno;
}
public Emp() {
super();
// TODO Auto-generated constructor stub
}
}
4、在java文件夹下,新建mapper->EmpMapper.xml的数据库映射文件,里面放置sql查询的语句。除了select还有insert等等语句都可以建。注意当调用参数的时候有些要注意传参数的格式,参数类型设置通过parameterType
<?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.gxa.mapper.EmpMapper">
<select id="queryEmpList " resultType="com.gxa.pojo.Emp">
select * from emp;
</select>
</mapper>
6、新建EmpMapper.java,一定注意这里的查询时候的参数名称要和实体类Emp.java和数据库对应的名称一致,这样可以替代dao的功能
package com.gxa.mapper;
import com.gxa.pojo.Emp;
import org.apache.ibatis.annotations.Param;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
public interface EmpMapper {
List<Emp> queryEmpList();
/**
* 根据雇员编号查询雇员信息
* @param
* @return
*/
List<Emp> queryEmpListByEmpno(int emp_id,int emp_mgr);
List<Emp> queryEmpListByEmpno(String emp_name,String emp_job);
List<Emp> queryEmpListByEmpno(int emp_id,String emp_name);
List<Emp> queryEmpListByEmpno(Map map);
List<Emp> queryEmpListByEmpno(Emp emp);
List<Emp> queryEmpByEnameAndComm(@Param("emp_name") String emp_name,@Param("emp_comm") BigDecimal comm);
int insertEmp();
}
7、编写测试代码,新建一个Test文件夹里面(直接在项目文件夹下面)
public class MybatisTest {
@Test
public void test01() throws IOException {
Reader reader = Resources.getResourceAsReader("mybatis.xml");//刚自己建好的xml
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
SqlSession session = sqlSessionFactory.openSession();
EmpMapper empMapper = session.getMapper(EmpMapper.class);
List<Emp> empList = empMapper.queryEmpList();
System.out.println(empList);
}
(这里遇到了Cannot find class: com.mysql.jdbc.Driver的错误 是mybatis的jar包没有配置好的问题,getResourceAsReader一直爆红,依赖引入出问题也可以手动引入jar包)
结果可以现实语句和查询结果
新来的一些文件的结构,要比较注意的就是mybatis在resources目录下面,接口EmpMapper里面放了查询数据库的方法,通过在EmpMapper.xml的映射中id,得到调用,EmpMapper.xml里面放了具体的sql语句。数据库的链接在mybatis.xml里面实现,也要在里面映射到mapper文件夹里面的xml文件(有两种方式)。到此基本文件就搭建好咯。
PS:文件搭建好以后的其他重要内容
1、解决后台提示找不到对应xml文件
Idea默认找不到对应的xml配置路径,在pom文件的build标签中,加入resource标签如下代码:
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
2、Xml配置方式的增删改查
首先配置mapper.xml文件
<!-- namespace一般定义为 包名+文件名 -->
<mapper namespace="com.gxa.mapper.UserMapper">
<select id="selectUser" resultType="com.gxa.pojo.User">
select * from user;
</select>
<insert id="insertUser" parameterType="com.gxa.pojo.User">
insert into user values (#{id},#{username},#{password});
</insert>
<update id="updateUser" parameterType="com.gxa.pojo.User">
update user set username=#{username},password=#{password} where id=#{id};
</update>
<delete id="deleteUser" parameterType="java.lang.String">
delete from user where id=#{id};
</delete>
</mapper>
然后再修改接口代码
public interface UserMapper {
// 方法名、参数类型、返回类型要和mapper.xml文件中的id相同
List<User> selectUser();
void insertUser(User user);
void updateUser(User user);
void deleteUser(String id);
}
在控制器中调用接口中指定的四个方法,就可以完成基本的增删改查
多参数传递的方式
在项目中,多参数传递更多的是基于pojo对象,或者map结构传递,但是也可能有需要多个形式参数传递,比如下面不用的类型和解解决方式:
- public List<Emp> queryParamListEmp (String ename,String job);
<select id="queryParamListEmp" parameterType="java.lang.String" resultType="com.gxa.pojo.Emp">
select * from emp where ename = #{arg0} or job = #{arg1}
</select>
<select id="queryParamListEmp" parameterType="java.lang.String" resultType="com.gxa.pojo.Emp">
select * from emp where ename = #{param1} or job = #{param2}
</select>
- public List<Emp> queryParamListEmp (String job,double sal);
public List<Emp> queryParamListEmp (@Param("job ") String job, @Param("sal ") double sal);
//注意:@Param("字段名称 ") 字段的名称必须和sql语句中变量保持一致
- public List<Emp> queryParamListEmp (Map map);
<select id="queryParamListEmp" parameterType="java.util.Map" resultType="com.gxa.pojo.Emp">
select * from emp where job=#{job} and sal > #{sal}
</select>
- public List<Emp> queryParamListEmp (Etity etity);
<select id="queryParamListEmp" parameterType="com.gxa.pojo.Emp" resultType="com.gxa.pojo.Emp">
select * from emp where job=#{job} and sal > #{sal}
</select>
对应的结果参数的映射
<resultMap id="emp2" type="com.gxa.pojo.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>
3、动态SQL的if使用
<select id="selectUser" resultType="com.gxa.pojo.User" parameterType="com.gxa.pojo.User">
select * from user
<if test="username != null">
where username=#{username}
</if>
</select>
在配置文件中添加动态的if语句,如果传递过来的user对象中,username不等于null,那么追加条件查询
4、动态SQL的where使用
如果我们有多个条件需要添加,但是有可能一个条件都不满足,那么这时候使用上面的方式就会出现问题,所以我们还需要在if外部添加一个where标签
<select id="selectUser" resultType="com.gxa.pojo.User" parameterType="com.gxa.pojo.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
5、动态SQL的choose when otherwise使用
<select id="selectUser" resultType="com.gxa.pojo.User" parameterType="com.gxa.pojo.User">
select * from user where password='888888'
<where>
<choose>
<when test="username != null">
AND username=#{username}
</when>
<when test="password != null">
AND password=#{password}
</when>
<otherwise>
AND id=#{id}
</otherwise>
</choose>
<where>
</select>
Choose when 类似于java中的switch case,任中只会走一个,一般是在有一个条件固定的情况下,需要额外不确定的条件时,使用choose的方式
6、动态SQL的set的使用
注意:set是检查去掉参数后的逗号
<update id="updateEmp" parameterType="Emp">
update emp
<set>
<if test="ename != null">
ename = #{ename},
</if>
<if test="job != null">
job = #{job},
</if>
</set>
where empno=#{empno}
</update>
<select id="selectInEmp" parameterType="java.util.List" resultType="Emp">
select * from emp where empno in
<foreach item="item" index="index" collection="list"
open="(" separator="," close=")">
#{item}
</foreach>
</select>
7、动态SQL的foreach的使用
Reader reader = Resources.getResourceAsReader("mybatis/mybatis.xml");
//创建一个SqlSessionFactory工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
SqlSession sqlSession = sqlSessionFactory.openSession();
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
List<Integer> empnos = new ArrayList<>();
empnos.add(7566);
empnos.add(7654);
empnos.add(7698);
List<Emp> list = mapper.selectInEmp(empnos);
for (Emp e : list){
System.out.println(e.getEname());
}