Mybatis——(2)

2.2 Mybatis 工具类(了解)

为了简化MyBatis的开发,可将MyBatis进一步封装。

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
/*** Mybatis工具类*/
public class MybatisUtil {/*** 不让用户在外界创建工具类对象*/private MybatisUtil() {}/*** 初始化SqlSessionFactory对象*/private static SqlSessionFactory factory;static {try {InputStream in = Resources.getResourceAsStream("mybatis-config.xml");factory = new SqlSessionFactoryBuilder().build(in);} catch (IOException e) {e.printStackTrace();}}/*** 获取SqlSession对象的方法*/public static SqlSession getSession() {return factory.openSession();}
}

测试:

public class MybatisUtilTest {@Testpublic void test() {SqlSession sqlSession = MybatisUtil.getSession();System.out.println(sqlSession);sqlSession.close();}
}

2.4 Mapper代理方式(强制)

Mapper代理开发方式只需要程序员编写Mapper接口(相当于Dao接口),由MyBatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法。

程序员编写Mapper接口需要遵循一些开发规范,MyBatis可以自动生成Mapper接口实现类代理对象

2.4.1 开发规范

1、Mapper.xml文件中的namespace与mapper接口的类路径相同。

2、Mapper.xml中定义的每个标签的id与Mapper接口方法名相同。

3、Mapper.xml中定义的每个sql的parameterType的类型与Mapper接口方法的参数类型相同。

4、Mapper.xml中定义的每个sql的resultType的类型与Mapper接口方法返回值类型相同。

注:Mapper.xml映射文件最好和Mapper接口名称一致。

2.4.2 实体类

package org.example.mybatis.entity;
​
import java.util.Date;
​
/*** Emp实体类*/
public class Emp {private Integer empno;private String ename;private String job;private Integer mgr;private Date hiredate;private Double sal;private Double comm;private Integer deptno;
​public Integer getEmpno() {return empno;}
​public void setEmpno(Integer empno) {this.empno = empno;}
​public String getEname() {return ename;}
​public void setEname(String ename) {this.ename = ename;}
​public String getJob() {return job;}
​public void setJob(String job) {this.job = job;}
​public Integer getMgr() {return mgr;}
​public void setMgr(Integer mgr) {this.mgr = mgr;}
​public Date getHiredate() {return hiredate;}
​public void setHiredate(Date hiredate) {this.hiredate = hiredate;}
​public Double getSal() {return sal;}
​public void setSal(Double sal) {this.sal = sal;}
​public Double getComm() {return comm;}
​public void setComm(Double comm) {this.comm = comm;}
​public Integer getDeptno() {return deptno;}
​public void setDeptno(Integer deptno) {this.deptno = deptno;}
​@Overridepublic String toString() {return "Emp{" +"empno=" + empno +", ename='" + ename + '\'' +", job='" + job + '\'' +", mgr=" + mgr +", hiredate=" + hiredate +", sal=" + sal +", comm=" + comm +", deptno=" + deptno +'}';}
}

2.4.3 Mapper接口

package org.example.mybatis.mapper;
​
import org.example.mybatis.entity.Emp;
​
import java.util.List;
​
/** Mapper接口相当于我们之前写的Dao接口,只是在Mybatis里面我们习惯这么写而已。*/
public interface Mapper {List<Emp> select();
​Emp selectById(Integer empno);
​void insert(Emp emp);
​int update(Emp emp);
​boolean delete(Integer empno);
}

批量查询:方法返回值为List类型,表示SqlSession对象将调用selectList()方法。

单条查询:方法返回值为单个实体对象,表示SqlSession对象将调用selectOne()方法。

增删改:

方法返回值为void,表示SqlSession对象中insert,update,delete方法的返回值不做任何处理。

方法返回值为int类型,表示SqlSession对象中insert,update,delete方法的返回值直接返回。

方法返回值为boolean类型,表示根据SqlSession对象中的insert,update,delete方法返回值(影响数据库的条数)判断操作是否成功,如果影响数据库的条数大于0条,表示成功,否则表示失败。

2.4.4 mapper文件

