MyBatis的命名空间方式的增删改查操作(二)

本文详细介绍了MyBatis这一优秀持久层框架,重点阐述其单表的CRUD操作。包括根据id查询单个对象、查询全部记录等查询语句,普通插入、插入时获取id等插入语句,全部修改、部分修改等修改语句,以及删除语句,还提及了操作中的注意点。

沉迷于黑与白世界中的人,无论怎么挣扎,都逃不过被同化的命运。前世看见了什么,那么今世便是什么。

上一章简单介绍了MyBatis的简单了解(一),如果没有看过,请观看上一章

一. Mybatis 的官方介绍

MyBatis 是支持普通 SQL 查询,存储过程和高级映射的优秀持久层框架。MyBatis 消除 了几乎所有的 JDBC 代码和参数的手工设置以及对结果集的检索。MyBatis 可以使用简单的 XML 或注解用于配置和原始映射,将接口和 Java 的 POJO(Plain Old Java Objects,普通的 Java 对象)映射成数据库中的记录。

现在都是用Mapper 的形式来进行数据库的持久化操作,但是以前的ibatis 形式的 命名空间方式的CRUD ,也需要进行了解。 下面,就进行详细的分析。

二. 查询语句 select

二.一 根据id 查询单个对象

接口:

User getById(int userId);

实现类:

@Override
	public User getById(int userId) {
		SqlSession sqlSession=SqlSessionFactoryUtils.getSession();
		User user=null;
		try{
			user=sqlSession.selectOne("com.yjl.pojo.User.getById",userId);
		}finally{
			sqlSession.close();
		}
		return user;
	}

对应的xml 查询语句:

<select id="getById" parameterType="int" resultType="com.yjl.pojo.User">
		select * from user where id=#{id} 
	</select>

测试方法:

@Test
	public void getByIdTest(){
		UserDao userDao=new UserDaoImpl();
		User user=userDao.getById(1);
		System.out.println(user);
	}

查询对象的时候,如果可以确定 查询的是唯一的对象(包括没有,没有查询出来为null),那么就可以使用selectOne() 来精确的表示出唯一的对象。 后面跟的值, 是名称空间+id的形式, 命名空间来确定是哪一个实体, com.yjl.pojo.User 表示 是User 实体类, getById 表示确定的是getById() 的方法。 其中, id不能重复。

对User.xml 的解释。

namespace 为命名空间,一般是用包名+类名 即全限定名称。 sql 语句的id 一般是方法名,是唯一的,不能重复。 (接口中的方法名可以重载,可以重复,但是id是不能重复的,但一般还是用方法名来写id)。

是查询语句,用的是select parameterType 为参数类型, 是int 型, int 是MyBatis 内置的对象类型, 与Java 中的java.lang.Integer 一致。 Java 类型,MyBatis 类型,数据库类型 ,这三种类型有一种转换的关系。 以后会讲。
resultType 为结果类型, 自定义的类型,要写 全限定名称,如com.yjl.pojo.User, 以后也可以写别名。

其中,#{id} 表示传入的参数 放置到id 里面。 会采用 占位符的方式,转换成
select * from user where id=?, ?传入的参数值为id参数值。

如果传入的值是单个的基本类型值的话,可以用value 来代替。

只能是单个的值,并且是基本类型值。

<select id="getById" parameterType="int" resultType="com.yjl.pojo.User">
		select * from user where id=#{value} 
	</select>

如果传入两个值,如 :

<select id="getById" parameterType="int" resultType="com.yjl.pojo.User">
		select * from user where id=#{value}  and name=#{name}
	</select>

这样是错误的。

二.二 查询全部的记录

接口:

List<User> findAll();

实现类:

@Override
	public List<User> findAll() {
		SqlSession sqlSession=SqlSessionFactoryUtils.getSession();
		List<User> allList=new ArrayList<User>();
		try{
			allList=sqlSession.selectList("com.yjl.pojo.User.findAll");
		}finally{
			sqlSession.close();
		}
		return allList;
	}

对应的xml sql语句

<select id="findAll" resultType="com.yjl.pojo.User">
		select * from user
	</select>

测试方法:

@Test
	public void findAllTest(){
		UserDao userDao=new UserDaoImpl();
		List<User> allList=userDao.findAll();
		allList.forEach(n ->System.out.println(n));
	}

没有传入参数值,那么就不写 参数值, 虽然查询的是一个集合list, 但是返回类型resultType 仍然写 类的全限定名称, MyBatis 会根据调用方法的名称 selectList() 来自动内部构建集合。

注意点:

  1. 在查询的时候,如果查询的是单个对象的话,也是可以用selectList() 的,只是此时查询出来是一个长度的集合。 但是,如果查询的是多个对象的话,是不能用selectOne() 的,会报错。
