MyBatis基础:MyBatis数据基本操作(2)
1. MyBatis映射器
2. MyBatis数据基本操作
示例项目结构:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>libing</groupId> <artifactId>com-helloworld-api</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <name>com-helloworld-api Maven Webapp</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.43</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.5</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.0-b07</version> <scope>provided</scope> </dependency> </dependencies> <build> <finalName>com-helloworld-api</finalName> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.6.2</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> </project>
<?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> <environments default="development"> <environment id="development"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/helloworld?characterEncoding=utf-8" /> <property name="username" value="root" /> <property name="password" value="root" /> </dataSource> </environment> </environments> <mappers> <mapper resource="mappers/RoleMapper.xml" /> </mappers> </configuration>
package com.libing.helloworld.model; public class Role { private Integer id; private String roleName; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getRoleName() { return roleName; } public void setRoleName(String roleName) { this.roleName = roleName; } }
<?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.libing.helloworld.dao.IRoleDao"> <resultMap id="baseResultMap" type="com.libing.helloworld.model.Role"> <id property="id" column="id" /> <result property="roleName" column="role_name" /> </resultMap> <select id="findAll" resultMap="baseResultMap"> SELECT id, role_name FROM role ORDER BY id ASC </select> <select id="findBySearchText" resultMap="baseResultMap"> SELECT id, role_name FROM role WHERE role_name LIKE CONCAT(CONCAT('%',#{searchText,jdbcType=VARCHAR}),'%') ORDER BY id ASC </select> <select id="findById" resultMap="baseResultMap"> SELECT id, role_name FROM role WHERE id = #{id} </select> <insert id="insert" useGeneratedKeys="true" keyProperty="id" parameterType="com.libing.helloworld.model.Role"> INSERT role ( role_name ) VALUES ( #{roleName} ) </insert> <update id="update" parameterType="com.libing.helloworld.model.Role"> UPDATE role SET role_name=#{roleName} WHERE id = #{id} </update> <delete id="deleteById"> DELETE FROM role WHERE id = #{id} </delete> <delete id="deleteByIds" parameterType="java.util.List"> DELETE FROM role WHERE id IN <foreach collection="list" index="index" item="item" open="(" separator="," close=")"> #{item} </foreach> </delete> </mapper>
package com.libing.helloworld.test; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import com.libing.helloworld.dao.IRoleDao; import com.libing.helloworld.model.Role; public class RoleTest { SqlSession sqlSession = null; @Before public void init() { String resource = "mybatis-config.xml"; InputStream inputStream = RoleTest.class.getClassLoader().getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); sqlSession = sqlSessionFactory.openSession(); } @Test public void findAll() { try { IRoleDao roleDao = sqlSession.getMapper(IRoleDao.class); List<Role> roles = roleDao.findAll(); Assert.assertNotNull(roles); Assert.assertTrue(roles.size() > 0); } catch (Exception e) { e.printStackTrace(); } finally { sqlSession.close(); } } @Test public void findById() { try { IRoleDao roleDao = sqlSession.getMapper(IRoleDao.class); Role role = roleDao.findById(1); Assert.assertNotNull(role); Assert.assertNotNull(role.getRoleName()); } catch (Exception e) { e.printStackTrace(); } finally { sqlSession.close(); } } @Test public void insert() { try { IRoleDao roleDao = sqlSession.getMapper(IRoleDao.class); Role role = new Role(); role.setRoleName("测试"); int result = roleDao.insert(role); // 只插入一条记录 Assert.assertEquals(1, result); // id不为null Assert.assertNotNull(role.getId()); } catch (Exception e) { e.printStackTrace(); } finally { sqlSession.rollback(); sqlSession.close(); } } public void Update() { try { IRoleDao roleDao = sqlSession.getMapper(IRoleDao.class); Role role = roleDao.findById(1); Assert.assertNotNull(role); role.setRoleName("测试"); int result = roleDao.update(role); // 只修改一条记录 Assert.assertEquals(1, result); // 修改后的值 Assert.assertEquals("测试", roleDao.findById(1).getRoleName()); } catch (Exception e) { e.printStackTrace(); } finally { sqlSession.rollback(); sqlSession.close(); } } @Test public void deleteById() { try { IRoleDao roleDao = sqlSession.getMapper(IRoleDao.class); Assert.assertNotNull(roleDao.findById(1)); // 调用删除方法 Assert.assertEquals(1, roleDao.deleteById(1)); // 再次查询,判断是否为null Assert.assertNull(roleDao.findById(1)); } catch (Exception e) { e.printStackTrace(); } finally { // 由于sqlSessionFactory.openSession()是不自动提交的,不手动执行sqlSession.commit()不会提交到数据库 sqlSession.rollback(); sqlSession.close(); } } @Test public void deleteByIds() { try { List<Integer> ids = new ArrayList<Integer>(); ids.add(1); ids.add(2); IRoleDao roleDao = sqlSession.getMapper(IRoleDao.class); int result = roleDao.deleteByIds(ids); Assert.assertTrue(result > 0); } catch (Exception e) { e.printStackTrace(); } finally { sqlSession.rollback(); sqlSession.close(); } } }
package com.libing.helloworld.dao; import java.util.List; import org.apache.ibatis.annotations.Delete; import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.Options; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Result; import org.apache.ibatis.annotations.Results; import org.apache.ibatis.annotations.Select; import org.apache.ibatis.annotations.SelectKey; import org.apache.ibatis.annotations.Update; import com.libing.helloworld.model.Role; public interface IRoleDao { @Select("SELECT id,role_name FROM role") @Results( value = { @Result(id = true, property = "id", column = "id"), @Result(property="roleName", column="role_name") }) List<Role> findAll(); @Select("SELECT id,role_name FROM role WHERE role_name LIKE CONCAT(CONCAT('%',#{searchText}),'%')") @Results( value = { @Result(id = true, property = "id", column = "id"), @Result(property="roleName", column="role_name") }) List<Role> findBySearchText(@Param("searchText") String searchText); @Select("SELECT id,role_name FROM role WHERE id = #{id}") @Results( value = { @Result(id = true, property = "id", column = "id"), @Result(property="roleName", column="role_name") }) Role findById(Integer id); @Insert({ "INSERT INTO role(id,role_name)", " VALUES ", "(#{id}, #{roleName})" }) @Options(useGeneratedKeys = true, keyProperty = "id") @SelectKey(statement="select last_insert_id()", keyProperty = "id", before = false, resultType = int.class) int insert(Role role); @Update({ "UPDATE role SET ", "role_name = #{roleName} ", "WHERE id = #{id}" }) int update(Role role); @Delete("DELETE FROM role WHERE id = #{id}") int deleteById(Integer id); int deleteByIds(List<Integer> ids); }
2.1 select
基于XML方式:
<resultMap id="baseResultMap" type="com.libing.helloworld.model.Role"> <id property="id" column="id" /> <result property="roleName" column="role_name" /> </resultMap> <select id="findAll" resultMap="baseResultMap"> SELECT id, role_name FROM role ORDER BY id ASC </select>
基于注解方式:
@Select("SELECT id,role_name FROM role") @Results( value = { @Result(id = true, property = "id", column = "id"), @Result(property="roleName", column="role_name") }) List<Role> findAll();
单元测试:
@Test public void findAll() { try { IRoleDao roleDao = sqlSession.getMapper(IRoleDao.class); List<Role> roles = roleDao.findAll(); Assert.assertNotNull(roles); Assert.assertTrue(roles.size() > 0); } catch (Exception e) { e.printStackTrace(); } finally { sqlSession.close(); } }
XML中大于符号与小于符号转义:
> >
< <
或使用 <![CDATA[ ]]>
<select id="findAll" resultMap="baseResultMap"> SELECT id, role_name FROM role WHERE id >= 10 ORDER BY id ASC </select>
<select id="findAll" resultMap="baseResultMap"> SELECT id, role_name FROM role WHERE id <![CDATA[>=]]> 10 ORDER BY id ASC </select>
Role findById(Integer id);
<select id="findById" resultMap="baseResultMap"> SELECT id, role_name FROM role WHERE id = #{id} </select>
@Test public void findById() { try { IRoleDao roleDao = sqlSession.getMapper(IRoleDao.class); Role role = roleDao.findById(1); Assert.assertNotNull(role); Assert.assertNotNull(role.getRoleName()); } catch (Exception e) { e.printStackTrace(); } finally { sqlSession.close(); } }
@Select("SELECT id,role_name FROM role WHERE id = #{id}") @Results( value = { @Result(id = true, property = "id", column = "id"), @Result(property="roleName", column="role_name") }) Role findById(Integer id);
传递多个参数:
1>. 使用Map传递参数
List<Role> findByMap(Map<String, String> params);
<select id="findByMap" parameterType="map" resultMap="baseResultMap"> SELECT id, role_name FROM role WHERE id != #{id} AND role_name = #{roleName} </select>
@Test public void findByMap() { try { Map<String, String> params = new HashMap<String, String>(); params.put("id", "1"); params.put("roleName", "管理员"); IRoleDao roleDao = sqlSession.getMapper(IRoleDao.class); List<Role> roles = roleDao.findByMap(params); Assert.assertNotNull(roles); Assert.assertTrue(roles.size() > 0); } catch (Exception e) { e.printStackTrace(); } finally { sqlSession.close(); } }
2>. 使用注解方式传递参数
import org.apache.ibatis.annotations.Param;
List<Role> findByAnnotation(@Param("id") Integer id, @Param("roleName") String roleName);
<select id="findByAnnotation" resultMap="baseResultMap"> SELECT id, role_name FROM role WHERE id != #{id} AND role_name = #{roleName} </select>
3>. 使用JavaBean传递参数
package com.libing.helloworld.params; public class RoleParam { private Integer id; private String roleName; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getRoleName() { return roleName; } public void setRoleName(String roleName) { this.roleName = roleName; } }
List<Role> findByRoleParam(RoleParam params);
<select id="findByRoleParam" parameterType="com.libing.helloworld.params.RoleParam" resultMap="baseResultMap"> SELECT id, role_name FROM role WHERE id != #{id} AND role_name = #{roleName} </select>
传递多个参数总结:
◊ 使用Map方式:Map扩展和维护困难,在实际应用中废弃这种传递参数方式。
◊ 使用@Param注解方式:参数个数<=5时是最佳的传参方式。
◊ JavaBean方式:当参数个数大于5个时,建议使用JavaBean方式。
2.2 insert
MyBatis在执行Insert语句之后返回一个整数,表示插入的记录数。
int insert(Role role);
<insert id="insert" useGeneratedKeys="true" keyProperty="id" parameterType="com.libing.helloworld.model.Role"> INSERT role ( role_name ) VALUES ( #{roleName} ) </insert>
其中,useGeneratedKeys:配置MyBatis使用JDBC的getGeneratedKeys()来获取由数据库内部生成的主键值,keyProperty:指定主键字段。
@Test public void insert() { try { IRoleDao roleDao = sqlSession.getMapper(IRoleDao.class); Role role = new Role(); role.setRoleName("测试"); int result = roleDao.insert(role); // 只插入一条记录 Assert.assertEquals(1, result); // id不为null Assert.assertNotNull(role.getId()); } catch (Exception e) { e.printStackTrace(); } finally { sqlSession.rollback(); sqlSession.close(); } }
@Insert({ "INSERT INTO role(id,role_name)", " VALUES ", "(#{id}, #{roleName})" }) @Options(useGeneratedKeys = true, keyProperty = "id") @SelectKey(statement="select last_insert_id()", keyProperty = "id", before = false, resultType = int.class) int insert(Role role);
2.3 update
MyBatis在执行update语句之后返回一个整数,表示更新的记录数。
int update(Role role);
<update id="update" parameterType="com.libing.helloworld.model.Role"> UPDATE role SET role_name = #{roleName} WHERE id = #{id} </update>
@Test public void Update() { try { IRoleDao roleDao = sqlSession.getMapper(IRoleDao.class); Role role = roleDao.findById(1); Assert.assertNotNull(role); role.setRoleName("测试"); int result = roleDao.update(role); // 只修改一条记录 Assert.assertEquals(1, result); // 修改后的值 Assert.assertEquals("测试", roleDao.findById(1).getRoleName()); } catch (Exception e) { e.printStackTrace(); } finally { sqlSession.rollback(); sqlSession.close(); } }
@Update({ "UPDATE role SET ", "role_name = #{roleName} ", "WHERE id = #{id}" }) int update(Role role);
2.4 delete
MyBatis在执行delete语句之后返回一个整数,表示删除的记录数。
int deleteById(Integer id);
<delete id="deleteById"> DELETE FROM role WHERE id = #{id} </delete>
@Test public void deleteById() { try { IRoleDao roleDao = sqlSession.getMapper(IRoleDao.class); Assert.assertNotNull(roleDao.findById(1)); // 调用删除方法 Assert.assertEquals(1, roleDao.deleteById(1)); // 再次查询,判断是否为null Assert.assertNull(roleDao.findById(1)); } catch (Exception e) { e.printStackTrace(); } finally { // 由于sqlSessionFactory.openSession()是不自动提交的,不手动执行sqlSession.commit()不会提交到数据库 sqlSession.rollback(); sqlSession.close(); } }
@Delete("DELETE FROM role WHERE id = #{id}") int deleteById(Integer id);
删除多条记录:
int deleteByIds(List<Integer> ids);
<delete id="deleteByIds" parameterType="java.util.List"> DELETE FROM role WHERE id IN <foreach collection="list" index="index" item="item" open="(" separator="," close=")"> #{item} </foreach> </delete>
@Test public void deleteByIds() { try { List<Integer> ids = new ArrayList<Integer>(); ids.add(1); ids.add(2); IRoleDao roleDao = sqlSession.getMapper(IRoleDao.class); int result = roleDao.deleteByIds(ids); Assert.assertTrue(result > 0); } catch (Exception e) { e.printStackTrace(); } finally { sqlSession.rollback(); sqlSession.close(); } }