<?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接口的全限定名保持一致-->
<mapper namespace="org.example.mybatis.mapper.Mapper"><!--statementId与Mapper接口的方法名称保持一致;parameterType的类型必须与方法的参数类型保持一致;resultType的类型必须与方法的返回值类型保持一致;--><select id="select" resultType="org.example.mybatis.entity.Emp">select empno,ename,job,mgr,hiredate,sal,comm,deptnofrom emp</select><select id="selectById" parameterType="java.lang.Integer"resultType="org.example.mybatis.entity.Emp">select empno,ename,job,hiredate,mgr,sal,comm,deptnofrom empwhere empno = #{empno}</select>
​<insert id="insert" parameterType="org.example.mybatis.entity.Emp">insert into emp(ename, job, mgr, hiredate, sal, comm, deptno)values (#{ename}, #{job}, #{mgr}, #{hiredate}, #{sal}, #{comm}, #{deptno})</insert><update id="update" parameterType="org.example.mybatis.entity.Emp">update empset ename=#{ename}, job=#{job}, mgr=#{mgr}, hiredate=#{hiredate}, sal=# {sal},comm=#{comm}, deptno=#{deptno}where empno=#{empno}</update><delete id="delete" parameterType="java.lang.Integer">deletefrom empwhere empno = #{empno}</delete>
</mapper>

加载mapper文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<!-- configuration 文件的根节点 -->
<configuration><!--properties 用于引入外部的properties配置文件resource:引入类路径下的文件url:引入磁盘或网路--><properties/><!--environments:多个配置环境;通过default属性可以对多个环境快速切换。environments default属性的值必须和某个environment的id值一致。--><!-- 和spring整合后 environments配置将废除,了解即可 --><environments default="mysql"><environment id="oracle"><!-- 配置事务:使用jdbc的事务管理 --><transactionManager type="JDBC"/><!-- 配置数据源:连接数据库的信息type: 表示连接是否使用连接池,POOLED表示mybatis中自带的连接池;JNDI、POOLED、UNPOOLED--><dataSource type="POOLED"><property name="driver"value="oracle.jdbc.driver.OracleDriver"/><property name="url"value="jdbc:oracle:thin:@localhost:1521:orcl"/><property name="username" value="scott"/><property name="password" value="tiger"/></dataSource></environment><environment id="mysql"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/mybatis?
characterEncoding=utf8&amp;useSSL=false"/><property name="username" value="root"/><property name="password" value=""/></dataSource></environment></environments>
​<!-- 加载映射文件的位置 --><mappers><mapper resource="mapper/Mapper.xml"/></mappers>
</configuration>

2.4.5 测试

package org.example.mybatis.test;
​
import org.apache.ibatis.session.SqlSession;
import org.example.mybatis.entity.Emp;
import org.example.mybatis.mapper.Mapper;
import org.example.mybatis.utils.MybatisUtil;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
​
import java.util.Date;
import java.util.List;
​
public class MapperTest {private SqlSession sqlSession;private Mapper mapper;
​@Beforepublic void before() {sqlSession = MybatisUtil.getSession();//获取Mapper接口的代理对象mapper = sqlSession.getMapper(Mapper.class);}
​@Afterpublic void after() {sqlSession.commit();sqlSession.close();}
​@Testpublic void test() {System.out.println(sqlSession);System.out.println(mapper);}
​@Testpublic void testSelect() {List<Emp> list = mapper.select();for (Emp emp : list) {System.out.println(emp);}}
​@Testpublic void testSelectById() {Emp emp = mapper.selectById(7938);System.out.println(emp);}
​@Testpublic void testInsert() {Emp emp = new Emp();emp.setEname("小明");emp.setJob("职员");emp.setSal(4500.0);emp.setComm(1000.0);emp.setMgr(1);emp.setHiredate(new Date());mapper.insert(emp);}
​@Testpublic void testUpdate() {Emp emp = new Emp();emp.setEmpno(7940);emp.setEname("小李");emp.setJob("秘书");emp.setSal(5300.0);emp.setComm(1300.0);emp.setMgr(1);emp.setHiredate(new Date());int result = mapper.update(emp);System.out.println("方法的返回值:" + result);}
​@Testpublic void testDelete() {boolean result = mapper.delete(7940);System.out.println("方法的返回值:" + result);}
}

三、Mybatis 核心配置文件(了解)

MyBatis的全局配置文件mybatis-config.xml,配置内容如下:

properties(属性)

settings(全局配置参数)

typeAliases(类型别名)

typeHandlers(类型处理器)

objectFactory(对象工厂)

plugins(插件)

environments(环境集合属性对象)

environment(环境子属性对象)

transactionManager(事务管理)

dataSource(数据源)

mappers(映射器)

四、Mybatis Mapper配置文件

mapper.xml映射文件中定义了操作数据库的Sql,每个Sql是一个statement,映射文件是MyBatis的核心。

4.1 parameterType输入映射(强制)

parameterType配置输入参数的类型。

4.1.1 表结构

CREATE TABLE `users` (
`id` int(11) PRIMARY KEY AUTO_INCREMENT,
`username` varchar(20),
`password` varchar(50),
`realname` varchar(20)
);
INSERT INTO `users` VALUES (1, 'admin', '123456', '管理员');
INSERT INTO `users` VALUES (2, 'tom', '123', '汤姆');
INSERT INTO `users` VALUES (3, 'jerry', '456', '杰瑞');
INSERT INTO `users` VALUES (4, 'zhangsan', '111', '张三');
INSERT INTO `users` VALUES (5, 'lisi', '222', '李四');

4.1.2 实体类

package org.example.mybatis.entity;public class User {private Integer id;private String username;private String password;private String realname;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public String getRealname() {return realname;}public void setRealname(String realname) {this.realname = realname;}@Overridepublic String toString() {return "Users{" +"id=" + id +", username='" + username + '\'' +", password='" + password + '\'' +", realname='" + realname + '\'' +'}';}
}

4.1.3 简单类型

Java基本数据类型以及包装类,String字符串类型。

mapper接口:

package org.example.mybatis.mapper;import org.example.mybatis.entity.Users;import java.util.List;public interface UsersMapper {List<Users> selectByRealname(String realname);
}

mapper文件:

<?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="org.example.mybatis.mapper.UsersMapper"><select id="selectByRealname" parameterType="java.lang.String"resultType="org.example.mybatis.entity.Users">select id, username, password, realnamefrom userswhere realname likeconcat('%', #{realname}, '%')</select>
</mapper>

测试:

package org.example.mybatis.test;import org.apache.ibatis.session.SqlSession;
import org.example.mybatis.entity.Users;
import org.example.mybatis.mapper.UsersMapper;
import org.example.mybatis.utils.MybatisUtil;
import org.junit.Test;import java.util.List;public class ParameterTypeTest {@Testpublic void testSimpleParam() {SqlSession sqlSession = MybatisUtil.getSession();UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);List<Users> list = usersMapper.selectByRealname("张");for (Users users : list) {System.out.println(users);}sqlSession.close();}
}

4.1.4 实体类或自定义类型

开发中通过实体类或pojo类型传递查询条件,查询条件是综合的查询条件,不仅包括实体类中查询条件

还包括其它的查询条件,这时可以使用包装对象传递输入参数。

4.1.4.1 自定义类型

分页类:

package org.example.mybatis.entity;public class Page {//当前页码private Integer pageNum = 1;//每页条数private Integer pageSize = 3;//总页数: 总记录数/每页条数,除不尽+1private Integer pages;//总记录数private Integer total;/*** mysql* 起始偏移量:(当前页码-1)*每页条数*/private Integer offset;/*** oracle* 起始条数:(当前页码-1)*每页条数+1* 结束条数: 当前页码*每页条数*/private Integer start;private Integer end;public Integer getPageNum() {return pageNum;}public void setPageNum(Integer pageNum) {this.pageNum = pageNum;}public Integer getPageSize() {return pageSize;}public void setPageSize(Integer pageSize) {this.pageSize = pageSize;}public Integer getPages() {return getTotal() % getPageSize() == 0 ? getTotal() / getPageSize() :getTotal() / getPageSize() + 1;}public void setPages(Integer pages) {this.pages = pages;}public Integer getTotal() {return total;}public void setTotal(Integer total) {this.total = total;}public Integer getOffset() {return (getPageNum() - 1) * getPageSize();}public void setOffset(Integer offset) {this.offset = offset;}public Integer getStart() {return (getPageNum() - 1) * getPageSize() + 1;}public void setStart(Integer start) {this.start = start;}public Integer getEnd() {return getPageNum() * getPageSize();}public void setEnd(Integer end) {this.end = end;}
}

复合类:UsersQuery

package org.example.mybatis.entity;/*** 多条件查询复合类*/
public class UsersQuery {private Users users;private Page page;public Users getUsers() {return users;}public void setUsers(Users users) {this.users = users;}public Page getPage() {return page;}public void setPage(Page page) {this.page = page;}
}
4.1.4.2 mapper接口
// 在UsersMapper接口上增加
List<Users> selectByPage(Page page);List<Users> selectByRealnameAndPage(UsersQuery usersQuery);
4.1.4.3 mapper文件
<select id="selectByPage" parameterType="org.example.mybatis.entity.Page"resultType="org.example.mybatis.entity.Users">select id,username,password,realname from users order by id limit #{offset}, #{pageSize}
</select>
<select id="selectByRealnameAndPage" parameterType="org.example.mybatis.entity.UsersQuery"resultType="org.example.mybatis.entity.Users">select id,username,password,realname from userswhere realname like concat('%',#{users.realname},'%')order by id limit #{page.offset}, #{page.pageSize}
</select>
4.1.4.4 测试
package org.example.mybatis.test;import org.apache.ibatis.session.SqlSession;
import org.example.mybatis.entity.Page;
import org.example.mybatis.entity.Users;
import org.example.mybatis.entity.UsersQuery;
import org.example.mybatis.mapper.UsersMapper;
import org.example.mybatis.utils.MybatisUtil;
import org.junit.Test;import java.util.List;public class ClassParamTests {@Testpublic void testClassParam1() {SqlSession sqlSession = MybatisUtil.getSession();UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);Page page = new Page();page.setPageNum(1);System.out.println("mysql起始偏移量:" + page.getOffset());System.out.println("起始条数:" + page.getStart());System.out.println("结束条数:" + page.getEnd());List<Users> list = usersMapper.selectByPage(page);for (Users users : list) {System.out.println(users);}sqlSession.close();}@Testpublic void testPojoParam2() {SqlSession sqlSession = MybatisUtil.getSession();UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);Page page = new Page();page.setPageNum(1);Users users = new Users();users.setRealname("张");UsersQuery usersQuery = new UsersQuery();usersQuery.setPage(page);usersQuery.setUsers(users);List<Users> list = usersMapper.selectByRealnameAndPage(usersQuery);for (Users u : list) {System.out.println(u);}sqlSession.close();}
}

4.1.5 Map类型

mapper接口:

// 在UsersMapper接口上增加
List<Users> selectUseMap(Map<String, Object> map)

mapper文件:

<select id="selectUseMap" parameterType="java.util.HashMap" resultType="org.example.mybatis.entity.Users">select id,username,password,realname from userswhere realname like concat('%',#{name},'%')order by id limit #{begin}, #{size}
</select>

测试:

@Test
public void testMapParam() {SqlSession sqlSession = MybatisUtil.getSession();UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);Map<String, Object> map = new HashMap<>();map.put("name", "李");map.put("size", 5);map.put("begin", 0);List<Users> list = usersMapper.selectUseMap(map);for (Users u : list) {System.out.println(u);}sqlSession.close();
}

4.1.6 多输入参数

MyBatis中允许有多个输入参数,可使用@Param注解。

这种做法类似与Map类型的输入参数,其中@Param注解的value属性值为Map的key,在映射文件中通

过ognl可获取对应的value,并且parameterType可以不指定类型。

mapper接口:

Users login(@Param("uname") String username, @Param("pwd") String password);

mapper文件:

<select id="login" parameterType="java.util.HashMap" resultType="org.example.mybatis.entity.Users">select id,username,password,realname from userswhere username=#{uname} and password=#{pwd}
</select>

测试:

@Test
public void testMultiParam() {SqlSession sqlSession = MybatisUtil.getSession();UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class);Users users = usersMapper.login("jerry", "456");System.out.println(users);sqlSession.close();
}

