MyBatis 的使用 2


在这里插入图片描述

  将 sql 连接参数写到 properties 里,然后Mybatis 引用。


// jdbc.properties

jdbc.username=root
jdbc.password=Liu01234
jdbc.url=jdbc:mysql://localhost:3306/mydb1?characterEncoding=utf-8
jdbc.driverClass=com.mysql.cj.jdbc.Driver


// mybatis-config.xml 部分代码

<configuration>

    <!--  1.  -->
    <properties resource="jdbc.properties"></properties>

    <!--  2. 第二种方式 -->
<!--    <properties>-->
<!--        <property name="jdbc.url" value="jdbc:mysql://localhost:3306/mydb1?characterEncoding=utf-8"/>-->
<!--        <property name="jdbc.username" value="root"/>-->
<!--        <property name="jdbc.password" value="Liu01234"/>-->
<!--        <property name="jdbc.driverClass" value="com.mysql.cj.jdbc.Driver"/>-->
<!--    </properties>-->

	<environments default="d2">

        <environment id="d2">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <!-- ${} 动态参数-->
                <property name="driver" value="${jdbc.driverClass}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>

    </environments>
</configuration>

  注意 key 要做混合。

  引用实体类带包名,名称太长,可以设置别名。


// mybatis-config.xml 部分代码

<typeAliases>

<!--         1. 给单独的 实体类 设置别名-->
<!--         <typeAlias type="com.baidu.day.text.entity.Acount" alias="acountAli"></typeAlias> -->

<!--         2. 给一个包下所有的 实体 设置别名,类名默认首字母小写;也可以通过@Alias在类里修改-->
        <package name="com.baidu.day.text.entity"/>
    </typeAliases>

// Acount 类部分代码

@Data
@AllArgsConstructor
//@Alias("xxx")
public class Acount {

    private Integer id;

}

<!--  3. Mybatis 自带别名 -->
java.lang.Integer 为 integer 等等。

// IAcountMapper.xml 使用
//原
<select id="getAcountById" parameterType="java.lang.Integer" resultType="com.baidu.day.text.entity.Acount">
        select * from t_acount where id = #{id}
</select>

// 别名替换后
<select id="getAcountById" parameterType="integer" resultType="acount">
        select * from t_acount where id = #{id}
</select>

  主键回填。
  数据库设置主键自增后,添加新的数据,获取到这条数据的主键。


// IAcountMapper.xml 部分代码

<!--
    1. useGeneratedKeys 是否开启主键回填;keyProperty 赋值的主键,赋值给 acount 的 id,不是数据库。
