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 类型的最终基类。当分配给泛型的类型参数不满足约束的类型时&…...

idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...

页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...

跨链模式:多链互操作架构与性能扩展方案
跨链模式:多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈:模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展(H2Cross架构): 适配层…...

苍穹外卖--缓存菜品
1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: ①每个分类下的菜品保持一份缓存数据…...
Robots.txt 文件
什么是robots.txt? robots.txt 是一个位于网站根目录下的文本文件(如:https://example.com/robots.txt),它用于指导网络爬虫(如搜索引擎的蜘蛛程序)如何抓取该网站的内容。这个文件遵循 Robots…...

中医有效性探讨
文章目录 西医是如何发展到以生物化学为药理基础的现代医学?传统医学奠基期(远古 - 17 世纪)近代医学转型期(17 世纪 - 19 世纪末)现代医学成熟期(20世纪至今) 中医的源远流长和一脉相承远古至…...

Yolov8 目标检测蒸馏学习记录
yolov8系列模型蒸馏基本流程,代码下载:这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中,**知识蒸馏(Knowledge Distillation)**被广泛应用,作为提升模型…...
JS设计模式(4):观察者模式
JS设计模式(4):观察者模式 一、引入 在开发中,我们经常会遇到这样的场景:一个对象的状态变化需要自动通知其他对象,比如: 电商平台中,商品库存变化时需要通知所有订阅该商品的用户;新闻网站中࿰…...
快刀集(1): 一刀斩断视频片头广告
一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...

Linux nano命令的基本使用
参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时,显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...