教你使用mybatis完成mysql普通的增删改查和高级查询

1.Mybatis 映射器

之前讲过通过Mybatis的核心配置文件,和定义一个书写sql的配置文件,然后通过SqlSession对象的方法执行sql语句,sql语句通过sql的xml文件的namespace属性和具体sql的id属性来定位到一个sql,今天会告诉大家通过Mybatis的映射器直接将dao层接口和sql的xml文件映射起来,然后执行dao层接口的方法完成CRUD。

1.1 Mybatis完成CRUD的操作步骤
  • 创建数据库和建表
  • 准备一个普通的项目
  • 导入mybatis需要的jar包(核心包、依赖包、数据库驱动包)
  • 准备好domain
  • 准备好mybatis的核心配置文件
  • 准备好dao层接口和书写sql的xml配置文件
  • junit4单元测试
1.2 Mybatis的核心配置文件:MyBatis_config.xml

这个配置和之前的一样,唯一不同的地方就是在引入sql的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>
    <!--环境配置,连接的数据库,这里使用的是MySQL-->
    <environments default="development">
        <environment id="development">
            <!--指定事务管理的类型,这里简单使用Java的JDBC的提交和回滚设置-->
            <transactionManager type="JDBC"></transactionManager>
            <!--dataSource 指连接源配置,POOLED是JDBC连接对象的数据源连接池的实现-->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"></property>
                <property name="url" value="${jdbc.url}"></property>
                <property name="username" value="${jdbc.username}"></property>
                <property name="password" value="${jdbc.password}"></property>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <!--这是告诉Mybatis区哪找持久化类的映射文件,对于在resoures资源文件下的文件直接写文件名,如果在某包下,则要写明路径,如:com/mybatistest/config/User.xml-->
        <mapper resource="cn/lqq/mapper/EmployeeMapper.xml"></mapper>
    </mappers>
</configuration>
1.3 dao层接口和sql的xml文件

规范:

  • mybatis中dao层的命名规范是mapper,mapper包其实就是dao层
  • 接口的方法映射到对应的sql,接口的方法名必须和sql语句的id属性值对应上
  • xml配置文件的namespace属性值必须和接口的完全限定名一致
    mybatis写sql语句有两种方式:1.在xml文件中写 2.直接在接口方法上使用注解
    下面注释的那一行代码就是在直接在方式上使用注解的方式来写sql语句
    mapper包下的接口实现代码:
public interface EmployeeMapper {
	//查询所有数据
	// @Select("select * from employee")
    List<Employee> findAll();
	//查询一条数据
    Employee findOne(Long id);
	//保存数据
    void save(Employee employee);
	//修改数据
    void update(Employee employee);
	//删除数据
    void delete(Long id);
}

