mybatis03_配置文件

一、核心配置详解

这里只写几个个人认为比较常用的,具体的官网上面有明确的说明

1、properties

​ 这些属性可以在外部进行配置,并可以进行动态替换。个人感觉最常用的作用就是吧数据源内的硬编码提取出来。

​ 我们可以再创建一个mysql.properties文件用于存放数据库的信息,方便我们更改数据库信息,更改后的配置文件和数据库文件如下:

mysql.url = jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=UTF-8
mysql.driver = com.mysql.cj.jdbc.Driver
mysql.username = root
mysql.passwd = passwd

​ 在properties标签中有resource和url两个属性用于指定你写的配置在哪儿,我们可以用上文就提到过的方式${}进行取值。

<configuration>
    
    <properties resource="mysql.properties"></properties>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC" />
            <dataSource type="POOLED">
                <property name="driver" value="${mysql.driver}"/>
                <property name="url" value="${mysql.url}"/>
                <property name="username" value="${mysql.username}"/>
                <property name="password" value="${mysql.passwd}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
<!--        <mapper class="com.ls.dao.BookDao"></mapper>-->
        <package name="com.ls.dao"/>
    </mappers>
</configuration>

2、environments

​ 看名字就知道这里面可以包含多个environment,这能够方便我们切换不同的数据源,测试、生产、和开发用的数据库肯定是不一样的,如果想切换数据源直接更改environments的default的值即可,下面的代码块配置两个数据源,在实际使用时我们用的是id为product的数据库。同时environment标签中有 transactionManager type=" " 用于切换事务管理器(不同数据库的事务管理器也不一样,下面代码块是我瞎写的,理解这个意思就行)。

<environments default="product">
    
        <environment id="development">
            <transactionManager type="JDBC" />
            <dataSource type="POOLED">
                <property name="driver" value="${mysql.driver}"/>
                <property name="url" value="${mysql.url}"/>
                <property name="username" value="${mysql.username}"/>
                <property name="password" value="${mysql.passwd}"/>
            </dataSource>
        </environment>
    
    <environment id="product">
            <transactionManager type="ODBC" />
            <dataSource type="POOLED">
                <property name="driver" value="${mysql.driver}"/>
                <property name="url" value="${mysql.url}"/>
                <property name="username" value="${mysql.username}"/>
                <property name="password" value="${mysql.passwd}"/>
            </dataSource>
        </environment>
    </environments>

3、别名typeAliases

​ 在我们编写mapper映射文件时,如果需要写入参或者出参类型的话都是写全路径名称,有提示还好,我这一版他没提示,所以我们可以给这些类其一个简单的别名,在mybatis-config.xml有这么一个标签

<typeAliases>
  <typeAlias alias="book" type="com.ls.model.Book"/>
</typeAliases>

​ 在这个typeAliases标签中就可以给类起别名辣,不过不是很推荐这个用法,如果你有mybatisX插件的话你可以直接互相定位dao和xml的映射关系,但如果你没有装插件的话你想在mapper文件找到你的接口的话那不得根据包名找吗,所以不起别名从我做起。