4.2 resultType输出映射(强制)

4.2.1 表结构

CREATE TABLE `person` (
`id` int(11) PRIMARY KEY AUTO_INCREMENT,
`person_name` varchar(20),
`person_age` int(4),
`person_address` varchar(50)
);
INSERT INTO `person` VALUES (1, '曹操', 40, '洛阳');
INSERT INTO `person` VALUES (2, '刘备', 38, '成都');
INSERT INTO `person` VALUES (3, '孙权', 29, '杭州');
INSERT INTO `person` VALUES (4, '关羽', 35, '荆州');
INSERT INTO `person` VALUES (5, '张飞', 32, '成都');
INSERT INTO `person` VALUES (6, '曹仁', 28, '许都');

4.2.2 实体类

package org.example.mybatis.entity;public class Person {private Integer id;private String personName;private Integer personAge;private String personAddress;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getPersonName() {return personName;}public void setPersonName(String personName) {this.personName = personName;}public Integer getPersonAge() {return personAge;}public void setPersonAge(Integer personAge) {this.personAge = personAge;}public String getPersonAddress() {return personAddress;}public void setPersonAddress(String personAddress) {this.personAddress = personAddress;}@Overridepublic String toString() {return "Person{" +"id=" + id +", personName='" + personName + '\'' +", personAge=" + personAge +", personAddress='" + personAddress + '\'' +'}';}
}

