`
yuanleilei628
  • 浏览: 12801 次
  • 性别: Icon_minigender_1
  • 来自: 河南安阳
社区版块
存档分类
最新评论

mybatis系列二:单表CRUD

 
阅读更多

单表的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的数据,这时候可能会出错。

        单元测试是为了测试我们的功能片断是否正常,每个分支是否覆盖到,一些代码的边界是否存在的问题等等,这里不纠结它了,后面我们再研究。

 

  • 大小: 18.5 KB
  • 大小: 17.1 KB
  • 大小: 19.7 KB
  • 大小: 19.4 KB
  • 大小: 30.8 KB
分享到:
评论

相关推荐

    精通MyBatis-Plus:高效单表查询与复杂联表查询实战指南

    本资源《精通MyBatis-Plus:高效单表查询与复杂联表查询实战指南》是一份详尽而实用的技术文档,专为希望深入掌握MyBatis-Plus框架在数据库操作领域应用的开发者设计。MyBatis-Plus作为MyBatis的增强工具,不仅继承...

    MyBatis-Flex: 一个优雅的 MyBatis 增强框架

    只增强,MyBatis-Flex 支持 CRUD、分页查询、多表查询、批量操作,但不丢失 MyBatis 原有的任何功能。高性能,MyBatis-Flex 采用独特的技术架构、相比许多同类框架,MyBatis-Flex 的在增删改查等方面的性能均超越其 ...

    MyBatisCRUD:MyBatis的CRUD操作

    MyBatis CRUD操作Java,MyBatis,单元测试,MySql,Maven的CRUD操作这包含构建和运行MyBatisCRUD应用程序所需的一组指令。建设项目。先决条件设置了JDK 1.6.x或更高版本的Maven 2或更高版本的java_home和m2_home。...

    mybatis 增强工具包,简化 CRUD 操作

    mybatis 增强工具包,简化 CRUD 操作。Mybatis-Plus 在 Mybatis 的基础上进行扩展,只做...内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求。

    基于Java和Mybatis的便捷单表CRUD设计源码

    本项目为Java和Mybatis环境下设计的单表CRUD便捷源码,包含485个文件,其中Java源文件383个,XML配置文件51个,SQL文件22个,Markdown文件11个,YAML文件5个,FreeMarker模板4个,属性文件2个,Git忽略文件1个,Git...

    MyBatis 采用注解方式实现CRUD

    然而,随着Java注解的普及,MyBatis也引入了注解方式来简化配置,让CRUD(创建、读取、更新、删除)操作更加便捷。下面我们将详细介绍如何使用注解实现MyBatis的CRUD。 1. **注解简介** MyBatis 的注解主要包括 `@...

    [] - 2023-11-18 自己动手写一款 IDEA Mybatis 插件:大大提高 CRUD 效率.pdf

    互联网资讯,技术简介,IT、AI技术,人工智能互联网资讯,技术简介,IT、AI技术,人工智能互联网资讯,技术简介,IT、AI技术,人工智能互联网资讯,技术简介,IT、AI技术,人工智能互联网资讯,技术简介,IT、AI技术...

    Spring boot整合Mybatis实现级联一对多CRUD操作的完整步骤

    在本文中,我们将深入探讨如何使用Spring Boot整合Mybatis实现级联一对多的CRUD(创建、读取、更新、删除)操作。首先,我们需要理解什么是级联操作和一对多的关系。在关系型数据库中,级联操作涉及到一个表中的记录...

    mybatis-mapper:mybatis单表通用CURD插件和分页插件

    发现一些通用的操作,比如单表的CURD,在每一个xml文件中都需要定义一遍。而且每个人写的风格又不统一。于是寻找了一个解决 办法,使用maven插件mybatis-generator。使用一段时间之后,发现还是不能令人满意。每次...

    mybatis+jdbc的jar包

    MyBatis是一个优秀的持久层框架,它支持定制化SQL、存储过程以及高级映射。MyBatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果集。MyBatis可以使用简单的XML或注解进行配置和原始映射,将接口和Java的POJOs...

    mybatis的增删改查CRUD

    本项目实现了基于MyBatis的CRUD操作,即创建(Create)、读取(Read)、更新(Update)和删除(Delete),并以MySQL作为数据存储引擎。以下将详细介绍如何在MyBatis中进行这些操作。 1. 创建(Create) 创建操作...

    mybatis学习总结:annotation与xml结合示例

    它提供了灵活的SQL映射机制,使得Java对象和数据库表之间的映射变得简单易行。本篇文章将聚焦于MyBatis中的注解(Annotation)与XML配置的结合使用,旨在帮助开发者更深入地理解这一关键特性。 首先,MyBatis允许...

    Mybatis通用DAO设计封装(mybatis)

    利用Mybatis的代码生成器,可以根据数据库表自动生成对应的Mapper接口、Mapper XML文件以及实体类,进一步减少手动编写的工作量。 8. **依赖注入**: 使用Spring框架进行依赖注入,将DAO实例注入到Service层,...

    从Servlet+JSP+JDBC到MyBatis:重构用户CRUD操作的高效之旅第二版

    修改了删除确认的操作

    外卖点餐系统,后端:springboot+mybatis+mybatis-plus 前端:vue+elmen

    MyBatis提供了简单易用的API,可以将复杂的数据库操作封装成简单的CRUD操作。 MyBatis-Plus是MyBatis的增强版,提供了更多的便捷方法和性能优化。它可以自动生成SQL语句,提高了开发效率。 前端开发框架 前端使用...

    从Servlet+JSP+JDBC到MyBatis:重构用户CRUD操作的高效之旅

    源代码,解压导入本地,主要数据库相关配置

    SpringBoot+MybatisCRUD 整合案例

    这个"SpringBoot+MybatisCRUD 整合案例"是为初学者设计的,旨在帮助他们快速掌握这两个流行的框架的结合使用。 首先,我们需要在项目中引入Spring Boot和MyBatis的依赖。在`pom.xml`文件中,我们需要添加以下Maven...

    mybatis中使用接口编程方式实现CRUD模板

    本文将深入探讨如何在MyBatis中利用接口实现CRUD(创建、读取、更新、删除)模板。 首先,让我们了解MyBatis的核心概念。MyBatis是一个优秀的持久层框架,它允许开发者通过SQL映射文件或者注解来定义SQL语句,避免...

    mybatis in practice 源代码

    5. **DAO层**:DAO接口和实现类负责与数据库的交互,通常会使用MyBatis的SqlSession进行 CRUD(创建、读取、更新、删除)操作。 6. **示例应用**:可能包含一个简单的Web应用程序,演示如何在实际项目中集成MyBatis...

Global site tag (gtag.js) - Google Analytics