草庐IT

Mybatis实现简单的CRUD(增删改查)原理及实例分析笔记【全】

靠谱杨 2023-03-28 原文

Mybatis实现简单的CRUD(增删改查)

用到的数据库:

CREATE DATABASE `mybatis`;
USE `mybatis`;
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` int(20) NOT NULL,
  `name` varchar(30) DEFAULT NULL,
  `pwd` varchar(30) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert  into `user`(`id`,`name`,`pwd`) values (1,'靠谱杨','123456'),(2,'张三','abcdef'),(3,'李四','987654');

使用之前要在Maven中导入Mybatis依赖包

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.2</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.47</version>
</dependency>

官方的MyBatis核心配置文件mybatis-config.xml

<?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/mybatis?	
                	useSSL=false&amp;useUnicode=true&amp;characterEncoding=utf8"/>
                <property name="username" value="root"/>
                <property name="password" value="000429"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="com/kuang/dao/userMapper.xml"/>
    </mappers>
</configuration>

注意

****

这里很有可能会报错,需要解决Maven静态资源过滤问题,Maven有习惯大于配置原则

在pom.xml文件中加入以下代码:

    <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
        </resources>
    </build>

注意配置完之后刷新maven!


简单数据类型User.java:

package com.kuang.pojo;
public class User {
	private int id;  //id
	private String name;   //姓名
	private String pwd;   //密码
	//构造,有参,无参
	//set/get
	//toString()

	@Override
	public String toString() {
		return "User{" +
				"id=" + id +
				", name='" + name + '\'' +
				", pwd='" + pwd + '\'' +
				'}';
	}

	public User(){}
	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public User(int id, String name, String pwd) {

		this.id = id;
		this.name = name;
		this.pwd = pwd;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getPwd() {
		return pwd;
	}

	public void setPwd(String pwd) {
		this.pwd = pwd;
	}
}

数据接口层UserMapper.java:

public interface UserMapper {
	//查询全部用户
	List<User> getUserList();
	//根据ID查询用户
	User getUserByID(int id);
	//insert一个用户
	int addUser(User user);
	//update一个用户
	int updateUser(User user);
	//delete一个用户
	int deleteUser(User user);
}

用户定义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.kuang.dao.UserMapper">
    
    <select id="getUserList" resultType="com.kuang.pojo.User">
    select * from user
    </select>
    
    <select id="getUserByID" resultType="com.kuang.pojo.User" parameterType="int">
    select * from user WHERE id = #{id}
    </select>
    
    <!--对象中的属性可以直接取出来 -->
    <insert id="addUser" parameterType="com.kuang.pojo.User">
        insert into mybatis.user (id,name,pwd) values (#{id},#{name},#{pwd});
    </insert>

    <update id="updateUser" parameterType="com.kuang.pojo.User">
        update mybatis.user set name = #{name} , pwd=#{pwd} where id = #{id} ;
    </update>
    
    <delete id="deleteUser" parameterType="com.kuang.pojo.User" >
        delete from mybatis.user where id = #{id}
    </delete>
</mapper>

这里我们可以发现:数据接口是和xml对应的,xml文件实例了这个接口和里面的方法,namespace就是这个接口的名字,里面的select标签对应这个接口里的一个方法,id就是方法名,resultType对应这个方法的返回值类型。

xml文件namespace的包名要和Dao/Mapper接口类名保持一致!

  • id(getUserList):就是对应的namespace中的方法名( List getUserList(); )
  • resultType:是SQL语句执行后的返回值!(Class、基本数据类型)
  • parameterType:参数类型!
  • delete from mybatis.user where id = #{id} 分析这个sql语句,赋值方式和JDBC有所不同,使用这样的格式#{ } 里面的参数是这个方法参数User对象里的成员属性 id 可以直接放到这里用!

配置工具类(MybatisUtils.java)获取连接对象:

package com.kuang.utils;

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 MybatisUtils {
	//从SqlSessionFactory中获得SqlSession的实例,SqlSession完全包含了SQL命令的执行方法
	private static SqlSessionFactory sqlSessionFactory;
	static {
		try {
			String resource = "mybatis-config.xml";
			InputStream inputStream = Resources.getResourceAsStream(resource);
            //读取配置文件获取连接
			sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	//返回获取的SqlSession连接
	public static SqlSession getSession(){
		return sqlSessionFactory.openSession();
	}
}

分析一下这个工具类:

首先这个SqlSessionFactory类是一个工厂类,这个工厂可以产生传统JDBC方法中获得的PreparedStatement对象。也就是这个工具类要完成和JDBCutils同样的任务,首先获取和数据库的连接,那么第一步也就是读取用户配置的mybatis-config.xml文件,可以得到一个数据库连接对象,之后用这个对象去获得一个类似于PreparedStatement对象的SqlSession类的对象。


下面给出具体的调用方法(UserDaoTest.java):

import com.kuang.dao.UserMapper;
import com.kuang.pojo.User;
import com.kuang.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.List;
public class UserDaoTest {
	@Test
	public void test(){
		//sqlSession对象相当于是一个JDBC的PreparedStatement对象,这个对象可以执行sql语句
		//我们现在做的事情就是:获取数据库连接,得到sqlSession对象,通过这个对象去实现我们定义的数据操作接口
		//UserMapper,这个接口再通过解析我们定义的userMapper.xml文件去执行带有SQL语句的特定方法。
		SqlSession sqlSession = MybatisUtils.getSession();
		UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//		List<User> userList = mapper.getUserList();
//		for (User user : userList)
//		{
//			System.out.println(user);
//		}
		//根据ID取
		/*User user=mapper.getUserByID(1);
		System.out.println(user);
		sqlSession.close();*/
		//更新一条数据 id为1
//		updateUser();
		//删除一个用户
		deleteUser();
	}
	public void addUser(){
		SqlSession sqlSession = MybatisUtils.getSession();
		UserMapper mapper = sqlSession.getMapper(UserMapper.class);
		//插入一条数据
		User user = new User(4, "名字", "密码");
		int res = mapper.addUser(user);
		if (res>0){
			System.out.println("插入成功!");
		}
		//提交事务
		sqlSession.commit();
		sqlSession.close();
	}
	public void updateUser(){
		//获得连接coon和执行sql语句的对象 类似JDBC的PreparedStatement
		SqlSession sqlSession = MybatisUtils.getSession();
		//实现UserMapper接口 通过反射机制
		UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
		User user = new User(1, "修改后的名字", "resetpass01");
		userMapper.updateUser(user);
		sqlSession.commit();
		sqlSession.close();
	}

	public void deleteUser(){
		//获取连接
		SqlSession sqlSession = MybatisUtils.getSession();
		//实现接口
		UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
		//实现接口后的mapper调用自己的方法执行sql语句
		userMapper.deleteUser(new User(1,"sss","123"));
		sqlSession.commit();
		sqlSession.close();
	}
}

分析一下这两行代码:

	SqlSession sqlSession = MybatisUtils.getSession();
	UserMapper mapper = sqlSession.getMapper(UserMapper.class);
  • 第一行代码,通过MybatisUtils类的getSession方法获得一个sqlSession对象,这个对象是一个已经连接了数据库的可以执行sql语句的对象(类似JDBC的PreparedStatement对象)
  • 这样还不够,这只是停留在工具类层面,下面要做的一件事情就是让这个工具类去实现用户自定义的数据层接口,从而可以根据用户定义的数据操作方法去执行相应的sql语句,进而得到相应的结果集。

有关Mybatis实现简单的CRUD(增删改查)原理及实例分析笔记【全】的更多相关文章

  1. ruby-on-rails - 如何使用 instance_variable_set 正确设置实例变量? - 2

    我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击

  2. ruby 正则表达式 - 如何替换字符串中匹配项的第 n 个实例 - 2

    在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如5到15之间)的子字符串,并将该实例替换为另一个字符串“X”。我的测试字符串s="1foo100bar10gee1"我的初始模式是1个或多个数字的任何字符串,例如,re=Regexp.new(/\d+/)matches=s.scan(re)给出["1","100","10","1"]如果我想用“X”替换第N个匹配项,并且只替换第N个匹配项,我该怎么做?例如,如果我想替换第三个匹配项“10”(匹配项[2]),我不能只说s[matches[2]]="X"因为它做了两次替换“1fooX0barXg

  3. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  4. ruby - 简单获取法拉第超时 - 2

    有没有办法在这个简单的get方法中添加超时选项?我正在使用法拉第3.3。Faraday.get(url)四处寻找,我只能先发起连接后应用超时选项,然后应用超时选项。或者有什么简单的方法?这就是我现在正在做的:conn=Faraday.newresponse=conn.getdo|req|req.urlurlreq.options.timeout=2#2secondsend 最佳答案 试试这个:conn=Faraday.newdo|conn|conn.options.timeout=20endresponse=conn.get(url

  5. ruby-on-rails - Rails - 从另一个模型中创建一个模型的实例 - 2

    我有一个正在构建的应用程序,我需要一个模型来创建另一个模型的实例。我希望每辆车都有4个轮胎。汽车模型classCar轮胎模型classTire但是,在make_tires内部有一个错误,如果我为Tire尝试它,则没有用于创建或新建的activerecord方法。当我检查轮胎时,它没有这些方法。我该如何补救?错误是这样的:未定义的方法'create'forActiveRecord::AttributeMethods::Serialization::Tire::Module我测试了两个环境:测试和开发,它们都因相同的错误而失败。 最佳答案

  6. ruby-on-rails - RSpec:避免使用允许接收的任何实例 - 2

    我正在处理旧代码的一部分。beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)endRubocop错误如下:Avoidstubbingusing'allow_any_instance_of'我读到了RuboCop::RSpec:AnyInstance我试着像下面那样改变它。由此beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)end对此:let(:sport_

  7. ruby - 用 Ruby 编写一个简单的网络服务器 - 2

    我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b

  8. ruby-on-rails - 简单的 Ruby on Rails 问题——如何将评论附加到用户和文章? - 2

    我意识到这可能是一个非常基本的问题,但我现在已经花了几天时间回过头来解决这个问题,但出于某种原因,Google就是没有帮助我。(我认为部分问题在于我是一个初学者,我不知道该问什么......)我也看过O'Reilly的RubyCookbook和RailsAPI,但我仍然停留在这个问题上.我找到了一些关于多态关系的信息,但它似乎不是我需要的(尽管如果我错了请告诉我)。我正在尝试调整MichaelHartl'stutorial创建一个包含用户、文章和评论的博客应用程序(不使用脚手架)。我希望评论既属于用户又属于文章。我的主要问题是:我不知道如何将当前文章的ID放入评论Controller。

  9. ruby-on-rails - 使用 ruby​​ 将多个实例变量转换为散列的更好方法? - 2

    我收到格式为的回复#我需要将其转换为哈希值(针对活跃商家)。目前我正在遍历变量并执行此操作:response.instance_variables.eachdo|r|my_hash.merge!(r.to_s.delete("@").intern=>response.instance_eval(r.to_s.delete("@")))end这有效,它将生成{:first="charlie",:last=>"kelly"},但它似乎有点hacky和不稳定。有更好的方法吗?编辑:我刚刚意识到我可以使用instance_variable_get作为该等式的第二部分,但这仍然是主要问题。

  10. ruby - 使用 Ruby 通过 Outlook 发送消息的最简单方法是什么? - 2

    我的工作要求我为某些测试自动生成电子邮件。我一直在四处寻找,但未能找到可以快速实现的合理解决方案。它需要在outlook而不是其他邮件服务器中,因为我们有一些奇怪的身份验证规则,我们需要保存草稿而不是仅仅发送邮件的选项。显然win32ole可以做到这一点,但我找不到任何相当简单的例子。 最佳答案 假设存储了Outlook凭据并且您设置为自动登录到Outlook,WIN32OLE可以很好地完成此操作:require'win32ole'outlook=WIN32OLE.new('Outlook.Application')message=

随机推荐