SSM复习——M(MyBatis)二
注解形式工作量最小
三种方式:纯xml,xml+接口,注解+接口;
XML 映射器
XML 映射器的主要元素
元素名称 | 描述 | 备注 |
---|---|---|
mapper | 映射文件的根节点,只有namescape 一个属性 | namescape 用于区分不同的 mapper,全局唯一,绑定DAO接口。MyBatis 通过接口的完整限定名找到对应的 mapper 配置来执行 SQL 语句。 |
select | 查询语句 | 可以自定义参数,返回结果集等 |
insert | 插入语句 | 执行后返回一个整数,代表插入的条数 |
update | 更新语句 | 执行后返回一个整数,代表更新的条数 |
delete | 删除语句 | 执行后返回一个整数,代表删除的条数 |
sql | 允许定义一部分的 SQL,然后在各个地方引用它 | 例如,一张表列名,我们可以一次定义,在多个 SQL 语句中使用 |
resultMap | 用来描述数据库结果集与对象的对应关系 | 提供映射规则,是最复杂、最强大的元素 |
cache | 配置命名空间的缓存 | 用于启动 mybatis 的二级缓存 |
cache-ref | 引用其它命名空间的缓存配置 |
XML文件:UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.lsy.ibook.dao.UserMapper"> <!-- 启用二级缓存(注意:相关pojo需实现 Serializable 接口) --> <cache /> <!-- parameterType 可省略,mybatis 会自动探测并解析参数 --> <insert id="addUser" parameterType="com.lsy.ibook.bean.User"> insert into user(yhm, pwd, yhsf, zcsj) values (#{yhm},#{pwd},#{yhsf},#{zcsj}) <!-- 占位符和对象属性名一一对应 --> </insert> <delete id="deleteUser" > delete from user where yhbh = #{id} </delete> <delete id="deleteByIds"> delete from user where yhbh in <foreach item="id" collection="list" open="(" separator="," close=")"> #{id} </foreach> </delete> <update id="updateUser" > update user <set> <if test="pwd !=null and pwd !=''"> pwd = #{pwd} </if> <if test="yhsf !=null and yhsf !=''"> ,yhsf = #{yhsf} </if> <if test="yhtx != null and yhtx !=''"> ,yhtx = #{yhtx} </if> </set> where yhbh = #{yhbh} </update> <!-- 查询的记录按字段名与User属性同名原则,一一对应封装成一个 User 对象 --> <select id="selectUser" resultType="com.lsy.ibook.bean.User"> select * from user <where> <if test="yhbh != null and yhbh != ''"> and yhbh = #{yhbh} </if> <if test="yhm != null and yhm != ''"> and yhm = #{yhm} </if> <if test="pwd !=null and pwd !='' "> and pwd = #{pwd} </if> </where> </select> <select id="listUsers" resultType="com.lsy.ibook.bean.Userr"> select * from user <where> <if test="yhm != null and yhm != ''"> and yhm like concat('%',#{yhm},'%') </if> <if test="yhsf !=null and yhsf !='' "> and yhsf = #{yhsf} </if> <if test="zcsj != null and zcsj != ''"> and zcsj like concat('%',#{zcsj},'%') <!-- # 为占位符,可防止SQL注入 --> </if> <if test="sjh != null and sjh != ''"> and sjh like '%${sjh}%' <!-- $ 为取值符,无法防止SQL注入 --> </if> <if test="sex !=null and sex !='' "> and sex = #{sex} </if> <if test="email != null and email != ''"> and email like '%${email}%' </if> </where> </select> </mapper>
上面的 UserMapper.xml 放在 com.lsy.ibook.dao 包下面的
动态SQL
MyBatis 的动态 SQL 包括以下几种元素:
元素 | 作用 | 备注 |
---|---|---|
if | 判断语句 | 单条件分支判断 |
choose(when、otherwise) | 相当于 Java 中的 switch case 语句 | 多条件分支判断 |
trim、where | 辅助元素 | 用于处理一些SQL拼装问题 |
foreach | 循环语句 | 在in语句等列举条件常用 |
set | 更新赋值 | 用于update更新 |
bind | 辅助元素 | 拼接参数 |
<choose> <when test="判断条件1"> SQL语句1 </when > <when test="判断条件2"> SQL语句2 </when > <otherwise> SQL语句3 </otherwise> </choose> <foreach item="item" index="index" collection="list|array|map key" open="(" separator="," close=")"> #{item} </foreach>
配置文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> ...... <mappers> <mapper resource="com/lsy/ibook/dao/UserMapper.xml"></mapper> </mappers> </configuration>
配置文件中<mapper>指定的越来越多,可以之间用一个<package>来指定
测试
-
工具类:MyBatisUtil
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; public class MyBatisUtil { private static SqlSessionFactory ssf; static { try { // 1. 读取配置文件 mybatis-config.xml InputStream is = Resources.getResourceAsStream("mybatis-config.xml"); // 2. 根据配置文件构建SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(is); } catch (IOException e) { e.printStackTrace(); } } public static SqlSession getSqlSession(){ // 3. 通过SqlSessionFactory创建SqlSession return ssf.openSession(true);//true:开启事务自动提交,默认为false } }
-
测试类:UserMapperTest
@Log4j class UserMapperTest { @Test void addUser() { User user = new User(); user.setYhm("ccc"); user.setPwd("999999"); SqlSession sqlSession = MyBatisUtil.getSqlSession(); //通过 namespace + id 找到对应的 XML映射文件中的 SQL 语句 int ret = sqlSession.insert("com.lsy.ibook.dao.UserMapper.addUser",user); sqlSession.close(); log.info(ret); } @Test void deleteUser() { SqlSession sqlSession = MyBatisUtil.getSqlSession(); int ret = sqlSession.delete("com.lsy.ibook.dao.UserMapper.delete",10); sqlSession.close(); log.info(ret); } @Test void updateUser() { User user = new User(); user.setYhbh("12"); user.setPwd("666666"); SqlSession sqlSession = MyBatisUtil.getSqlSession(); int ret = sqlSession.update("com.lsy.ibook.dao.UserMapper.updateUser",user); sqlSession.close(); log.info(ret); } @Test void selectUser() { User user = new User(); user.setYhm("admin"); user.setPwd("123456"); SqlSession sqlSession = MyBatisUtil.getSqlSession(); User yh = sqlSession.selectOne("com.lsy.ibook.dao.UserMapper.selectByUser",user); sqlSession.close(); log.info(yh); } @Test void listUsers() { SqlSession sqlSession = MyBatisUtil.getSqlSession(); List<User> list= sqlSession.selectList("com.lsy.ibook.dao.UserMapper.listUsers"); sqlSession.close(); log.info(list); } }
XML 映射器(配合接口)
接口
在·mapper.xml的地方,同步建立一个同名的接口interface
接口默认是public的
接口可以指明指明返回值类型
接口的内容:xml里面所有跟id同名的方法,参数相同
例如 int add(User user)
逻辑就会改为:给xml文件映射一个接口,通过调用接口的方法,方法调用xml文件同名id(的sql语句)
sqlSession调用getMapper方法,通过动态代理使得 接口生成一个具体实现类,然后具体实现类回去调用接口的方法
package com.lsy.ibook.dao; public interface UserMapper { /** 新增用户 */ boolean addUser(User user); /** 通过主键ID删除用户 */ boolean deleteUser(Serializable id); /** 更新用户信息 */ boolean updateUser(User user); /** 获取单个用户*/ User selectUser1(Serializable id); /** 获取单个用户*/ User selectUser2(String yhm,String pwd); /** 获取单个用户*/ User selectUser3(User u1, User u2); /** 查询多个用户*/ ArrayList<User> listUsers(User user); }
XML文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.lsy.ibook.dao.UserMapper"> <insert id="addUser"> insert into user(yhm, pwd) values(#{yhm},#{pwd}) </insert> <delete id="deleteUser" > delete from user where yhbh = #{id} </delete> <update id="updateUser" > update user set pwd = #{pwd} where yhbh = #{yhbh} </update> <select id="selectUser1" resultType="com.lsy.ibook.bean.User"> select * from user where yhbh = #{id} </select> <select id="selectUser2" resultType="com.lsy.ibook.bean.User"> <!-- param1 匹配方法中的第1个参数 yhm, param2 匹配方法中的第2个参数 pwd --> <!-- param1,param2 可分别替换为 arg0,arg1 --> select * from user where yhm = #{param1} and pwd = #{param2} </select> <select id="selectUser3" resultType="com.lsy.ibook.bean.User"> <!-- param1 匹配方法中的第1个参数 u1, param2 匹配方法中的第2个参数 u2 --> <!-- param1,param2 可分别替换为 arg0,arg1 --> select * from user where yhm = #{param1.yhm} and pwd = #{param2.pwd} </select> <select id="listUsers" resultType="com.lsy.ibook.bean.User"> select * from user </select> </mapper>
上面的 UserMapper.xml 放在 com.lsy.ibook.dao 包下面的
配置文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> ...... <mappers> <!-- 下面两种引入映射器的方式都对,任选其一即可 --> <mapper resource="com/lsy/ibook/dao/UserMapper.xml"></mapper> <!-- <mapper class="com.lsy.ibook.dao.UserMapper" ></mapper> --> </mappers> </configuration>
配置文件中<mapper>指定的越来越多,可以之间用一个<package>来指定
测试
@Log4j class UserMapperTest { UserMapper userMapper; @Test void addUser() { User user = new User(); user.setYhm("ddd"); user.setPwd("999999"); SqlSession ss = MyBatisUtil.getSqlSession(); userMapper = ss.getMapper(UserMapper.class); boolean ret = userMapper.addUser(user); ss.close(); log.info(ret); } @Test void selectUser1() { SqlSession ss = MyBatisUtil.getSqlSession(); userMapper = ss.getMapper(UserMapper.class); User user = userMapper.selectUser1(1); log.info(user); ss.close(); } @Test void selectUser2() { SqlSession ss = MyBatisUtil.getSqlSession(); userMapper = ss.getMapper(UserMapper.class); User user = userMapper.selectUser2("admin","123456"); log.info(user); ss.close(); } @Test void selectUser3() { User u1 = new User(); u1.setYhm("admin"); User u2 = new User(); u2.setPwd("123456"); SqlSession ss = MyBatisUtil.getSqlSession(); userMapper = ss.getMapper(UserMapper.class); User user = userMapper.selectUser3(u1,u2); log.info(user); ss.close(); } }
注解映射器(配合接口)
接口
package com.lsy.ibook.dao; @CacheNamespace // 开启二级缓存 public interface UserMapper { @Insert("insert into user(yhm, pwd) values(#{yhm},#{pwd})") boolean addUser(User user); @Delete("delete from user where yhbh = #{id}") boolean deleteUser(Serializable id); @Update("update user set pwd = #{pwd} where yhbh = #{yhbh}") boolean updateUser(User user); @Select("select * from user where yhbh = #{id}") User selectUser1(Serializable id); //@Select("select * from user where yhm = #{arg0} and pwd = #{arg1}") @Select("select * from user where yhm = #{param1} and pwd = #{param2}") User selectUser2(String yhm,String pwd); @Select("select * from user where yhm = #{aaa} and pwd = #{bbb}") User selectUser3(@Param("aaa") String yhm, @Param("bbb") String pwd); //@Select("select * from user where yhm = #{arg0.yhm} and pwd = #{arg1.pwd}") @Select("select * from user where yhm = #{param1.yhm} and pwd = #{param2.pwd}") User selectUser4(User u1, User u2); // 动态 SQL(SQL语句由 UserProvider 类中的 listUsersProvider 方法提供) @SelectProvider(type = UserMapperProvider.class,method = "listUsers1SQL") ArrayList<User> listUsers(User user); @SelectProvider(type = UserMapperProvider.class,method = "listUsers2SQL") ArrayList<User> listUsers2(User u1,User u2); }
动态SQL Provider
的注解是 Provider
xxProvider,Provider即提供者
即一个独立的类(最好和这个mapper类前缀保持一致)
public class UserMapperProvider { public String listUsers1SQL(User user){ StringBuffer sb = new StringBuffer("select * from user where 1=1 "); if(StringUtil.isNotEmpty(user.getYhm())){ sb.append(" and yhm like '%${yhm}%' "); } if(StringUtil.isNotEmpty(user.getSjh())){ sb.append(" and sjh like concat('%',#{sjh},'%') "); } if(StringUtil.isNotEmpty(user.getYhsf())){ sb.append(" and yhsf = #{yhsf}"); } return sb.toString(); } // map 封装接口方法传递过来的多个参数 public String listUsers2SQL(Map<String,Object> map){ User u1 = (User) map.get("param1"); // 或:map.get("arg0") User u2 = (User) map.get("param2"); // 或:map.get("arg1") StringBuffer sb = new StringBuffer("select * from user where 1=1 "); if(StringUtil.isNotEmpty(u1.getYhm())){ sb.append(" and yhm like '%${param1.yhm}%' "); } if(StringUtil.isNotEmpty(u2.getYhsf())){ sb.append(" and yhsf = #{param2.yhsf}"); } return sb.toString(); } }
StringUtil.java:
public static boolean isNotEmpty(String s){ return s != null ? !"".equals(s) : false; }
配置文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> ...... <mappers> <mapper class="com.lsy.ibook.dao.UserMapper" ></mapper> </mappers> </configuration>
测试
@Log4j class UserMapperTest { UserMapper userMapper; @Test void addUser() { User user = new User(); user.setYhm("www"); user.setPwd("999999"); SqlSession ss = MyBatisUtil.getSqlSession(); userMapper = ss.getMapper(UserMapper.class); boolean ret = userMapper.addUser(user); ss.close(); log.info(ret); } @Test void selectUser3() { SqlSession ss = MyBatisUtil.getSqlSession(); userMapper = ss.getMapper(UserMapper.class); User user = userMapper.selectUser3("admin","123456"); log.info(user); ss.close(); } @Test void selectUser4() { User u1 = new User(); u1.setYhm("admin"); User u2 = new User(); u2.setPwd("123456"); SqlSession ss = MyBatisUtil.getSqlSession(); userMapper = ss.getMapper(UserMapper.class); User user = userMapper.selectUser4(u1,u2); log.info(user); ss.close(); } @Test void listUsers1() { User u = new User(); //u.setYhm("a"); u.setSjh("123"); //u.setYhsf("1"); SqlSession ss = MyBatisUtil.getSqlSession(); userMapper = ss.getMapper(UserMapper.class); ArrayList<User> list = userMapper.listUsers1(u); log.info(list); ss.close(); } @Test void listUsers2() { User u1 = new User(); u1.setYhm("a"); User u2 = new User(); u2.setYhsf("3"); SqlSession ss = MyBatisUtil.getSqlSession(); userMapper = ss.getMapper(UserMapper.class); ArrayList<User> list = userMapper.listUsers2(u1,u2); log.info(list); ss.close(); } }