对应的sql的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="cn.lqq.mapper.EmployeeMapper">

    <!--查询所有数据-->
    <select id="findAll" resultType="cn.lqq.domain.Employee">
        select * from employee
    </select>
	<!--查询一条数据-->
    <select id="findOne" parameterType="long" resultType="cn.lqq.domain.Employee">
        select * from employee where id=#{id}
    </select>
	<!--保存数据-->
    <insert id="save" parameterType="cn.lqq.domain.Employee">
        insert into employee (name,age,sex) values(#{name},#{age},#{sex})
    </insert>
	<!--修改数据-->
    <update id="update" parameterType="cn.lqq.domain.Employee">
        update employee set name=#{name},age=#{age},sex=#{sex} where id=#{id}
    </update>
	<!--删除数据-->
    <delete id="delete" parameterType="long">
        delete from employee where id=#{id}
    </delete>
</mapper>

注意: 这个xml文件要在Mybatis的核心配置文件中读取

1.4 单元测试
public class EmployeeTest {
    
    @Test
    public void testSave()throws Exception{
        SqlSession session = MyBatiUtils.openSession();
        EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
        for (int i = 0; i < 30; i++) {
            Employee employee = new Employee();
            employee.setName("李巧巧"+i);
            employee.setAge(i);
            employee.setSex(i%2==0);
            mapper.save(employee);
        }
        session.commit();
    }

    @Test
    public void testFindAll()throws Exception{
        //创建Mapper对象,这个可以获取到EmployeeMapper接口的实现
        EmployeeMapper mapper = MyBatiUtils.openSession().getMapper(EmployeeMapper.class);
        //直接通过这个调用里面的方法
        mapper.findAll().forEach(e-> System.out.println(e));
    }

    @Test
    public void testFindOne()throws Exception{
        EmployeeMapper mapper = MyBatiUtils.openSession().getMapper(EmployeeMapper.class);
        Employee employee = mapper.findOne(1L);
        System.out.println(employee);
    }

    @Test
    public void testUpdate()throws Exception{
        SqlSession session = MyBatiUtils.openSession();
        EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
        Employee employee = mapper.findOne(31L);
        employee.setName("张三丰");
        mapper.update(employee);
        session.commit();
    }
    @Test
    public void testDelete()throws Exception{
        SqlSession session = MyBatiUtils.openSession();
        EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
        mapper.delete(  31L);
        session.commit();
    }
}

2.Mybatis 高级查询

2.1 高级查询需要注意的点
  • 高级查询的条件通过一个query对象传过来,要准备一个query对象
  • 多个条件拼接的时候,直接使用where标签
  • 模糊查询进行字符串的拼接使用:concat()函数进行拼接
  • 特殊字符的处理:1.使用转义字符 2.使用CDATA区:<![CDATA[ 数据 ]]>
  • 在if语句中有联接条件,使用and/or,而不是&&/ ||
  • 在sql的xml中对于公共代码的提取:使用sql标签
2.2 query对象的准备

定义一个类作为高级查询的条件,这里只是为了做测试定义的,在实际开发中查询的条件是根据实际需求的

public class EmployeeQuery {
    private String name;
    private Integer minAge;
    private Integer maxAge;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getMinAge() {
        return minAge;
    }
    public void setMinAge(Integer minAge) {
        this.minAge = minAge;
    }
    public Integer getMaxAge() {
        return maxAge;
    }
    public void setMaxAge(Integer maxAge) {
        this.maxAge = maxAge;
    }
}
2.3 在xml中写拼接高级查询的sql语句
<!--对于下面的高级查询的条件这个可以提取出来,后面在高级查询的时候就可以使用
        使用sql标签提取,然后在需要使用这一段代码的地方,直接使用Include标签引入-->
<sql id="whereSql">
    <where>
        <if test="name!=null and name!=''">
            and name like concat("%",#{name},"%")
        </if>
        <if test="minAge!=null">
            and age >= #{minAge}
        </if>
        <if test="maxAge!=null">
            and age &lt;= #{maxAge}
        </if>
    </where>
</sql>
<!--定义高级查询,需要接收高级查询的参数然后动态的拼接sql-->
<select id="query" parameterType="cn.lqq.query.EmployeeQuery" resultType="cn.lqq.domain.Employee">
    select * from employee <include refid="whereSql"></include>
</select>

在接口EmployeeMapper 添加一个query方法:

List<Employee> query(EmployeeQuery query);
2.4 测试
@Test
    public void testQuery()throws Exception{
        EmployeeMapper mapper = MyBatiUtils.openSession().getMapper(EmployeeMapper.class);
        EmployeeQuery query = new EmployeeQuery();
        query.setName("1");
        query.setMinAge(13);
        query.setMaxAge(34);
        List<Employee> list = mapper.query(query);
        list.forEach(e-> System.out.println(e));
    }

3.Mybatis 批量处理

3.1 批量添加

批量添加的sql,在mysql中可以使用下面的添加语句实现一条sql添加多条数据

INSERT INTO employee (name,age,sex) VALUES ('张三',23,true),('李四',34,false),('王五',25,true)

所以在xml中我们只需要拼接出上面的sql就可以实现批量添加,但是这种语法只能在mysql中使用,传过去一个集合,然后循环遍历value后面的值就可以了

<insert id="batchSave" parameterType="list">
    insert into employee (name,age,sex) values
    <foreach collection="list" item="employee" separator=",">
        (#{employee.name},#{employee.age},#{employee.sex})
    </foreach>
</insert>

在接口EmployeeMapper 添加一个batchSave方法:

//定义一个批量添加的方法,参数是一个list集合
void batchSave(List<Employee> list);

测试:

@Test
public void testBatchSave()throws Exception{
     SqlSession session = MyBatiUtils.openSession();
     EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
     List<Employee> list = Arrays.asList(new Employee("王五", 24, true),
             new Employee("赵敏",34,false),
             new Employee("小昭",45,false)
     );
     mapper.batchSave(list);
     session.commit();
 }
3.2 批量删除

批量删除的sql可以使用in关键字:delete from tableName where id in(1,2,3…)
可以传过去一个数组,也可以是个list,在xml中拼接的sql如下:

<delete id="batchDelete" parameterType="list">
        delete from employee where id in
        <foreach collection="list" item="d" separator="," open="(" close=")">
          #{d}
        </foreach>
</delete>

在接口EmployeeMapper 添加一个batchDelete方法:

//定义一个批量删除的方法,参数传递的是多个id值,可以使用集合也可以使用数组
void  batchDelete(List<Long> list);

测试:

@Test
public void testBatchDelete()throws Exception{
     SqlSession session = MyBatiUtils.openSession();
     EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
     List<Long> list = new ArrayList<>();
     list.add(61L);
     list.add(62L);
     list.add(63L);
     mapper.batchDelete(list);
     session.commit();
 }
3.3 动态修改sql
3.3.1数据丢失问题:

在修改一条数据的,在我们只需要修改其中某几个字段时,其他不修改的字段,修改以后直接变成null,然后造成数据丢失的问题
解决方案:
1)在前台代码上写上隐藏域,所有字段都传递过去,这样没有修改的字段也会将原来的值传过去,这种方式不安全,且麻烦
2)修改我们的sql,没有修改的字段在写sql的时候不修改这些字段
3)先通过id查询到这条数据,然后再改里面需要修改的字段的值。因为修改之前先查询,所以性能不好

3.3.2 动态修改sql

修改的字段不确定,需要通过前台穿过来的字段来确定修改的值,这里就需要通过判断来动态生成sql
生成动态sql的xml代码如下:

<update id="dynamicUpdate" parameterType="cn.lqq.domain.Employee">
      update employee
      <set>
          <if test="name!=null and name!=''">
              name=#{name},
          </if>
          <if test="age!=null">
              age=#{age},
          </if>
          <if test="sex!=null">
              sex=#{sex}
          </if>
      </set>
      where id=#{id}
</update>

在接口EmployeeMapper 添加一个dynamicUpdate方法:

//定义一个动态修改的方法
void dynamicUpdate(Employee employee);

测试:

 @Test
public void testDynamicUpdate()throws Exception{
    SqlSession session = MyBatiUtils.openSession();
    EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
    Employee employee = mapper.findOne(64L);
    employee.setName("孙逊");
    employee.setAge(43);
    employee.setSex(false);
    mapper.dynamicUpdate(employee);
    session.commit();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值