4.2.3 简单类型

查询出来的结果集只有一行且一列,可以使用简单类型进行输出映射。

mapper接口:

package org.example.mybatis.mapper;public interface PersonMapper {// 查询Person的总数量Integer selectCount();
}

mapper文件:

<?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="org.example.mybatis.mapper.PersonMapper"><select id="selectCount" resultType="java.lang.Integer">select count(1) from person</select>
</mapper>

测试:

package org.example.mybatis.test;import org.apache.ibatis.session.SqlSession;
import org.example.mybatis.mapper.PersonMapper;
import org.example.mybatis.utils.MybatisUtil;
import org.junit.Test;public class ResultTypeTest {@Testpublic void testSimpleResult() {SqlSession sqlSession = MybatisUtil.getSession();PersonMapper personMapper = sqlSession.getMapper(PersonMapper.class);int total = personMapper.selectCount();System.out.println("总记录数:" + total);sqlSession.close();}
}

4.2.4 实体类对象和列表

不管是输出的实体类是单个对象还是一个列表(list中包括实体类对象),在mapper.xml中resultType指定的类型是一样的。

在原始Dao的方式中,通过selectOne和selectList方法来区分返回值为单个对象或集合列表,而在mapper代理中,则通过接口中定义的方法返回值来区分。

mapper接口:

    Person selectById(Integer id);List<Person> selectAll();

mapper文件:

<select id="selectById" parameterType="java.lang.Integer" resultType="org.example.mybatis.entity.Person">select id,person_name personName,person_age personAge,person_addresspersonAddress from person where id=#{id}
</select><select id="selectAll" resultType="org.example.mybatis.entity.Person">select id,person_name personName,person_age personAge,person_addresspersonAddress from person
</select>

测试:

@Test
public void testResultType1() {SqlSession sqlSession = MybatisUtil.getSession();PersonMapper personMapper = sqlSession.getMapper(PersonMapper.class);Person person = personMapper.selectById(1);System.out.println(person);sqlSession.close();
}@Test
public void testResultType2() {SqlSession sqlSession = MybatisUtil.getSession();PersonMapper personMapper = sqlSession.getMapper(PersonMapper.class);List<Person> list = personMapper.selectAll();for (Person person : list) {System.out.println(person);}sqlSession.close();
}

4.2.5 resultMap

resultType可以指定将查询结果映射为实体类,但需要实体类的属性名和SQL查询的列名一致方可映射成功,当然如果开启下划线转驼峰 或 Sql设置列别名,也可以自动映射。

如果SQL查询字段名和实体类的属性名不一致,可以通过resultMap将字段名和属性名作一个对应关系,resultMap实质上还会将查询结果映射到实体类对象中。

resultMap可以实现将查询结果映射为复合型的实体类,比如在查询结果映射对象中包括实体类和list实现一对一查询和一对多查询。

mapper接口:

List<Person> selectAll();

mapper文件:使用resultMap作为statement的输出映射类型。

<resultMap id="selectResultMap" type="org.example.mybatis.entity.Person"><id property="id" column="id"/><result property="personName" column="person_name"/><result property="personAge" column="person_age"/><result property="personAddress" column="person_address"/>
</resultMap>
<select id="select" resultMap="selectResultMap">select id,person_name,person_age,person_address from person
</select>

resultType: 自动映射。

resultMap: 手动映射。

id: 唯一标识,名称;

type: 手动映射的java类型;

子标签 <id/> 配置数据库表中的主键和实体类中属性的对应关系;

子标签 <result/> 配置数据库表中的普通字段和实体类中属性的对应关系;

property:实体类中的成员变量名;

column:结果集中的字段名称;

javaType:实体类成员变量的类型,由mybaits自动识别,可不配置;

jdbcType:表字段的类型,由mybaits自动识别,可不配置;

typeHandler:自定义类型处理器,用的相对比较少;

测试:

@Test
public void testResultMap() {SqlSession sqlSession = MybatisUtil.getSession();PersonMapper personMapper = sqlSession.getMapper(PersonMapper.class);List<Person> list = personMapper.select();for (Person person : list) {System.out.println(person);}sqlSession.close();
}

