单表的CRUD。 C:Create,创建;R:Retrieve,读取;U:Update,更新;D,Delete,删除。
1. 首先配置映射文件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.alex.app.entity.User"> <select id="selectUser" parameterType="int" resultType="com.alex.app.entity.User"> select * from t_user where id = #{id} </select> <insert id="insertUser" parameterType="com.alex.app.entity.User"> insert into t_user(username,password) values(#{username},#{password}) </insert> <update id="updateUser" parameterType="com.alex.app.entity.User"> update t_user set username=#{username},password=#{password} where id = #{id} </update> <delete id="deleteUser" parameterType="int"> delete from t_user where id = #{id} </delete> </mapper>
2. 先提供一个工具类,方便测试
package com.alex.app.util; import java.io.IOException; import java.io.InputStream; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; public class MyBatisUtil { private MyBatisUtil() { } private static SqlSessionFactory factory; private static String configFile = "mybatis-config.xml"; static{ InputStream in; try { // 加载总配置文件 in = Resources.getResourceAsStream(configFile); // 创建SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in); } catch (IOException e) { e.printStackTrace(); } } /** * 获取SqlSession,并关闭自动提交,打开事务。 * 通俗点说就是将自动提交事务,改为手动提交 * @return */ public static SqlSession openSession(){ return factory.openSession(); } /** * 关闭session * @param session */ public static void coloseSession(SqlSession session){ if(session != null){ session.close(); } } }
SqlSession创建的时候,会关闭自动提交,打开事务。我们扫一眼SqlSessionFactory的openSessoin方法的源码就知道了。
以下源码分析不是重点,可以略过
eclipse中,使用 maven构建的项目要把源码一并下载下来,右击pom.xml选择Run As-->Maven Build..,在对话框Goals中输入命令dependency:sources,点Run,相关maven的插件和源码就都下载下来。
源码已经关联上,图标上有了个文本的标识
SqlSessionFactory是个接口,这里调用到的是DefaultSqlSessionFactory实现类的openSessoin方法。
public SqlSession openSession() { return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false); }我们看到第4个参数的值就是false。往里看代码直到JdbcTransaction类中,构造方法有
public JdbcTransaction(DataSource ds, TransactionIsolationLevel desiredLevel, boolean desiredAutoCommit) { dataSource = ds; level = desiredLevel; autoCommmit = desiredAutoCommit; }flase这个值会传递给JdbcTransaction构造方法的desiredAutoCommit,设置了autoCommmit 这个值为false。
那么肯定有地方调用了这个构造方法,在哪里呢,是在SqlSessoin调用insert/update/delete方法的时候
public int insert(String statement, Object parameter) { return update(statement, parameter); }调用了update(statement, parameter)
public int update(String statement, Object parameter) { try { dirty = true; MappedStatement ms = configuration.getMappedStatement(statement); return executor.update(ms, wrapCollection(parameter)); } catch (Exception e) { throw ExceptionFactory.wrapException("Error updating database. Cause: " + e, e); } finally { ErrorContext.instance().reset(); } }继续往里跟executor.update(ms, wrapCollection(parameter));直到BatchExecutor类的doUpdate方法
public int doUpdate(MappedStatement ms, Object parameterObject) throws SQLException { //.....省略这些代码,节省篇幅 if (sql.equals(currentSql) && ms.equals(currentStatement)) { //.....省略这些代码,节省篇幅 } else { Connection connection = getConnection(ms.getStatementLog()); stmt = handler.prepare(connection); //.....省略这些代码,节省篇幅 } //.....省略这些代码,节省篇幅 }其中有一句代码是Connection connection = getConnection(ms.getStatementLog());
protected Connection getConnection(Log statementLog) throws SQLException { Connection connection = transaction.getConnection(); if (statementLog.isDebugEnabled()) { return ConnectionLogger.newInstance(connection, statementLog, queryStack); } else { return connection; } }Connection connection = transaction.getConnection();transaction对象这里是JdbcTransaction对象
public Connection getConnection() throws SQLException { if (connection == null) { openConnection(); } return connection; }openConnection();
protected void openConnection() throws SQLException { // 省略... setDesiredAutoCommit(autoCommmit); }
protected void setDesiredAutoCommit(boolean desiredAutoCommit) { try { if (connection.getAutoCommit() != desiredAutoCommit) { //..... connection.setAutoCommit(desiredAutoCommit); } } catch (SQLException e) { // .... } }connection.setAutoCommit(desiredAutoCommit);desiredAutoCommit参数的值就是在SqlSession调用openSessoin()方法的时候,第4个参数值 false
public SqlSession openSession() { return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false); }上面的源分析码可以无视,不是重点
3. 编写UserTest测试类。
package com.alex.app.test; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import com.alex.app.entity.User; import com.alex.app.util.MyBatisUtil; public class UserTest { /** * C,Create 创建 */ @Test public void testInsertUser() { SqlSession session = null; try { // 获取SqlSession session = MyBatisUtil.openSession(); // 准备要添加的数据 User user = new User(); user.setUsername("belongtou"); user.setPassword("9988"); /*insert()方法说明 * 第一个参数,就是User.xml的namespace属性 + "." + insert标签的id属性 * 我们看到User.xml的namespace属性正好与我们的实体User的完整类名一致 * 所以我们可以使用反射的方式取到这个完整的类名,然再后 + "." + insert标签的id属性, * 一长串的字符写起来很容易出错的。我们说约定优与配置::: * */ session.insert(User.class.getName()+".insertUser",user); /* 需要手动提交事务 * mybaits的事务在创建SqlSessoin时,自动将作了一个操作:Connection.setAutoCommint(false),将事务设置为非自动提交。 */ session.commit(); } catch (Exception e) { e.printStackTrace(); // 异常回滚 session.rollback(); }finally{ // 关闭SqlSession MyBatisUtil.coloseSession(session); } } /** * R,Retrieve 读取 */ @Test public void testSelectUser() { SqlSession session = null; try { session = MyBatisUtil.openSession(); User user = (User)session.selectOne(User.class.getName()+".selectUser",2); // 断言 user不为空 Assert.assertNotNull(user); // 断言user对象的Id就是我们刚上面所查询到的ID值 2 // assertEquals第一个参数是预期值,第二个参数是实际 Assert.assertEquals(user.getId(), 2); } catch (Exception e) { e.printStackTrace(); } } /** * U, Update 更新 */ @Test public void testUpdateUser() { SqlSession session = null; try { session = MyBatisUtil.openSession(); User user = (User)session.selectOne(User.class.getName()+".selectUser", 1); Assert.assertNotNull(user);//断言user对象不为null user.setUsername("Nunu"); user.setPassword("7788"); session.update(User.class.getName()+".updateUser", user); session.commit(); User user2 = (User)session.selectOne(User.class.getName()+".selectUser", 1); Assert.assertNotNull(user2); //断言,user2所查询到的值,与我们上面更新时(更新user对象)所设置的值是否一致。一致则测试通过 Assert.assertEquals(user2.getUsername(), "Nunu"); Assert.assertEquals(user2.getPassword(), "7788"); } catch (Exception e) { e.printStackTrace(); session.rollback(); }finally{ MyBatisUtil.coloseSession(session); } } /** * D ,Delete 删除 */ @Test public void testDeleteUser() { SqlSession session = null; try { session = MyBatisUtil.openSession(); session.delete(User.class.getName()+".deleteUser", 3); session.commit(); } catch (Exception e) { e.printStackTrace(); session.rollback(); }finally{ MyBatisUtil.coloseSession(session); } } }
注意,SqlSession在创建的时候,MyBatis把事务自动设置为了false,就是JDBC规范的Connection.setAutoCommit(false);事务不会自动提交。再做URD的时候,需要调用SqlSession的commint() 方法提交。
4. 映射文件问题
现在我们映射文件有很多重复主要是parameterType="com.alex.app.entity.User" resultType="com.alex.app.entity.User" 这里,都是重复的。
我们可以在mybatis-config.xml配置文件中properties标签和environments之前,使用typeAlias 标签配置一个别名
<?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> <!-- 引入外部properties文件 --> <properties resource="jdbc.properties" /> <typeAliases> <typeAlias type="com.alex.app.entity.User" alias="User"/> </typeAliases> <environments default="development"> <!-- 省略部分配置 --> </environments> <!-- 映射文件 --> <mappers> <mapper resource="com/alex/app/entity/User.xml"/> </mappers> </configuration>
那么在映射文件中,就可以使用这个别名来定义这些属性 parameterType="User" resultType="User"
<?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.alex.app.entity.User"> <select id="selectUser" parameterType="int" resultType="User"> select * from t_user where id = #{id} </select> <insert id="insertUser" parameterType="User"> insert into t_user(username,password) values(#{username},#{password}) </insert> <update id="updateUser" parameterType="User"> update t_user set username=#{username},password=#{password} where id = #{id} </update> <delete id="deleteUser" parameterType="int"> delete from t_user where id = #{id} </delete> </mapper>
单元的测试断言部分不用纠结,可以直接去数据库中查看。或者最笨的方式直接把信息打印到控制台上查看。
另外还有几个问题,就是在执行CRUD操作的时候,会破坏数据库中的数据;每个单元测都是独立的,不依赖与其它单元测试,假如我先执行一个删除动作,删除Id 为2的数据,之后执行了查询动作,查询ID为2的数据,这时候可能会出错。
单元测试是为了测试我们的功能片断是否正常,每个分支是否覆盖到,一些代码的边界是否存在的问题等等,这里不纠结它了,后面我们再研究。
相关推荐
只增强,MyBatis-Flex 支持 CRUD、分页查询、多表查询、批量操作,但不丢失 MyBatis 原有的任何功能。高性能,MyBatis-Flex 采用独特的技术架构、相比许多同类框架,MyBatis-Flex 的在增删改查等方面的性能均超越其 ...
MyBatis CRUD操作Java,MyBatis,单元测试,MySql,Maven的CRUD操作这包含构建和运行MyBatisCRUD应用程序所需的一组指令。建设项目。先决条件设置了JDK 1.6.x或更高版本的Maven 2或更高版本的java_home和m2_home。...
mybatis 增强工具包,简化 CRUD 操作。Mybatis-Plus 在 Mybatis 的基础上进行扩展,只做...内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求。
MyBatis 采用注解方式实现CRUD 参考博客:https://www.jianshu.com/p/74fbe5f1e610
MyBatis增删改查(CRUD)操作
发现一些通用的操作,比如单表的CURD,在每一个xml文件中都需要定义一遍。而且每个人写的风格又不统一。于是寻找了一个解决 办法,使用maven插件mybatis-generator。使用一段时间之后,发现还是不能令人满意。每次...
主要给大家介绍了关于Spring boot整合Mybatis实现级联一对多CRUD操作的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
mybatis中使用接口编程方式实现CRUD模板
SpringBoot+MybatisCRUD 整合案例 . 适合新手入门学习。
mybatis CRUD mybatis CRUD mybatis CRUD mybatis CRUD mybatis CRUD
05实现mybatis简单crud功能demo05实现mybatis简单crud功能demo05实现mybatis简单crud功能demo05实现mybatis简单crud功能demo05实现mybatis简单crud功能demo05实现mybatis简单crud功能demo05实现mybatis简单crud功能...
ibatis mybatis crud 完整代码
MyBatis - CRUD + 多表联合查询 一个简单的demo
实现了mybatis的增删查改,用的是mysql数据库,本人亲自测试过,基本上导入项目,加载tomcat库即可用了
单纯使用Mybatis框架对数据库CRUD 增删改查操作,支持Junit测试
mybatis-plus-sample-crud: 完整 CRUD 示例 mybatis-plus-sample-wrapper: 条件构造器示例 mybatis-plus-sample-pagination: 分页功能示例 mybatis-plus-sample-active-record: ActiveRecord示例 mybatis-plus-...
NULL 博文链接:https://zhaoshijie.iteye.com/blog/2003209
第一个mybatis程序——CRUD,第一个mybatis程序——CRUD,
班级的crud,学生的crud,班级可以添加学生,根据学生可以查找到所在的班级; 使用框架技术: springboot+springdata(springdata不熟悉可以使用mybatis) 项目搭建: maven 目的: 尽快熟悉springboot及springdata或者...