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&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关键字。
-
当where标签内所有的条件都不成立,不会拼接where关键字,只要有一个条件成立就会在SQL语句中拼接where关键字。
-
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关键字。
-
当set标签内所有的条件都不成立,不会拼接set关键字,只要有一个条件成立就会在SQL语句中拼接set关键字。
注意:如果set包含的内容为空SQL语句会出错。
-
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();}
相关文章:

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.apa…...

景联文科技入选中国信通院发布的“人工智能数据标注产业图谱”
近日,由中国信息通信研究院、中国人工智能产业发展联盟牵头,联合中国电信集团、沈阳市数据局、保定高新区等70多家单位编制完成并发布《人工智能数据标注产业图谱》。景联文科技作为人工智能产业关键环节的代表企业,入选图谱中技术服务板块。…...

修改浏览器地址栏参数
Vue 修改当前页面地址栏参数 function updateUrlParameter(param: string, value: string) {const url new URL(window.location.href); // 获取当前页面的 URL// 解析哈希部分const hash url.hash ? url.hash.slice(1) : "";const [path, queryString] hash.sp…...

Spring Boot教程之二十五: 使用 Tomcat 部署项目
Spring Boot – 使用 Tomcat 部署项目 Spring Boot 是一个基于微服务的框架,在其中创建可用于生产的应用程序只需很少的时间。Spring Boot 建立在 Spring 之上,包含 Spring 的所有功能。如今,它正成为开发人员的最爱,因为它是一个…...

解决 Git 默认不区分文件名大小写的问题
不得不说 Git 默认不区分文件名大小写真是一个大坑,由于之前的项目目录比较乱,项目下的文件夹命名都不规范,这两天一直在整理,然后今天从服务器将项目重新 clone 下来后发现,之前将所有文件名首字母改成大写的改动全部…...

python学opencv|读取图像(十二)BGR图像转HSV图像
【1】引言 前述已经学习了opencv中图像BGR相关知识,文章链接包括且不限于下述: python学opencv|读取图像(六)读取图像像素RGB值_opencv读取灰度图-CSDN博客 python学opencv|读取图像(七)抓取像素数据顺利…...

信息安全工程师-选择题考点总结
密码理论知识 基础理论 一个密码系统至少由明文、密文、加密算法、解密算法和密钥五个部分组成,而其安全性是由密钥决定的。 按照密钥特征的不同,密码体制分为:对称密码体制和非对称密码体制。 按照对明文加密方式的不同,密码体制分为:流密码和分组密码。 非对称密码体…...

重学SpringBoot3-WebClient配置与使用详解
更多SpringBoot3内容请关注我的专栏:《SpringBoot3》 期待您的点赞👍收藏⭐评论✍ 重学SpringBoot3-WebClient配置与使用详解 1. 简介2. 环境准备2.1 依赖配置 3. WebClient配置3.1 基础配置3.2 高级配置3.3 retrieve()和exchange()区别 4. 使用示例4.1 …...

springBoot中的日志级别在哪里配置
在Spring Boot中,日志级别的配置可以通过多种方式来实现,主要包括在配置文件中设置、使用自定义的logback配置文件,以及在代码中动态配置等。以下是一些具体的配置方法: 一、在配置文件中设置日志级别 Spring Boot默认使用appli…...

统一身份安全管理体系的业务协同能力
随着集团企业数字化组织转型深化,各组织机构间业务协同程度提升。研发业务协同、数据驱动生产决策等数字化生产协作工作体系得以展开,企业内数据流转加快。企业对统一身份安全管理体系的业务协同管理和支撑能力要求提升: 统一身份管理流程需…...

JAVA课堂笔记23(IO流 (java.io包中))
第五章:IO流 (java.io包中) 三、字符流 1. 字符流的父类(抽象类): Reader:字符输入流 对应的操作为读操作 功能方法:read方法 Writer:字符输出流 对应的操作为写操作 功能方法:write方法 …...

C# DLT645 97/07数据采集工具
电表模拟器 97协议测试 07协议测试 private void btnSend_Click(object sender, EventArgs e) {string addr txtAddr.Text.Trim();string data txtDataFlg.Text.Trim();byte control 0x01;switch (cmbControl.SelectedIndex){case 0: control (byte)0x01; break;// 97协议c…...

中后台管理信息系统:Axure12套高效原型设计框架模板全解析
中后台管理信息系统作为企业内部管理的核心支撑,其设计与实现对于提升企业的运营效率与决策能力具有至关重要的作用。为了满足多样化的中后台管理系统开发需求,一套全面、灵活的原型设计方案显得尤为重要。本文将深入探讨中后台管理信息系统通用原型方案…...

Reactor 响应式编程(第四篇:Spring Security Reactive)
系列文章目录 Reactor 响应式编程(第一篇:Reactor核心) Reactor 响应式编程(第二篇:Spring Webflux) Reactor 响应式编程(第三篇:R2DBC) Reactor 响应式编程(…...

JVM 双亲委派模型以及垃圾回收机制
目录 1. JVM 内存区域划分 2. JVM 中类加载的过程 1) 类加载的基本流程 2) 双亲委派模型 3. JVM 中垃圾回收机制 1) 找到垃圾 a) 引用计数 b) 可达性分析 2) 释放垃圾 1. JVM 内存区域划分 一个运行起来的 Java 进程,其实就是一个 JVM 虚拟机。 而进程是…...