4.3 动态SQL(强制)

4.3.1 什么是动态SQL

动态Sql是指MyBatis对Sql语句进行灵活操作,通过表达式进行判断,对Sql进行灵活拼接、组装。

比如:

我们要查询姓名中带 M 和 高于 1000的员工信息;

可能有时候我们需要不带条件查询;

可能有时候我们需要模糊查询;

可能有时候需要根据多条件查询;

动态SQL可以帮助我们解决这些问题。

通过Mybatis提供的各种标签方法实现动态拼接sql。

4.3.2 if标签

判断标签,当参数符合判断条件拼接SQL语句。

实体类:

package org.example.mybatis.entity;import java.util.Date;public class Emp {private Integer empno;private String ename;private String job;private Integer mgr;private Date hiredate;private Double sal;private Double comm;private Integer deptno;private String gender;public Integer getEmpno() {return empno;}public void setEmpno(Integer empno) {this.empno = empno;}public String getEname() {return ename;}public void setEname(String ename) {this.ename = ename;}public String getJob() {return job;}public void setJob(String job) {this.job = job;}public Integer getMgr() {return mgr;}public void setMgr(Integer mgr) {this.mgr = mgr;}public Date getHiredate() {return hiredate;}public void setHiredate(Date hiredate) {this.hiredate = hiredate;}public Double getSal() {return sal;}public void setSal(Double sal) {this.sal = sal;}public Double getComm() {return comm;}public void setComm(Double comm) {this.comm = comm;}public Integer getDeptno() {return deptno;}public void setDeptno(Integer deptno) {this.deptno = deptno;}public String getGender() {return gender;}public void setGender(String gender) {this.gender = gender;}@Overridepublic String toString() {return "Emp{" +"empno=" + empno +", ename='" + ename + '\'' +", job='" + job + '\'' +", mgr=" + mgr +", hiredate=" + hiredate +", sal=" + sal +", comm=" + comm +", deptno=" + deptno +", gender='" + gender + '\'' +'}';}
}

mapper接口:

package org.example.mybatis.mapper;import org.example.mybatis.entity.Emp;import java.util.List;public interface EmpMapper {List<Emp> selectUseIf(Emp emp);
}

mapper文件:

<?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="org.example.mybatis.mapper.EmpMapper"><select id="selectUseIf" parameterType="org.example.mybatis.entity.Emp"resultType="org.example.mybatis.entity.Emp">select empno,ename,job,mgr,hiredate,sal,comm,deptno from empwhere<!--注意:判断条件中使用的变量为实体类或输入参数的属性空字符串的判断仅能使用在字符串类型的属性中--><if test="ename != null and ename != ''">ename like concat('%',#{ename},'%')</if><if test="sal != null">and sal=#{sal}</if><if test="deptno != null">and deptno=#{deptno}</if></select>
</mapper>

测试:

package org.example.mybatis.test;import org.apache.ibatis.session.SqlSession;
import org.example.mybatis.entity.Emp;
import org.example.mybatis.mapper.EmpMapper;
import org.example.mybatis.utils.MybatisUtil;
import org.junit.Test;import java.util.List;/** 动态sql测试*/
public class DynamicSqlTest {@Testpublic void testIf() {SqlSession sqlSession = MybatisUtil.getSession();EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);Emp emp = new Emp();emp.setEname("S");emp.setSal(1300.0);emp.setDeptno(20);List<Emp> list = empMapper.selectUseIf(emp);for (Emp e : list) {System.out.println(e);}sqlSession.close();}
}

4.3.3 where标签

where标签,替代where关键字。

  1. 当where标签内所有的条件都不成立,不会拼接where关键字,只要有一个条件成立就会在SQL语句中拼接where关键字。

  2. where标签会自动剔除条件头部的and或者or关键字。

mapper接口:

List<Emp> selectUseWhere(Emp emp);

mapper文件:

<select id="selectUseWhere" parameterType="org.example.mybatis.entity.Emp"resultType="org.example.mybatis.entity.Emp">select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp<where><if test="ename != null and ename != ''">ename like concat('%',#{ename},'%')</if><if test="sal != null">and sal=#{sal}</if><if test="deptno != null">and deptno=#{deptno}</if></where>
</select>

测试:

@Test
public void testWhere() {SqlSession sqlSession = MybatisUtil.getSession();EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);Emp emp = new Emp();emp.setEname("S");emp.setSal(1300.0);emp.setDeptno(20);List<Emp> list = empMapper.selectUseWhere(emp);for (Emp e : list) {System.out.println(e);}sqlSession.close();
}

4.3.4 set标签

set标签,替代set关键字。

  1. 当set标签内所有的条件都不成立,不会拼接set关键字,只要有一个条件成立就会在SQL语句中拼接set关键字。

注意:如果set包含的内容为空SQL语句会出错。

  1. set标签会自动剔除条件末尾的任何不相关的逗号。

mapper接口:

void updateUseSet(Emp emp);

mapper文件:

<update id="updateUseSet" parameterType="org.example.mybatis.entity.Emp">update emp<set><if test="ename != null">ename=#{ename},</if><if test="job != null">job=#{job},</if><if test="mgr != null">mgr=#{mgr},</if><if test="hiredate != null">hiredate=#{hiredate},</if><if test="sal != null">sal=#{sal},</if><if test="comm != null">comm=#{comm},</if><if test="deptno != null">deptno=#{deptno},</if></set>where empno=#{empno}
</update>

