2.Mybatics_映射器与参数

映射器与参数

一.XML映射器

1.创建工具类

每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。更多参考

我们希望每个线程访问是各自线程中的sqlsession,这时可以考虑使用线程中的ThreadLocal来实现,常用方法有:

  • set(value): 线程中放值
  • get():取线程中的值
public class MybatisUtil {
    private static final SqlSessionFactory sessionFactory;
    //线程容器
    private static final ThreadLocal<SqlSession> t1 = new ThreadLocal<SqlSession>();

    static {
        InputStream inputStream = null;
        try {
            //       从资源中获取名为 "mybatis-config.xml" 的文件的输入流(InputStream)
            inputStream = Resources.getResourceAsStream("mybatis-config.xml");
            //      使用SqlSessionFactoryBuilder类构建实例sqlSessionFactory(用来创建SqlSessio对象)
            sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static SqlSession getSession() {
        SqlSession sqlSession = t1.get();
        if (sqlSession == null) {
            sqlSession = sessionFactory.openSession();
        }
        return sqlSession;
    }
    public static void closeSession() {
        SqlSession sqlSession = t1.get();
        if (sqlSession != null) {
            sqlSession.close();
        }
        t1.set(null);
    }
}

测试工具类:


    @Before
    public void setUp() throws Exception {
        inputStream = Resources.getResourceAsStream("mybatis-config.xml");
//      使用SqlSessionFactoryBuilder类构建实例sqlSessionFactory(用来创建SqlSessio对象)
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//        使用工具类MybatisUtil生成SqlSession对象
        SqlSession = MybatisUtil.getSession();
//getMapper() 方法会返回一个实现了 EmployeeDaoMapper 接口的动态代理对象,
// 可以直接调用接口中定义的方法来执行数据库操作。
        employeeDaoMapper = SqlSession.getMapper(EmployeeDaoMapper.class);
    }

    @After
    public void tearDown() throws Exception {
        //提交事务,数据同步
        SqlSession.commit();
        //释放资源
        inputStream.close();
        SqlSession.close();
    }
    <!--"queryById"是接口中调用的方法名
    deptResultMap表示返回的结果集
    -->
    <select id="queryById" resultMap="deptResultMap">
        select e.emp_id,
               emp_name,
               age,
               sex,
               e.dept_id,
               d.dept_id,
               d.dept_name,
               d.remark
        from dept d
                 left join employee e on e.dept_id = d.dept_id
        where d.dept_id = #{id}
   </select>
<!--
单个参数id查询, #{参数}
-->

告诉 MyBatis 创建一个预处理语句(PreparedStatement)参数,在 JDBC中,这样的一个参数在 SQL 中会由一个“?”来标识,并被传递到一个新的预处理语句中,就像这样:

 // 近似的 JDBC 代码,非 MyBatis 代码...
 String selectPerson = "SELECT  id,dept_name as deptName,remark FROM DEPT WHERE ID=?";//?占位符,类似Mybatics中的#{id}
 PreparedStatement ps = conn.prepareStatement(selectPerson);
 ps.setInt(1,id);

2.SQL语句操作:

//add接口的方法名,    deptId与实体类Dept中的属性|变量名一致
<insert id="add">
        insert into dept
        values (#{deptId}, #{deptName}, #{remark})
 </insert>

更新和删除语句类似

3.模糊查询

默认情况下,使用 #{}参数语法时,MyBatis 会创建 PreparedStatement参数占位符,并通过占位符安全地设置参数(就像使用 JDBC的? 一样)

  1. sql语句的LIKE关键字,搭配%通配符

        <select id="queryNameAge">
            select emp_name, age
            from employee
            where emp_name like concat('%', #{arg0}, '%')  //concat()字符串拼接
              and age = #{arg1}
        </select>
    
  2. SQL 语句中直接插入一个不转义的字符串,使用${}

    //parameterType传递参数数据类型     
    <select id="queryByNameLike" parameterType="string" resultType="dept">
             select id, dept_name as deptName, remark
             from dept
             where dept_name like ${deptName}
         </select>
    

4.返回多个聚合函数的结果

  <!--    统计人数和薪水最大值-->
    <select id="queryCountAndMaxSal" resultType="map">
        select count(*) as count, max(salary) as maxsarlary
        from employee
    </select>
<!-- 接口中 ->
Map<String, Object> queryCountAndMaxSal();

5.返回分组后的结果

接口中:

List<Map<String, Object>> queryCountDeptMinSarlary();

    <select id="queryCountDeptMinSarlary">
        select dept_id as deptId, min(salary) as minsarlary
        from employee
        where dept_id is not null
        group by dept_id;
    </select>
<!--测试类中->
        List<Map<String, Object>> maps = employeeDaoMapper.queryCountDeptMinSarlary();
        for (Map<String, Object> map : maps) {
           //deptId相当于集合的索引
            System.out.println(map.get("deptId"));
            System.out.println(map.get("minsarlary"));
        }

二.不同个数参数的处理

1.单个参数

#{随意命名}, 参数类型(parameterType)会被自动设置

2.对象参数

#{实体类属性变量名一致}

  <!--deptId...与实体类属性变量名一致-->  
  <insert id="add">
         insert into dept
        values (#{deptId}, #{deptName}, #{remark})
    </insert>

3.多个参数

默认为两类:

  • arg0、arg1、…… argX
  • param1、param1、…… paramX
//处理方式1:arg0、arg1...或param0、param1....
<select id="queryNameAge">
        select emp_name, age
        from employee
        where emp_name like concat('%', #{arg0}, '%')
          and age = #{arg1}
    </select>

Mapper的接口中:

//方式2:
//或@Param标注形参,emp_name与xml中的参数一致
//上面方式的param0可以继续使用,而arg0不能正常使用
List<Map<String, Object>> queryNameAge(@Param("emp_name") String name, @Param("age") int age);
//使用@Param标注,不然报错
 Cause: org.apache.ibatis.binding.BindingException: Parameter 'empName' not found. Available parameters are [arg1, arg0, param1, param2]

4.传入一个map类型的参数

如果在查询时有多个条件,那么我们可以把多个条件放在一个map中来作为参数传递进来

     <select id="queryByMap" resultType="employee">
         select emp_name, phone, address, salary from employee where emp_name = #{empName} or phone= #{phone}
     </select>
<!--#{}中的内容是测试时传进来的map的key值-->
<!--或者通过封装一个实体类把参数放进去,命名dto包->

5.添加注册方法引出service层概念

用户在注册时要先判断是否添加过,如果添加过则提示账号已经存在

DAO层:负责访问数据库进行数据的操作,取得结果集之后将结果集中的数据取出封装到VO类对象之后返回给service层。

DAO只完成基本的增删改查,虽然可以1-n,n-n,1-1关联,模糊、动态、子查询都可以。但是无论多么复杂的查询,dao只是封装增删改查。

service层:主要负责一些业务处理,比如多个操作需要放在一个事务中进行管理,事务回滚,一些复杂的逻辑业务处理就放到service层。

Service层的业务实现,具体要调用到已定义的DAO层的接口。封装Service层的业务逻辑有利于通用的业务逻辑的独立性和重复利用性。

行数据的操作,取得结果集之后将结果集中的数据取出封装到VO类对象之后返回给service层。

DAO只完成基本的增删改查,虽然可以1-n,n-n,1-1关联,模糊、动态、子查询都可以。但是无论多么复杂的查询,dao只是封装增删改查。

service层:主要负责一些业务处理,比如多个操作需要放在一个事务中进行管理,事务回滚,一些复杂的逻辑业务处理就放到service层。

Service层的业务实现,具体要调用到已定义的DAO层的接口。封装Service层的业务逻辑有利于通用的业务逻辑的独立性和重复利用性。

  • 14
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值