@Override
	public List<User> findAll() {
		SqlSession sqlSession=SqlSessionFactoryUtils.getSession();
		List<User> allList=new ArrayList<User>();
		User user=sqlSession.selectOne("com.yjl.pojo.User.findAll");
		allList.add(user);
		return allList;
	}

在这里插入图片描述
TooManyResultsException, 太多结果记录异常。

  1. 在查询的时候,除了selectOne(), selectList() 之外,还有其他的查询结果 ,如Map 形式。
    在这里插入图片描述
    以后,会讲其余的用法。

三. 插入语句 insert

三.一 普通插入

接口:

int insert(User user);

实现类 (错误的形式):

@Override
	public int insert(User user) {
		SqlSession sqlSession=SqlSessionFactoryUtils.getSession();
		int result= sqlSession.insert("com.yjl.pojo.User.insertUser", user);
		sqlSession.close();
		return result;
	}

测试方法:

@Test
	public void insertTest(){
		UserDao userDao=new UserDaoImpl();
		User user=new User();
		user.setName("老蝴蝶");
		user.setAge(25);
		user.setSex("男");
		user.setDescription("这是一个老蝴蝶");
		userDao.insert(user);
		System.out.println("输出信息:"+user);
	}

xml实现类:

<insert id="insertUser" parameterType="com.yjl.pojo.User">
		insert into user(name,age,sex,description) values(#{name},#{age},#{sex}
		,#{description})
</insert>

传入的参数是 com.yjl.pojo.User 对象, #{name} 表示从对象参数中取出name 的值, #{sex} 表示从对象参数中取出sex的值。

在这里插入图片描述
在日志中,执行了插入的语句,但是并没有在数据库中找到这一条记录。

在这里插入图片描述
原因是什么, 就是自动提交的问题。 上面把自动提交 改成了false, 那么就需要我们手动提交。
所以,正确的实现方法是:

@Override
	public int insert(User user) {
		SqlSession sqlSession=SqlSessionFactoryUtils.getSession();
		int result= sqlSession.insert("com.yjl.pojo.User.insertUser", user);
		sqlSession.commit();  //手动提交
		sqlSession.close();
		return result;
	}

下面的更新和删除,都要进行手动提交。
这个时候,运行程序:
在这里插入图片描述
而数据库中也存在了这一条数据在这里插入图片描述
插入的编号是4, 3的那一条已经被使用了,刚才错误插入的时候。

三.二 插入时获取id

从输出结果中,发现,数据可以插入到数据库中,但是并没有 查询出相应的id 编号。
应该要将id 编号进行取出。 实际开发中,表关联时,常常获取刚才插入表的 id 主键,来进行 关联表的外键关联值。

<!-- 插入记录 ,获取id编号-->
	<insert id="insertUser" parameterType="com.yjl.pojo.User" keyProperty="id" useGeneratedKeys="true">
		insert into user(name,age,sex,description) values(#{name},#{age},#{sex}
		,#{description})
	</insert>

其中,useGeneratedKeys= true, 表示用主键信息, keyProperty 指定主键 为类属性 为id, 注意,用keyProperty ,不能用keyColumn
此时,运行:
在这里插入图片描述
数据库中也存在这条记录, id为5
在这里插入图片描述

三.三 数据库查询 id

<!-- 数据库查询,获取id编号-->
	<insert id="insertUser" parameterType="com.yjl.pojo.User">
		<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
			select last_insert_id()
		</selectKey>
		insert into user(name,age,sex,description) values(#{name},#{age},#{sex}
		,#{description})
	</insert>

顺序 order, 为AFTER, 在插入之后查询。 必须为全大写 AFTER, after 是错误的。
返回类型 resultType, 表示是 主键的类型,为全限定名称, java.lang.Integer,
last_insert_id () 是MySQL 数据库提供的内置查询 方法,自动返回最后一个INSERT或 UPDATE 问询为 AUTO_INCREMENT列设置的第一个 发生的值。
在这里插入图片描述

三.四 uuid 形式的主键插入

将id 的类型 改成String 类型,
在这里插入图片描述
数据库中id 列的类型也改成varchar 类型。
在这里插入图片描述
长度要设置长一点。
将User.xml 中的其他方法 注释掉。
写测试方法:

@Test
	public void insertUUIDTest(){
		UserDao userDao=new UserDaoImpl();
		User user=new User();
		user.setName("老蝴蝶uuid");
		user.setAge(25);
		user.setSex("男");
		user.setDescription("这是一个老蝴蝶uuid 测试");
		userDao.insert(user);
		System.out.println("输出信息:"+user);
	}

xml sql 语句。

<!-- uuid插入,获取id编号-->
	<insert id="insertUser" parameterType="com.yjl.pojo.User">
		<selectKey keyProperty="id" order="BEFORE" resultType="java.lang.String">
			select uuid()
		</selectKey>
		<!-- 这个时候,sql 语句就要写id 了。 -->
		insert into user(id,name,age,sex,description) values(#{id},#{name},#{age},#{sex}
		,#{description})
	</insert>

其中, 查询时顺序 order 就为BEFORE, 在插入之前进行查询, 不能写before ,必须为大写
uuid 的类型是String
select uuid() ,其中 uuid() 为mysl 提供的内置函数 。
插入的sql 语句,就需要写 id 的值了。

在这里插入图片描述
数据库中展示:
在这里插入图片描述

三.六 序列形式的插入

id 编号 还改成int 类型, 是自动增长, 数据库列id 还改成int 类型 ,自增。注释的sql 解除注释。
跟uuid 之前的操作一样。
没有oracle 客户端,不进行验证了。

<!-- oracle 序列插入,获取id编号-->
	<insert id="insertUser" parameterType="com.yjl.pojo.User">
		<selectKey keyProperty="id" order="BEFORE" resultType="java.lang.Integer">
			select 序列名.nextval() 
		</selectKey>
		<!-- 这个时候,sql 语句就要写id 了。 -->
		insert into user(id,name,age,sex,description) values(#{id},#{name},#{age},#{sex}
		,#{description})
	</insert>

四.修改 update

四.一 全部修改时

接口:

int update(User user);

实现方法:

@Override
	public int update(User user) {
		SqlSession sqlSession=SqlSessionFactoryUtils.getSession();
		int result= sqlSession.update("com.yjl.pojo.User.updateUser",user);
		sqlSession.commit();  //手动提交
		sqlSession.close();
		return result;
	}

测试方法:

@Test
	public void updateTest(){
		UserDao userDao=new UserDaoImpl();
		User user=new User();
		user.setId(1); //编号为1
		user.setName("修改老蝴蝶");
		user.setAge(25);
		user.setSex("男");
		user.setDescription("这是一个修改的老蝴蝶");
		userDao.update(user);
	}

xml 修改语句

<update id="updateUser" parameterType="com.yjl.pojo.User">
		update user set name=#{name},sex=#{sex},age=#{age},description=#{description}
		where id=#{id}
	</update>

运行时:
在这里插入图片描述
数据库:
在这里插入图片描述
确实发生了修改的操作。是正确的。

四.二 部分修改字段时

xml 不变。
测试方法:

@Test
	public void update1Test(){
		UserDao userDao=new UserDaoImpl();
		User user=new User();
		user.setId(1);
		user.setDescription("这是一个老蝴蝶,只修改描述");
		userDao.update(user);
	}

在这里插入图片描述
传入的值为空,
在这里插入图片描述
这样修改的话,#{name} 时取出的值 是默认的String 为null, #{age} 也是默认的Integer, 为null. 表示修改的传入值是null .

四.三 查询时修改

将id =1 的值设置成原先的值
在这里插入图片描述
xml 不变,测试方法为:

@Test
	public void update2Test(){
		UserDao userDao=new UserDaoImpl();
		SqlSession sqlSession=SqlSessionFactoryUtils.getSession();
		User user=sqlSession.selectOne("com.yjl.pojo.User.getById",1);
		user.setDescription("这是一个老蝴蝶,只修改描述");
		userDao.update(user);
	}

在这里插入图片描述
在这里插入图片描述
可以正确的进行修改。

如果一个表中 有几十个字段,而现在只修改 一个描述字段,会将以前所有的字段都进行修改, 很浪费资源的。 希望 可以修改哪一个,就只修改哪一个, 后面的动态sql 语句会学习的。

五. 删除 delete

接口:

int delete(int id);

实现类:

@Override
	public int delete(int id) {
		SqlSession sqlSession=SqlSessionFactoryUtils.getSession();
		int result= sqlSession.delete("com.yjl.pojo.User.deleteById",id);
		sqlSession.commit();  //手动提交
		sqlSession.close();
		return result;
	}

测试方法:

@Test
	public void deleteTest(){
		UserDao userDao=new UserDaoImpl();
		userDao.delete(1);
	}

xml 语句:

	<!-- 删除记录 -->
	<delete id="deleteById" parameterType="int">
		delete from user where id=#{id}
	</delete>

写正常的删除语句。

运行:
在这里插入图片描述
在这里插入图片描述

六. 注意点

这就是原来 ibatis 时的命名空间的 单表基本操作, 当然 ,也有其他的操作形式,这里暂不讲解,会在Mapper 时进行详细的讲解。
另外注意, sql 语句时, 如:

delete from user where id=#{id}

加上; 和不加; 都可以运行, 但不建议加; 号。

谢谢!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

两个蝴蝶飞

你的鼓励,是老蝴蝶更努力写作的

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值