测试:

@Test
public void testSet() {SqlSession sqlSession = MybatisUtil.getSession();EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);Emp emp = new Emp();emp.setEmpno(7938);emp.setEname("JACK");emp.setJob("MANAGER");emp.setMgr(7844);emp.setSal(5600.0);emp.setComm(1200.0);emp.setHiredate(new Date());emp.setDeptno(30);empMapper.updateUseSet(emp);sqlSession.commit();sqlSession.close();
}

4.3.5 trim标签

trim标签属性解析:

prefix:前缀,包含内容前加上某些字符。

suffix:后缀,包含内容后加上某些字符。

prefixOverrides:剔除包含内容前的某些字符。

suffixOverrides:剔除包含内容后的某些字符。

4.3.5.1 mapper接口
void insertUseTrim(Emp emp);
4.3.5.2 mapper文件
<!--trim标签--><insert id="insertUseTrim" parameterType="org.example.mybatis.entity.Emp">insert into emp<trim prefix="(" suffix=")" suffixOverrides=","><if test="ename != null">ename,</if><if test="job != null">job,</if><if test="mgr != null">mgr,</if><if test="hiredate != null">hiredate,</if><if test="sal != null">sal,</if><if test="comm != null">comm,</if><if test="deptno != null">deptno,</if></trim><trim prefix=" values(" suffix=")" suffixOverrides=","><if test="ename != null">#{ename},</if><if test="job != null">#{job},</if><if test="mgr != null">#{mgr},</if><if test="hiredate != null">#{hiredate},</if><if test="sal != null">#{sal},</if><if test="comm != null">#{comm},</if><if test="deptno != null">#{deptno},</if></trim></insert>
4.3.5.3 测试
@Test
public void testTrim() {SqlSession sqlSession = MybatisUtil.getSession();EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);Emp emp = new Emp();emp.setEname("CHRIS");emp.setJob("CLERK");emp.setMgr(1);emp.setSal(3400.0);emp.setComm(800.0);emp.setHiredate(new Date());emp.setDeptno(10);empMapper.insertUseTrim(emp);sqlSession.commit();sqlSession.close();
}
4.3.5.4 代替where标签
<select id="selectUseTrim" parameterType="org.example.mybatis.entity.Emp" resultType="org.example.mybatis.entity.Emp">select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp<trim prefix="where" prefixOverrides="and|or"><if test="ename != null and ename != ''">ename like concat('%',#{ename},'%')</if><if test="sal != null">and sal=#{sal}</if><if test="deptno != null">and deptno=#{deptno}</if></trim>
</select>
4.3.5.5 代替set标签
    <!--代替set标签--><update id="updateUseTrim" parameterType="org.example.mybatis.entity.Emp">update emp<trim prefix="set" suffixOverrides=","><if test="ename != null">ename=#{ename},</if><if test="job != null">job=#{job},</if><if test="mgr != null">mgr=#{mgr},</if><if test="hiredate != null">hiredate=#{hiredate},</if><if test="sal != null">sal=#{sal},</if><if test="comm != null">comm=#{comm},</if><if test="deptno != null">deptno=#{deptno},</if></trim>where empno=#{empno}</update>

4.3.6 foreach标签

向SQL传递数组或list,MyBatis使用foreach解析。

属性解析:

collection: 遍历的数组或集合对象名称。

SQL只接收一个数组参数,这时SQL解析参数的名称MyBatis固定为array。

SQL只接收一个List参数,这时SQL解析参数的名称MyBatis固定为list。

如果是通过一个实体类或自定义类型的属性传递到SQL的数组或List集合,则参数的名称为实体类或自定义类型中的属性名。

index: 为数组的下标。

item: 每次遍历生成的对象。

open: 开始遍历时拼接的串。

close: 结束遍历时拼接的串。

separator: 遍历的两个对象中需要拼接的串。

mapper接口:

void deleteUseForeach(Integer[] ids);
void insertUseForeach(List<Emp> empList);

mapper文件:

    <!--foreach标签--><delete id="deleteUseForeach" parameterType="java.lang.Integer"><!--delete from emp where empno in (1,2,3,4)-->delete from emp where empno in<foreach collection="array" open="(" close=")" separator="," item="id">#{id}</foreach></delete><insert id="insertUseForeach" parameterType="org.example.mybatis.entity.Emp">insert into emp(ename,job,mgr,hiredate,sal,comm,deptno) values<foreach collection="list" separator="," item="emp">(#{emp.ename},#{emp.job},#{emp.mgr},#{emp.hiredate},#{emp.sal},#{emp.comm},#{emp.deptno})</foreach></insert>

测试:

    @Testpublic void testForeach() {SqlSession sqlSession = MybatisUtil.getSession();EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);empMapper.deleteUseForeach(new Integer[]{1, 2, 3, 4});sqlSession.commit();sqlSession.close();}@Testpublic void testForeach2() {SqlSession sqlSession = MybatisUtil.getSession();EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);List<Emp> empList = new ArrayList<>();for (int i = 1; i <= 3; i++) {Emp emp = new Emp();emp.setEname("TOM" + i);emp.setJob("CLERK" + i);emp.setMgr(1);emp.setSal(4567.0);emp.setComm(123.0);emp.setHiredate(new Date());emp.setDeptno(10);empList.add(emp);}empMapper.insertUseForeach(empList);sqlSession.commit();sqlSession.close();}

4.3.7 choose标签

choose标签、when标签、otherwise标签的组合,类似于if-else-if判断。