<mapper namespace="com.ls.dao.BookDao">

    <insert id="add" parameterType="com.ls.model.Book">
    
        <selectKey keyProperty="bookId" order="AFTER" resultType="int">
            select last_insert_id()
        </selectKey>
        
        insert into book (book_name,book_author,create_time,update_time)
        values (#{bookName},#{bookAuthor},#{createTime},#{updateTime})
    </insert>
 </mapper>

​ 同时对于一些基本类型,mybatis已经给你提前写好别名了(但是我强迫症喜欢写全路径的),can can 下面,喜欢吗,官网截图的:

image-20230308162940278

二、映射文件

​ 映射文件是我们写sql语句的地方,在传统的JDBC编程中,我们一般会在数据持久层创建一个XxxDao,然后再dao包下创建impl包来实现我们XxxDao中的方法。Mybatis提供了映射的方式来代替传统的JDBC编程,这里的映射即为实体类与数据库表中记录的对应关系(上面纯属个人理解)。

1、在mybatis-config.xml中添加映射

​ 在自动查找资源方面,Java 并没有提供一个很好的解决方案,所以最好的办法是直接告诉 MyBatis 到哪里去找映射文件。一般有以下三种方式,这里最推荐第一种方式,毕竟可以全自动的扫描:

<!-- 将包内的映射器接口全部注册为映射器 -->
<mappers>
  <package name="org.mybatis.builder"/>
</mappers>

<!-- 使用相对于类路径的资源引用 -->
<mappers>
  <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
</mappers>

<!-- 使用完全限定资源定位符(URL) -->
<mappers>
  <mapper url="file:///var/mappers/AuthorMapper.xml"/>
</mappers>

<!-- 使用映射器接口实现类的完全限定类名 -->
<mappers>
  <mapper class="org.mybatis.builder.AuthorMapper"/>
</mappers>

​ 推荐一开始就把包建好把映射配置到mybatis-config.xml文件中在去干别的,因为真有可能忘记而报错,你还看不出来哪儿有问题。(也可能是我是个笨b看不出来报错信息)。

2、创建新项目

​ 为了方便下面入参、出参还有动态sql部分的笔记,我们再创建一个新的数据库和项目。这里只给出项目结构和主要类,其他工具、配置可移步到上一篇博客,Mapper代理开发。https://www.cnblogs.com/purearc/p/17195977.html

image-20230308200812709

⬇️数据库

CREATE TABLE `emp` (
  `emp_id` bigint NOT NULL AUTO_INCREMENT,
  `emp_name` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
  `address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  `email` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
  `create_time` datetime DEFAULT NULL,
  `update_time` datetime DEFAULT NULL,
  PRIMARY KEY (`emp_id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

⬇️ POJO(Plain Ordinary Java Object)类(在java开发手册嵩山版中POJO专指只有 setter/getter/toString 的 简单类,包括 DO/DTO/BO/VO 等。)

/**
 * date: 2023/3/2
 *
 * @author Arc
 */
package com.ls.pojo;

import lombok.Data;
import lombok.experimental.Accessors;

import java.util.Date;

@Data
@Accessors(chain = true)
public class Emp {
    private Long empId;
    private String empName;
    private String address;
    private String email;
    private Date createTime;
    private Date updateTime;

}

⬇️mapper映射文件(完整)

<?xml version="1.0" encoding="GBK"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.ls.mapper.EmpMapper">

    <insert id="add" parameterType="com.ls.pojo.Emp">
        insert into emp (emp_id,emp_name,address,email,create_time,update_time)
        values (#{empId},#{empName},#{address},#{email},#{createTime},#{updateTime});
    </insert>

    <select id="findByNameAndAddress" parameterType="map" resultType="com.ls.pojo.Emp">
        select emp_id empId,emp_name empName,address,email,create_time createTime,update_time updateTime
        from emp
        where emp_name like concat('%',#{empName},'%')
          and address like concat('%',#{address},'%');
    </select>
</mapper>

⬇️EmpMapper:

package com.ls.mapper;

import com.ls.pojo.Emp;
import org.apache.ibatis.annotations.Param;

import java.util.List;
import java.util.Map;

public interface EmpMapper {

    /**
     * 添加员工
     * @param emp
     * @return
     */
    int add(Emp emp);

    /**
     * 根据姓名和住址找
     * @param params
     * @return
     */
    List<Emp> findByNameAndAddress(Map<String,Object> params);


    /**
     *
     * @param empName
     * @param address
     * @return
     */
    List<Emp> findByNameAndAddress2(@Param("empName") String empName, @Param("address") String address);

    /**
     * 根据id查找
     * @param empId
     * @return
     */
    Emp selectById(long empId);
    
}

⬇️测试程序(完整)

/**
 * date: 2023/3/2
 *
 * @author Arc
 */
package com.ls.service;

import com.ls.mapper.EmpMapper;
import com.ls.pojo.Emp;
import com.ls.util.MybatisUtil;
import org.apache.ibatis.session.SqlSession;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class EmpService {
    public static void main(String[] args) {
//        testAdd();
//        testFindByNameAndAdress2();
        testSelect();
    }


    private static void testSelect() {
        SqlSession sqlSession = null;
        try {
            sqlSession = MybatisUtil.getSqlSession();
            EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
            Emp emp = empMapper.selectById(1L);
            System.out.println(emp);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
        }
    }
    /**
     * 测试传参map
     */
    private static void testFindByNameAndAdress() {
        SqlSession sqlSession = null;
        try {
            sqlSession = MybatisUtil.getSqlSession();
            EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
            Map<String, Object> params = new HashMap<>();
            params.put("empName","不举");
            params.put("address","大学");
//            System.out.println(params);
            List<Emp> empList = empMapper.findByNameAndAddress(params);
            for (Emp emp : empList) {
                System.out.println(emp);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
        }
    }

    /**
     * 注解传参
     */
    private static void testFindByNameAndAdress2() {
        SqlSession sqlSession = null;
        try {
            sqlSession = MybatisUtil.getSqlSession();
            EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
//            System.out.println(params);
            List<Emp> empList = empMapper.findByNameAndAddress2("不举","齐鲁");
            for (Emp emp : empList) {
                System.out.println(emp);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
        }
    }


    /**
     * 测试添加
     */
    private static void testAdd() {
        SqlSession sqlSession = null;
        try {
            sqlSession = MybatisUtil.getSqlSession();
            EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
            Emp emp = new Emp().setEmpName("庄不举").setAddress("齐鲁工业大学").setEmail("zxj@163.com")
                    .setCreateTime(new Date()).setUpdateTime(new Date());
            int result = empMapper.add(emp);
            sqlSession.commit();
            System.out.println(result > 0 ? "success" : "fail");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
        }
    }
}


3、入参

​ 前面我们已经尝试过把自己定义的类当作入参,但是实际情况可能有更加复杂的参数,比如说我们要同时查找Emp表中姓名和住址都符合的一条数据,那就需要传入两个参数,我们可以用map来封装(这里的map就是mybatis给他起的别名):

<select id="findByNameAndAddress" parameterType="map" resultType="com.ls.pojo.Emp">
        select emp_id empId,emp_name empName,address,email,create_time createTime,update_time updateTime
        from emp
        where emp_name like concat('%',#{empName},'%')
          and address like concat('%',#{address},'%');
    </select>

​ 需要注意我们在mapper映射文件中取的是map中的key,将我们要查找的条件放入自己定义好的map,再把这个叫params的map传到mapper文件中处理,就可以返回满足两个条件的了。

 private static void testFindByNameAndAdress() {
        SqlSession sqlSession = null;
        try {
            sqlSession = MybatisUtil.getSqlSession();
            EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
            Map<String, Object> params = new HashMap<>();
            params.put("empName","不举");
            params.put("address","大学");
//            System.out.println(params);
            List<Emp> empList = empMapper.findByNameAndAddress(params);
            for (Emp emp : empList) {
                System.out.println(emp);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
        }
    }

⬇️传入的两个参数

image-20230309111611811

​ 如果你不想用map的话,我们还可以通过注解的形式穿两个参数:

	/**
     *
     * @param empName
     * @param address
     * @return
     */
    List<Emp> findByNameAndAddress2(@Param("empName") String empName, @Param("address") String address);

​ 在mapper文件中取值符号内是@Param注解内的值,由于使用了注解,这里的paramType就不需要写了,写了也没作用。(至少我写map没报错,可能是注解导致失效了)

   <select id="findByNameAndAddress2" parameterType="map" resultType="com.ls.pojo.Emp">
        select emp_id empId,emp_name empName,address,email,create_time createTime,update_time updateTime
        from emp
        where emp_name like concat('%',#{empName},'%')
          and address like concat('%',#{address},'%');
    </select>

​ 在下面的测试程序中,我们传入的是两个String类型的字符串。

    /**
     * 注解传参
     */
    private static void testFindByNameAndAdress2() {
        SqlSession sqlSession = null;
        try {
            sqlSession = MybatisUtil.getSqlSession();
            EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
//            System.out.println(params);
            List<Emp> empList = empMapper.findByNameAndAddress2("不举","齐鲁");
            for (Emp emp : empList) {
                System.out.println(emp);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
        }
    }

4、出参

​ 出参可以是基本数据类型或者自定义数据类型,也可以是map,在我们写select *的时候因为mysql和java中对变量名称的规范不同,所以会给变量起一个别名(不起别名是nulli,如下图)。

image-20230309144230987

​ 这时候就可以自定义一个resultMap来对应数据表和实体类的名称。

    <resultMap id="EmpMap" type="com.ls.pojo.Emp">
        <id property="empId" column="emp_id"></id>
        <result property="empName" column="emp_name"></result>
        <result property="updateTime" column="update_time"></result>
        <result property="createTime" column="create_time"></result>
    </resultMap>

    <select id="selectById" resultMap="EmpMap">
        select *
        from emp
        where emp_id = #{empId}
    </select>

image-20230309144459322

​ 自然你也可以把这个本来返回值是Emp类型的方法定义为map类型的,毕竟这个类本身就是一个map。

    /**
     * 根据id查找
     * @param empId
     * @return
     */
    Emp selectById(long empId);
————————————————————————————————————
	Map<Emp> selectById2(long empId);
posted @ 2023-03-09 14:51  Purearc  阅读(35)  评论(0编辑  收藏  举报