-->
<!--    <insert id="addAcount" parameterType="acount" useGeneratedKeys="true" keyProperty="id">-->
<!--        insert into t_acount(username,img,balance) values(#{username},#{img},#{balance})-->
<!--    </insert>-->


<!--
    2. order,插入之前还是之后执行;keyProperty,语句执行后得到值赋给主键;resultType,语句执行后得到值的类型。
-->
    <insert id="addAcount" parameterType="acount">

        <selectKey order="AFTER" keyProperty="id" resultType="java.lang.Integer">
            select last_insert_id()
        </selectKey>

        insert into t_acount(username,img,balance) values(#{uname},#{img},#{balance})
    </insert>

<!--
       3. 不支持主键自增的数据库,获取主键方式。
       在插入语句执行之后,生成字符串赋值给 id
-->
    <insert id="addAcount" parameterType="acount">

        <selectKey order="BEFORE" keyProperty="id" resultType="integer">
            SELECT REPLACE(UUID(),'-','');
        </selectKey>
        INSERT into t_user (id,username,password) values(#{id},#{username},#{password});
    </insert>


// 测试代码

 @Test
    public void add() {
        Acount acount = new Acount(null,"zs","xx.png",30.0);
        SqlSession sqlSession = MybatisUtils.getSqlSession();

        System.out.println(acount);

        IAcountMapper acountMapper = sqlSession.getMapper(IAcountMapper.class);
        int sql = acountMapper.addAcount(acount);
        System.out.println(sql);

		// 主键回填之后的 acount 
        System.out.println(acount);

        sqlSession.commit();

        sqlSession.close();
    }

  解决当数据库的列名和实体类的属性名不一致问题。
  比如列名为username,实体类为uname。


// Acount.java

@Data
@AllArgsConstructor
public class Acount {

    private Integer id;
//    private String username;
    // 数据库列名和实体属性名不一致
    private String uname;
    private String img;
    private Double balance;

}


// IAcountMapper.xml 只是部分代码

// extends="",有大部分重复定义用继承。
<resultMap id="userResultMap" type="acount">

        <!--  column 数据库列;property 实体属性 ;只需要写上不一致的字段就行 -->
        <!-- 主键用 id 标签,其他用 result -->
<!--        <id column="id" property="id"></id>-->
        <result column="username" property="uname"/>
</resultMap>

<!--  
这里用了 resultType="acount",是因为上面只定义了不一致的字段。
如果换成 resultMap="userResultMap",则上面的定义要写完全,否则没定义的字段为 null
 -->
    <select id="getAcountById" parameterType="java.lang.Integer" resultType="acount">
        select * from t_acount where id = #{id}
    </select>

  ORM 映射关系。
  Mybatis 分两种,对一和对多关系。

  我使用的数据库表。
在这里插入图片描述
在这里插入图片描述

  一对一。


// Emp.java

@Data
public class Emp {

    private Integer empno; // 编码

    private String ename; // 姓名

    private Integer deptno; //部门编号

    private Double sal; // 公司

    private Double comm; // 奖金

    private Integer mgr; // 领导编号

    private Date hiredate; // 入职时间

    private String job; // 职位

	// 在员工对象里存储领导对象
    private Emp mgrEmp; // 领导对象

}


// IEmpMapper.java

public interface IEmpMapper {

    public Emp getEmpByEmpno(Integer empno);
}


// IEmpMapper.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">

<mapper namespace="com.baidu.day.text.mapper.IEmpMapper">

    <resultMap id="empResultMap" type="emp">
        <id column="empno" property="empno"/>
        <result column="ename" property="ename"/>
        <result column="job" property="job"/>
        <result column="sal" property="sal"/>
        <result column="comm" property="comm"/>
        <result column="mgr" property="mgr"/>
        <result column="hiredate" property="hiredate"/>
        <result column="deptno" property="deptno"/>

<!--
    员工和领导 一对一 关系 ,员工 emp 里有领导 emp 对象
    多表中存在相同列名的时候可以通过别名来解决
    property 实体属性
    javaType 实体属性的类型
-->
        <association property="mgrEmp" javaType="emp">
            <id column="mempno" property="empno" />
            <result column="mename" property="ename" />
            <result column="mjob" property="job" />
        </association>

    </resultMap>

<!--
    resultMap="empResultMap", 如果不写基本映射关系会为空
    resultType="emp" mgrEmp映射会为空,
 -->
    <select id="getEmpByEmpno" parameterType="java.lang.Integer" resultMap="empResultMap">
        select
            e.*,
            m.empno as mempno,
            m.ename as mename,
            m.job as mjob
        from emp e inner join emp m on (e.mgr = m.empno)
        where e.empno = #{empno}
    </select>


</mapper>


// MybatisTest.java 测试

public class MybatisTest {

    @Test
    public void testShow() {

        SqlSession sqlSession = MybatisUtils.getSqlSession();

        // mapper 写法
        IEmpMapper empMapper = sqlSession.getMapper(IEmpMapper.class);
        Emp emp = empMapper.getEmpByEmpno(7369);

        System.out.println(emp);

        sqlSession.close();
    }

}

  多对一。


@Data
public class Emp {

    private Integer empno; // 编码

    private String ename; // 姓名

    private Integer deptno; //部门编号

    private Double sal; // 公司

    private Double comm; // 奖金

    private Integer mgr; // 领导编号

    private Date hiredate; // 入职时间

    private String job; // 职位

    private Dept dept; // 员工对应的部门信息

}


@Data
public class Dept {

    private Integer deptno;
    private String dname;
    private String loc;

}


public interface IEmpMapper {

    // 查询所有的员工,要求员工的属性中包含部门信息
    public List<Emp> getEmpList();
}


// IEmpMapper.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">

<mapper namespace="com.baidu.day.text.mapper.IEmpMapper">

    <resultMap id="empResultMap" type="emp">
        <!--  基本映射  -->
        <id column="empno" property="empno"/>
        <result column="ename" property="ename"/>
        <result column="job" property="job"/>
        <result column="sal" property="sal"/>
        <result column="comm" property="comm"/>
        <result column="mgr" property="mgr"/>
        <result column="hiredate" property="hiredate"/>
        <result column="deptno" property="deptno"/>

<!--
    员工和部门 多对一 关系,多个员工属于一个部门
-->
        <association property="dept" javaType="dept">
            <id column="deptno" property="deptno" />
            <result column="dname" property="dname" />
            <result column="loc" property="loc" />
        </association>

    </resultMap>

    <select id="getEmpList" resultMap="empResultMap">
        select
            e.*,
            d.*
        from emp e inner join dept d on (e.deptno = d.deptno)
    </select>

</mapper>


// 测试类

public class MybatisTest {

    @Test
    public void testShow() {

        SqlSession sqlSession = MybatisUtils.getSqlSession();

        // mapper 写法
        IEmpMapper empMapper = sqlSession.getMapper(IEmpMapper.class);
        List<Emp> empList = empMapper.getEmpList();
        for (Emp emp : empList) {
            System.out.println(emp);
        }

        sqlSession.close();
    }

}

  一对多。


@Data
public class Dept {

    private Integer deptno;
    private String dname;
    private String loc;

    private List<Emp> empList; // 保存部门下的所有员工
}


@Data
public class Emp {

    private Integer empno; // 编码

    private String ename; // 姓名

    private Integer deptno; //部门编号

    private Double sal; // 公司

    private Double comm; // 奖金

    private Integer mgr; // 领导编号

    private Date hiredate; // 入职时间

    private String job; // 职位

//    private Emp mgrEmp; // 领导对象

    private Dept dept; // 员工对应的部门信息

}


public interface IDeptMapper {

    public Dept getDeptByDeptno(Integer deptno);
}


//IDeptMapper.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">

<mapper namespace="com.baidu.day.text.mapper.IDeptMapper">

    <resultMap id="deptResultMap" type="dept">
        <!--  基本映射  -->
        <id column="deptno" property="deptno"/>
        <result column="dname" property="dname"/>
        <result column="loc" property="loc"/>

<!--
    部门和员工 一对多 关系
    ofType 集合存储的类型,非集合
-->
       <collection property="empList" ofType="emp">

           <id column="empno" property="empno"/>
           <result column="ename" property="ename" />
           <result column="job" property="job"/>
           <result column="sal" property="sal"/>
           <result column="comm" property="comm"/>
           <result column="mgr" property="mgr"/>
           <result column="hiredate" property="hiredate"/>
           <result column="deptno" property="deptno"/>

<!--          可以套娃 员工对部门 多 对 一 -->
           <association property="dept" javaType="dept">

               <id column="deptno" property="deptno"/>
               <result column="dname" property="dname"/>
               <result column="loc" property="loc"/>

           </association>

       </collection>

    </resultMap>

    <select id="getDeptByDeptno" resultMap="deptResultMap">
        select
            d.*,
            e.*
        from dept d inner join emp e on (d.deptno = e.deptno)
        where d.deptno = #{deptno}
    </select>


</mapper>


public class MybatisTest {

    @Test
    public void testShow() {

        SqlSession sqlSession = MybatisUtils.getSqlSession();

        // mapper 写法
        IDeptMapper deptMapper = sqlSession.getMapper(IDeptMapper.class);
        Dept dept  = deptMapper.getDeptByDeptno(10);

        System.out.println(dept);

        for (Emp emp : dept.getEmpList()) {
            System.out.println(emp);
        }

        sqlSession.close();
    }

}

  mapper 接收参数问题。
  注意 #{arg1} 是占位符,数据库语句会预编译。占位符只能占位 value,不能占位 key。像查询语句,占位 key 值,不会返回数据。这时要使用 ${arg1},直接注入。

   如:


// 方法
public Emp findEmpByEmpno(Emp emp);

// mapper
<select id="findEmpByEmpno" parameterType="emp" resultType="emp">

	select #{ename},#{job} from emp where empno = #{empno}
	// 或
	select ${ename},${job} from emp where empno = ${empno}
</select>

// 测试
 		Emp emp = new Emp();
        emp.setEname("ename");
        emp.setJob("job");
        emp.setEmpno(7369);

        Emp empRes = empMapper.findEmpByEmpno(emp);
        System.out.println(empRes);

  区别如图:
在这里插入图片描述
在这里插入图片描述

  普通的传参方法,实际上跟参数名没有关系。

// 方法
public Emp getEmpByEmpno(Integer empno);

// mapper
<select id="getEmpByEmpno" resultType="emp">
        select * from emp where empno = #{ddasdfsdfaasdfd}
    </select>

// 测试
	@Test
	public void testGetEmpByEmpno() {
	
        SqlSession sqlSession = MybatisUtils.getSqlSession();

        IEmpMapper empMapper = sqlSession.getMapper(IEmpMapper.class);
        Emp empRes = empMapper.getEmpByEmpno(7369);
        System.out.println(empRes);

    }


// 打印,可以看到同样可以获取值

2021-01-16 17:07:32 DEBUG com.baidu.day.text.mapper.IEmpMapper.getEmpByEmpno {0}: 159 - ==>  Preparing: select * from emp where empno = ? 
2021-01-16 17:07:32 DEBUG com.baidu.day.text.mapper.IEmpMapper.getEmpByEmpno {0}: 159 - ==> Parameters: 7369(Integer)
2021-01-16 17:07:32 DEBUG com.baidu.day.text.mapper.IEmpMapper.getEmpByEmpno {0}: 159 - <==      Total: 1
Emp(empno=7369, ename=SMITH, deptno=20, sal=800.0, comm=null, mgr=7902, hiredate=Wed Dec 17 14:00:00 CST 1980, job=CLERK)

  mapper 接收参数有三种方式。一种是封装成对象(前面写过了)或map,一种是采用注解 @Param(“emp”);,一种是 ${arg1} 。


// 1.
// 方法
public Emp findEmpByEmpno(Integer empno, String column);

// mapper
select ${arg1} from emp where empno = ${arg0}
select ${param2} from emp where empno = ${param1}

// 2.
// 方法
public Emp findEmpByEmpno(@Param("empno") Integer empno,@Param("column") String column);

// mapper
select ${column} from emp where empno = #{empno}

// 3.
// 方法
public Emp findEmpByEmpno(Map<String, Object> map);

// mapper
select ${ename},${job} from emp where empno = ${empno}

// 测试
		Map<String, Object> map = new HashMap<>();
        map.put("ename","ename");
        map.put("job","job");
        map.put("empno",7369);

        Emp empRes = empMapper.findEmpByEmpno(map);
        System.out.println(empRes);


  ${arg1} 直接注入语句可以很灵活的控制接收。但要注意安全问题。


// 方法
public List<Map<String,Object>> findQuery(@Param("sql") String sql);

// mapper
<select id="findQuery" resultType="map">
        ${sql}
</select>

// 测试
	@Test
    public void testFindQuery(){
        IEmpMapper mapper = MyBatisUtils.getSqlSession().getMapper(IEmpMapper.class);
        List<Map<String, Object>> list= mapper.findQuery("select dname,loc from dept");

        for (Map<String, Object> map : list) {
            System.out.println(map);
        }
    }

  MyBatis 内数据库条件判断标签的使用。
  代码结构。有一部分没改动的代码我就不贴出来了。
在这里插入图片描述


public interface IEmpMapper {

    public List<Emp> getEmpList();

    public Emp getEmpByEmpno(Integer empno);

    public List<Emp> findEmp(Emp emp);

    public int update(Emp emp);

    public int batchDel(List<Integer> ids);

}


// IEmpMapper.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">

<mapper namespace="com.baidu.day.text.mapper.IEmpMapper">

<!--  提取公共部分  -->
    <sql id="base_emp">
        empno,
        ename,
        job,
        sal,
        comm,
        hiredate,
        mgr,
        deptno
    </sql>

    <select id="getEmpList" resultType="emp">
        select
        <include refid="base_emp" />
        from emp
    </select>

    <select id="getEmpByEmpno" resultType="emp">
        select
            <include refid="base_emp" />
        from emp where empno = #{empno}
    </select>

<!--
    where 标签,条件匹配并且自动删除多余 and
    <![CDATA[ ]]>,包装关键符号
-->
<!--
    <select id="findEmp" resultType="emp">

        select
            <include refid="base_emp"></include>
        from emp
        <where>
            <if test="ename != null and ename != ''">
                and ename like concat("%",#{ename},"%")
            </if>
            <if test="deptno != null">
                and deptno = #{deptno}
            </if>
            <if test="sal != null">
                <![CDATA[
                    and sal < #{sal}
                ]]>
            </if>
        </where>

    </select>
-->
<!--
    set 标签,条件匹配并且自动删除多余 ,
-->
<!--
    <update id="update">
        update emp
        <set>
            <if test="ename != null and ename != ''">
                ename = #{ename},
            </if>
            <if test="sal != null">
                sal = #{sal},
            </if>
            <if test="job != null">
                job = #{job},
            </if>
        </set>
        <where>
            empno = #{empno}
        </where>
    </update>
-->
<!--
    trim 标签,包装了 set 和 where;
    suffixOverrides 删除多余的后置字符;
    prefixOverrides 删除多余的前置字符
-->
    <select id="findEmp" resultType="emp">
        select
            <include refid="base_emp" />
        from emp
        <trim prefix="where" prefixOverrides="and">
            <if test="ename != null and ename != ''">
                and ename like concat("%",#{ename},"%")
            </if>
            <if test="deptno != null">
                and deptno = #{deptno}
            </if>
            <if test="sal != null">
                <![CDATA[
                    and sal < #{sal}
                ]]>
            </if>
        </trim>
    </select>

    <update id="update">
        update emp
        <trim prefix="set" suffixOverrides=",">
            <if test="ename != null and ename != ''">
                ename = #{ename},
            </if>
            <if test="sal != null">
                sal = #{sal},
            </if>
            <if test="job != null">
                job = #{job},
            </if>
        </trim>
        <where>
            empno = #{empno}
        </where>
    </update>

<!--
    foreach 标签
    collection 遍历集合
    open:第一次遍历的时执行
    close:最后一次遍历执行
    item:当前遍历的对象,类似var
    index: 遍历的索引,从0开始
    separator:分隔符,每遍历一次都会执行
-->
    <delete id="batchDel">
        delete from emp where empno in
<!--
    (7902,7934)
-->

        <foreach collection="list" open="(" close=")"
                 item="id" separator="," index="index">
            #{id}
        </foreach>

    </delete>

</mapper>


// 测试类

package com.baidu.day.text.mapper;
import com.baidu.day.text.entity.Emp;
import com.baidu.day.text.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;

public class IEmpMapperTest {

    @Test
    public void getEmpList() {

        SqlSession sqlSession = MybatisUtils.getSqlSession();
        IEmpMapper mapper = sqlSession.getMapper(IEmpMapper.class);

        List<Emp> empList = mapper.getEmpList();
        for (Emp emp : empList) {
            System.out.println(emp);
        }
        sqlSession.close();
    }

    @Test
    public void getEmpByEmpno() {

        SqlSession sqlSession = MybatisUtils.getSqlSession();
        IEmpMapper mapper = sqlSession.getMapper(IEmpMapper.class);

        Emp empRes = mapper.getEmpByEmpno(7369);
        System.out.println(empRes);
        sqlSession.close();
    }

    @Test
    public void findEmp() {

        SqlSession sqlSession = MybatisUtils.getSqlSession();
        IEmpMapper mapper = sqlSession.getMapper(IEmpMapper.class);
        Emp empOb = new Emp();
        empOb.setDeptno(10);

        List<Emp> empList = mapper.findEmp(empOb);
        for (Emp emp : empList) {
            System.out.println(emp);
        }
        sqlSession.close();
    }

    @Test
    public void update() {

        SqlSession sqlSession = MybatisUtils.getSqlSession();
        IEmpMapper mapper = sqlSession.getMapper(IEmpMapper.class);
        Emp emp = new Emp();
        emp.setEmpno(7499);
        emp.setEname("ALLEN1");

        int i = mapper.update(emp);
        System.out.println(i);

        sqlSession.commit();
        sqlSession.close();
    }

    @Test
    public void batchDel() {

        SqlSession sqlSession = MybatisUtils.getSqlSession();
        IEmpMapper mapper = sqlSession.getMapper(IEmpMapper.class);

        List<Integer> list = new ArrayList<>();
        list.add(7902);
        list.add(7934);
        int i = mapper.batchDel(list);
        System.out.println(i);

        sqlSession.commit();
        sqlSession.close();
    }
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值