<select id="">select...<choose><when test=""></when><when test=""></when><otherwise></otherwise></choose>
</select>

4.3.8 SQL片段

将实现的动态SQL判断代码块抽取出来,组成一个SQL片段,其它的statement中就通过 <include> 标

签就可以引用SQL片段,方便程序员进行开发。

注意:在SQL片段中不要包括where标签。

    <sql id="feildSql">empno,ename,job,mgr,hiredate,sal,comm,deptno</sql><sql id="whereSql"><if test="ename != null and ename != ''">ename like concat('%',#{ename},'%')</if><if test="sal != null">and sal=#{sal}</if><if test="deptno != null">and deptno=#{deptno}</if></sql><select id="selectUseSql" parameterType="org.example.mybatis.entity.Emp"resultType="org.example.mybatis.entity.Emp">select<include refid="feildSql"></include>from emp<where><include refid="whereSql"></include></where></select>

4.4 Map输入和输出类型(强制)

实体类:

package org.example.mybatis.entity;public class Dept {private Integer deptno;private String dname;private String loc;public Dept() {}public Dept(Integer deptno, String dname, String loc) {this.deptno = deptno;this.dname = dname;this.loc = loc;}/*** 获取* @return deptno*/public Integer getDeptno() {return deptno;}/*** 设置* @param deptno*/public void setDeptno(Integer deptno) {this.deptno = deptno;}/*** 获取* @return dname*/public String getDname() {return dname;}/*** 设置* @param dname*/public void setDname(String dname) {this.dname = dname;}/*** 获取* @return loc*/public String getLoc() {return loc;}/*** 设置* @param loc*/public void setLoc(String loc) {this.loc = loc;}public String toString() {return "Dept{deptno = " + deptno + ", dname = " + dname + ", loc = " + loc + "}";}
}

Mapper接口:

package org.example.mybatis.mapper;import java.util.List;
import java.util.Map;public interface DeptMapper {//查询List<Map<String, Object>> queryAllDept();//插入int insertDept(Map<String, Object> map);
}

Mapper文件:

<?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="org.example.mybatis.mapper.DeptMapper"><!--查询,输出参数是MapMybatis会把查询结果给我们封装成List<Map>因为一行数据就是一个Map--><select id="queryAllDept" resultType="hashmap">select *from dept</select><!--插入,输入参数是Map--><!--输入参数是hashmap,那么#{map中的key}--><insert id="insertDept" parameterType="hashmap">insert into deptvalues (#{id}, #{name}, #{address})</insert>
</mapper>

测试:

    @Testpublic void testMapResultType(){
// 获取Mapper接口的代理对象 (相当于实现类对象)SqlSession sqlSession = MybatisUtil.getSession();DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
//我们的输出参数是hashMap,那么mybatis会把查询结果集的列作为key,值作为valueList<Map<String, Object>> maps = mapper.queryAllDept();for(Map<String, Object> map:maps){System.out.println(map.get("DEPTNO")+"\t"+map.get("DNAME")+"\t"+map.get("LOC"));}sqlSession.close();}@Testpublic void testMapParameter(){
// 获取Mapper接口的代理对象 (相当于实现类对象)SqlSession sqlSession = MybatisUtil.getSession();DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);Map<String,Object> map = new HashMap<String,Object>();map.put("id",50);map.put("name","开发部门");map.put("address","北京市");int i = mapper.insertDept(map);System.out.println(i);sqlSession.close();}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/491867.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CCF-GESP 等级考试 2024年12月认证C++七级真题解析

2024年12月真题 一、单选题&#xff08;每题2分&#xff0c;共30分&#xff09; 正确答案&#xff1a;D 解析&#xff1a;考察字符类型和ASCII码值。 字符类型参与运算&#xff0c;是它所对应的ASCII码值在参与运算&#xff0c;运算结果为整数值。小写字母 b 的ASCII码为98&am…

递归实现指数型枚举(递归)

92. 递归实现指数型枚举 - AcWing题库 每个数有选和不选两种情况 我们把每个数看成每层&#xff0c;可以画出一个递归搜索树 叶子节点就是我们的答案 很容易写出每dfs函数 dfs传入一个u表示层数 当层数大于我们n时&#xff0c;去判断每个数字的选择情况&#xff0c;输出被选…

事务-介绍与操作四大特性

一.数据准备&#xff1a; 1.员工表&#xff1a; -- 员工管理 create table tb_emp (id int unsigned primary key auto_increment comment ID,username varchar(20) not null unique comment 用户名,password varchar(32) default 123456 comment 密码,n…

[白月黑羽]关于风机协议工具的解答

架构 python3.8pyqt5 先来看下原题&#xff1a; 视频中软件的效果 先来看下程序的效果如何&#xff0c;看上去大概相似 对应代码已经上传到了gitcode https://gitcode.com/m0_37662818/fan_protocol_tool/overview 实现中的难点是双悬浮可视化&#xff0c;同时要高亮悬浮对…

HCIA-Access V2.5_4_1_1路由协议基础_IP路由表

大型网络的拓扑结构一般会比较复杂&#xff0c;不同的部门&#xff0c;或者总部和分支可能处在不同的网络中&#xff0c;此时就需要使用路由器来连接不同的网络&#xff0c;实现网络之间的数据转发。 本章将介绍路由协议的基础知识、路由表的分类、静态路由基础与配置、VLAN间…

ISCTF复现-misc

File_Format 下载附件后用010打开查看文件头会发现是个exe文件 格式&#xff1a;文件描述&#xff08;后缀名&#xff09;&#xff0c;文件头(hex)&#xff1a;文件头标识&#xff08;十六进制&#xff09;PNG (png)&#xff0c;文件头(hex)&#xff1a;89504E47 PNGImageFile…

Windows设置所有软件默认以管理员身份运行

方法一、修改注册表 winr打开运行&#xff0c;输入“regedit”打开注册表&#xff1b; 打开此路径“计算机HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionPoliciesSystem”&#xff1b; 在右侧找到“EnableLUA”&#xff0c;将其值改为0&#xff0c;重启电脑。 …

【题解】—— LeetCode一周小结50

&#x1f31f;欢迎来到 我的博客 —— 探索技术的无限可能&#xff01; &#x1f31f;博客的简介&#xff08;文章目录&#xff09; 【题解】—— 每日一道题目栏 上接&#xff1a;【题解】—— LeetCode一周小结49 9.判断国际象棋棋盘中一个格子的颜色 题目链接&#xff1a;…

Docker安全性与最佳实践

一、引言&#xff1a;Docker安全性的重要性 Docker作为一种容器化技术&#xff0c;已成为现代应用程序部署和开发的核心工具。然而&#xff0c;随着容器化应用的普及&#xff0c;Docker的安全性问题也日益突出。容器本身的隔离性、网络配置、权限管理等方面的安全隐患&#xf…

利用notepad++删除特定关键字所在的行

1、按组合键Ctrl H&#xff0c;查找模式选择 ‘正则表达式’&#xff0c;不选 ‘.匹配新行’ 2、查找目标输入 &#xff1a; ^.*关键字.*\r\n (不保留空行) ^.*关键字.*$ (保留空行)3、替换为&#xff1a;&#xff08;空&#xff09; 配置界面参考下图&#xff1a; ​​…

上传图片的预览

解决:在上传图片时,1显示已有的图片 2显示准备替换的图片 前 后 在这个案例中可以预览到 【已有与准备替换】 2张图片 具体流程 1创建一个共享组件 与manage.py同级别路径的文件 manage.py custom_widgets.py# custom_widgets.py from django import forms from dja…

MySQL学习之DDL操作

目录 数据库的操作 创建 查看 选择 删除 修改 数据类型 表的创建 表的修改 表的约束 主键 PRIMARY KEY 唯一性约束 UNIQUE 非空约束 NOT NULL 外键约束 约束小结 索引 索引分类 常规索引 主键索引 唯一索引 外键索引 优点 缺点 视图 创建 删除 修改…

国际网络专线是什么?有什么优势?

国际网络专线作为一种独立的网络连接方式&#xff0c;通过卫星或海底光缆等物理链路&#xff0c;将全球不同国家和地区的网络直接互联&#xff0c;为企业提供了可靠的通信渠道。本文将详细探讨国际网络专线的优势以及其广泛的应用场景。 国际网络专线的优势解析 1. 专属连接&am…

密码编码学与网络安全(第五版)答案

通过如下代码分别统计一个字符的频率和三个字符的频率&#xff0c;"8"——"e"&#xff0c;“&#xff1b;48”——“the”&#xff0c;英文字母的相对使用频率&#xff0c;猜测频率比较高的依此为&#xff09;&#xff0c;t,*,5&#xff0c;分别对应s,o,n,…

【功能安全】随机硬件失效导致违背安全目标的评估(FMEDA)

目录 01 随机硬件失效介绍 02 FMEDA介绍 03 FMEDA模板 01 随机硬件失效介绍 GBT 34590 part5

mybatis 的动态sql 和缓存

动态SQL 可以根据具体的参数条件&#xff0c;来对SQL语句进行动态拼接。 比如在以前的开发中&#xff0c;由于不确定查询参数是否存在&#xff0c;许多人会使用类似于where 1 1 来作为前缀&#xff0c;然后后面用AND 拼接要查询的参数&#xff0c;这样&#xff0c;就算要查询…

Web APIs - 第5章笔记

目标&#xff1a; 依托 BOM 对象实现对历史、地址、浏览器信息的操作或获取 具备利用本地存储实现学生就业表案例的能力 BOM操作 综合案例 JavaScript的组成 ECMAScript: 规定了js基础语法核心知识。 比如&#xff1a;变量、分支语句、循环语句、对象等等 Web APIs : DO…

AI视频配音技术创新应用与商业机遇

随着人工智能技术的飞速发展&#xff0c;AI视频配音技术已经成为内容创作者和营销人员的新宠。这项技术不仅能够提升视频内容的吸引力&#xff0c;还能为特定行业带来创新的解决方案。本文将探讨AI视频配音技术的应用场景&#xff0c;并讨论如何合法合规地利用这一技术。 AI视频…

vlan和vlanif

文章目录 1、为什么会有vlan的存在2、vlan(虚拟局域网)1、vlan原理1. 为什么这样划分了2、如何实现不同交换机相同的vlan实现互访呢3、最优化的解决方法&#xff0c;vlan不同交换机4、vlan标签和vlan数据帧 5、vlan实现2、基于vlan的划分方式1、基于接口的vlan划分方式2、基于m…

Java每日一题(1)

给定n个数a1,a2,...an,求它们两两相乘再相加的和。 即&#xff1a;Sa1*a2a1*a3...a1*ana2*a3...an-2*an-1an-2*anan-1*an 第一行输入的包含一个整数n。 第二行输入包含n个整数a1,a2,...an。 样例输入 4 1 3 6 9 样例输出 117 答案 import java.util.Scanner; // 1:无…