Delphi编写涂鸦桌面的小程序
用Delphi编写涂鸦桌面的小程序,类似于腾讯会议中的画板功能的实现。这里用Delphi实现代码给大家提供一些思路; 首先,新建一个Application,将Form1的WindowState设为wsMaximized,BorderStyle设为bsNone。这样做的目的就…...

智星云技术文档:GPU测速教程
安装gpu burn git clone https://github.com/wilicc/gpu-burn cd gpu-burn/ make测试 ./gpu_burn 60100.0% procd: 14280 (7373 Gflop/s) - 13390 (6997 Gflop/s) - 15912 (7110 Gflop/s) - 13184 (7055 Gflop/s) - 13464 (7369 Gflop/s) - 13974 (7351 Gflop/s) - 16626 (7…...

《Kali Linux 软件源更换攻略:优化软件获取与系统更新》
KALI为什么要换源 速度提升 Kali Linux 默认的软件源服务器通常位于国外。在从这些国外源下载软件包、更新系统时,会受到网络带宽、网络延迟等因素的限制。例如,在中国,连接到国外服务器的网络速度可能较慢,尤其是在下载大型软件…...

C# 在dataview可以直接增删改查mysql数据库
C# 在dataview可以直接增删改查mysql数据库 首先,确保你的项目中已经安装了MySql.Data。你可以通过NuGet包管理器安装它: Install-Package MySql.Data -Version 8.0.28using System; using System.Data; using MySql.Data.MySqlClient;public class My…...

C#—泛型约束
C#—泛型约束 概念: 泛型约束就是告知编译器类型参数必须具备的功能。 在没有任何约束的情况下,类型参数可以是任何类型。 编译器只能假定 System.Object 的成员,它是任何 .NET 类型的最终基类。当分配给泛型的类型参数不满足约束的类型时&…...

MeiliSearch:一款轻量级开源搜索引擎
Meilisearch 是由 Meili (一家总部位于法国的软件开发公司)创建的搜索引擎,目前在 Github 上有 47.9k stars。 Meillisearch 具备以下特色功能(ChatGPT-4o 翻译): 混合搜索:结合语义搜索和全文…...

Ansible playbook 详解与实战操作
一、概述 playbook 与 ad-hoc 相比,是一种完全不同的运用 ansible 的方式,类似与 saltstack 的 state 状态文件。ad-hoc 无法持久使用,playbook 可以持久使用。 playbook 是由一个或多个 play 组成的列表,play 的主要功能在于将事先归并为一…...

青少年夏令营管理系统的设计与开发(社团管理)(springboot+vue)+文档
💗博主介绍💗:✌在职Java研发工程师、专注于程序设计、源码分享、技术交流、专注于Java技术领域和毕业设计✌ 温馨提示:文末有 CSDN 平台官方提供的老师 Wechat / QQ 名片 :) Java精品实战案例《700套》 2025最新毕业设计选题推荐…...

加速合并,音频与字幕的探讨
因上一节。合并时速度太慢了。显卡没用上。所以想快一点。1分钟的视频用了5分钟。 在合并视频时,进度条中的 now=None 通常表示当前处理的时间点没有被正确记录或显示。这可能是由于 moviepy 的内部实现细节或配置问题。为了加快视频合并速度并利用 GPU 加速,可以采取以下措…...

Uniapp插件如何通过NFC读取多种证卡信息?
nfc读卡uniapp插件,由中软高科进行开发,主要是通过NFC读取居民身份证、港澳台居住证、外国人居住证、护照等证卡的信息。经过多个版本的升级更新,目前性能已趋于稳定,并且读卡速度较之最初版本有了大的提升。 注意事项 测试使用的…...

米哈游C++开发精选60道面试题及参考答案
C++ 面向对象的三个特征 封装是把数据和操作数据的函数捆绑在一起,并且对数据的访问进行限制。这样做的好处是可以隐藏对象的内部实现细节,只暴露必要的接口给外部。例如,在一个银行账户类中,账户余额这个数据成员是被封装起来的,外部不能直接访问和修改,而是通过存款、取…...

深度与视差的关系及其转换
深度与视差的关系及其转换 在计算机视觉和立体视觉中,深度和视差是两个重要的概念。理解这两者之间的关系对于实现立体图像处理、三维重建以及深度估计至关重要。在这篇博客中,我们将深入探讨深度和视差的概念,并介绍它们之间的转换关系。 …...

安全见闻全解析
跟随 泷羽sec团队学习 声明! 学习视频来自B站up主 泷羽sec 有兴趣的师傅可以关注一下,如涉及侵权马上删除文章,笔记只是方便各位师傅的学习和探讨,文章所提到的网站以及内容,只做学习交流,其他均与本人以及…...

搭建Tomcat(四)---Servlet容器
目录 引入 Servlet容器 一、优化MyTomcat ①先将MyTomcat的main函数搬过来: ②将getClass()函数搬过来 ③创建容器 ④连接ServletConfigMapping和MyTomcat 连接: ⑤完整的ServletConfigMapping和MyTomcat方法: a.ServletConfigMappin…...

PT2044A 单触控单输出IC
1 产品概述 ● PT2044A 是一款单通道触摸检测芯片。该芯片内建稳压电路,提供稳定电压给触摸感应电路使用。同时内部集成高效完善的触摸检测算法,使得芯片具有稳定的触摸检测效果。该芯片专为取代传统按键而设计,具有宽工作电压与低功耗的特性…...