MyBatis学习笔记(一)——MyBatis介绍及 利用代理实现增删改查基本操作

一、MyBatis介绍

MyBatis 本来是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis,实质上Mybatis对ibatis进行一些改进。 目前mybatis在github上托管。

在传统的jdbc编程中,我们可以注意到像注册驱动、创建connection、创建statement、手动设置参数、结果集检索等这些操作都是我们手动实现的,可以说代码很多很繁杂。而且,在jdbc中 sql语句是硬编码,如果需求变更了就需要修改java中的代码,然后重新编译,非常不利于维护。然而,MyBatis框架就可以帮我们解决这一些列问题。

MyBatis 是一个优秀的持久层框架,它对JDBC的操作数据库过程进行封装,是开发者只要专注于SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。MyBatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。

二、MyBatis基本查询操作

准备工作:1. 创建测试项目   2. 导入两个jar包: mybatis-3.4.6.jar  和mysql-connection-java-8.0.11.jar

2.1  数据库建表(我这里建了一个订单表——orders

先插入两条记录:

2.2 创建orders表的实体类——Order

import java.util.Date;
import java.util.List;

public class Order {
	protected Integer id;
	protected Integer user_id;
	protected Integer number;
	protected Date createtime;
	protected String note;
	
	
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public Integer getUser_id() {
		return user_id;
	}
	public void setUser_id(Integer user_id) {
		this.user_id = user_id;
	}
	public Integer getNumber() {
		return number;
	}
	public void setNumber(Integer number) {
		this.number = number;
	}
	public Date getCreatetime() {
		return createtime;
	}
	public void setCreatetime(Date createtime) {
		this.createtime = createtime;
	}
	public String getNote() {
		return note;
	}
	public void setNote(String note) {
		this.note = note;
	}
	
	
	@Override
	public String toString(){
			return "domain.order{" +"id="+id
					+",userId="+user_id+",number="+number+",createtime="+createtime+",note="+note+"}";
		
	}

}

2.3 配置 配置xml文件 :SqlMapConfig.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>
	<!-- 和Spring整合后 environments配置将废除 -->
	<environments default="development">
		<environment id="development">
		<!-- 使用jdbc事务管理 -->
		<transactionManager type="JDBC"></transactionManager>
		 	<!-- 数据连接池 -->
			<dataSource type="POOLED">
				<property name="driver" value="com.mysql.cj.jdbc.Driver"></property>
				<property name="url" value="jdbc:mysql://localhost:3306/first_mybatis?useSSL=false&amp;useUnicode=true&amp;characterEncoding=utf8"></property>
				<property name="username" value="root"></property>
				<property name="password" value="yooneiweiyoonei."></property>
				</dataSource>
		</environment>
	</environments>
	
</configuration>

2.4 配置 Mapper xml 文件 :OrderMaper.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.xml文件中配置很多的sql语句,执行每个sql语句时,分装为MapperStatement对象 mapper.xml以statement为单位管理sql语句 -->
<!-- mapper标签中 namespace参数值为之后我们要创建的代理接口类的全限定名 -->
<mapper namespace="mapper.OrderMapper">

	<!-- 根据id查询订单信息 -->
	<!-- 
	 id:唯一标识 一个statement 这里对应我们之后要创建代理接口类中的方法名
	 #{}:表示 一个占位符,如果#{}中传入的是简单类型的参数,#{}中的名称可以随意取
	 parameterType:输入 参数的类型,通过#{}接收parameterType输入的参数 这里对应我们之后要创建的代理接口类对应方法中的参数类型
	 resultType:输出结果类型,不管返回多条还是单调,指定单挑记录映射的pojo类型(plain old java object 普通java对象)。这里对应我们以后要创建代理接口类对应方法的返回值类型。 
        --> 
	<select id="findOrderById" parameterType="int" resultType="domain.Order" >
		select * from orders where id=#{id}
	</select>
</mapper>

列表结构:

注意将OrderMapper.java 和OrderMapper.xml文件 放在一个包下。

2.5  在SqlMapConfig文件中注册OrderMapper.xml文件

在SqlMapConfig.xml中添加一个<mappers></mappers>字段,并在里面传入OrderMapper.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>
	<!-- 和Spring整合后 environments配置将废除 -->
	<environments default="development">
		<environment id="development">
		<!-- 使用jdbc事务管理 -->
		<transactionManager type="JDBC"></transactionManager>
		 	<!-- 数据连接池 -->
			<dataSource type="POOLED">
				<property name="driver" value="com.mysql.cj.jdbc.Driver"></property>
				<property name="url" value="jdbc:mysql://localhost:3306/first_mybatis?useSSL=false&amp;useUnicode=true&amp;characterEncoding=utf8"></property>
				<property name="username" value="root"></property>
				<property name="password" value="yooneiweiyoonei."></property>
				</dataSource>
		</environment>
	</environments>
	<mappers>
	<mapper resource="mapper/OrderMapper.xml"></mapper>
	</mappers>
	
</configuration>

2.6 写Mapper.java的代理接口类

package mapper;

import domain.Order;

public interface OrderMapper {

	public Order findOrderById(int id) throws Exception;
	
}

2.7 写dao层

package dao;

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;

import domain.Order;
import mapper.OrderMapper;

public class Dao {
	private SqlSessionFactory sqlSessionFactory;
	
  //初始化方法,创建sqlSessionFactory工厂对象用于之后的SqlSession的创建
	public void init() throws IOException{
		String resource="SqlMapConfig.xml";
		InputStream inputStream=Resources.getResourceAsStream(resource);
		sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
	}
	
	public String findOrderById(int id) throws Exception {
		SqlSession sqlSession=sqlSessionFactory.openSession();//创建会话
		OrderMapper orderMapper=sqlSession.getMapper(OrderMapper.class);//获取代理类对象
		Order result=orderMapper.findOrderById(id);//调用代理类方法
                sqlSession.close();//关闭会话
		return result.toString();
	}
	
	}

2.8 写测试类

package Demo;

import dao.Dao;

public class Demo1 {
	public static void main(String[] args) throws Exception {
		
		Dao dao=new Dao();
		dao.init();//初始化
		
		String result=dao.findOrderById(1);
		System.out.println(result);		
  		
	}

}

控制台显示结果

当我们使用模糊查询的时候,传入参数的地方不再使用#{}而是要使用${},如下:

	<select id="findOrderLike" parameterType="java.lang.String" resultType="domain.Order">
		select * from orders where note like '%${value}%'
		</select>

#{}和${}的区别:

  • #{}:1.表示一个占位符,向占位符输入参数,mybatis自动进行java类型和jdbc类型的转换。2.程序员不需要考虑参数的类型,比如:传入字符串,mybatis最终拼接好的sql就是参数两边加单引号。3.#{}接收pojo(Plain Old Java Object Java数据对象)数据,可以使用OGNL(就是el表达式)解析出pojo的属性值。
  • ${}:1.表示sql的拼接,通过${}接收参数,将参数的内容不加任何修饰拼接在sql中。2.${}也可以接收pojo数据,可以使用OGNL解析出pojo的属性值。3.缺点:不能防止sql注入。

三、Mybatis基本增删改操作

3.1.使用Mybatis向表中插入记录:

1.在OrderMapper.xml添加如下字段:

<!-- 添加用户 -->
	<!--
	parameterType:输入参数的类型 ,这里输入参数为Order对象 包括了Order的id,user_id,number,createtime,note;
	#{}接受pojo数据,可以通过OGNL解析出pojo的属性值
	#{id},#{user_id},#{number},#{createtime},#{note} 表示从parameterType中取出的pojo的属性值
	 -->
	<insert id="insertOrder" parameterType="domain.Order">
		insert into orders values(#{id},#{user_id},#{number},#{createtime},#{note})
	</insert>

2.在OrdeMapper.java 接口中添加insertOrder(Order order)方法

package mapper;

import domain.Order;

public interface OrderMapper {

	public Order findOrderById(int id) throws Exception;
	public void insertOrder(Order order) throws Exception;
}

3.在Dao中添加insertOrder(Order order) 方法

package dao;

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;

import domain.Order;
import mapper.OrderMapper;

public class Dao {
	private SqlSessionFactory sqlSessionFactory;
	
//	初始化方法,创建sqlSessionFactory工厂对象用于之后的SqlSession的创建
	public void init() throws IOException{
		String resource="SqlMapConfig.xml";
		InputStream inputStream=Resources.getResourceAsStream(resource);
		sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
	}
	
	public String findOrderById(int id) throws Exception {
		SqlSession sqlSession=sqlSessionFactory.openSession();//创建会话
		OrderMapper orderMapper=sqlSession.getMapper(OrderMapper.class);//获取代理类对象
		Order result=orderMapper.findOrderById(id);//调用代理类方法
		sqlSession.close();
		return result.toString();
		
	}
		public void insertOrder(Order order) throws Exception{
		SqlSession sqlSession=sqlSessionFactory.openSession();
		OrderMapper orderMapper=sqlSession.getMapper(OrderMapper.class);
		orderMapper.insertOrder(order);
		sqlSession.commit();//增,删,改 这类更新数据库操作都需要用commit()方法提交会话
		sqlSession.close();//关闭会话
	}
		}

4.编写测试类:

package Demo;

import java.util.Date;

import dao.Dao;
import domain.Order;

public class Demo1 {

	public static void main(String[] args) throws Exception {
		
		Dao dao=new Dao();
		
		dao.init();//初始化
		
//		String result=dao.findOrderById(1);
//		System.out.println(result);
//		

		Order order=new Order();
		order.setId(3);
		order.setUser_id(3);
		order.setNumber(6);
		order.setCreatetime(new Date());
		order.setNote("aha mybatis");
		dao.insertOrder(order);
		System.out.print("insert success!");
	}

}

此时查看控制台和数据库,发现数据已经被插入,结果如下:

控制台:

数据库:

扩展:主键返回

现在,我们还是利用测试类在数据库orders表中插入一条记录,不同的是 我们现在不给Order对象的id属性设置值,如下:

package Demo;

import java.util.Date;

import dao.Dao;
import domain.Order;

public class Demo1 {

	public static void main(String[] args) throws Exception {
		
		Dao dao=new Dao();
		
		dao.init();//初始化
		
//		String result=dao.findOrderById(1);
//		System.out.println(result);

		Order order=new Order();
		order.setUser_id(4);
		order.setNumber(8);
		order.setCreatetime(new Date());
		order.setNote("oh mybatis");
		dao.insertOrder(order);
		System.out.print("insert success!");
	}

}

因为我们在数据库建orders表时定义了id字段为自增长的主键,所以在数据库中orders的id字段是有值的,如下:

但当我们在测试类中尝试输出Order对象的id时会输出id=0。那么,当我们想输出改对象在记录中的id时,该怎么做呢?只需要在OrderMapper.xml文件中的<insert></insert>标签中添加<selectKey>标签就可以了。如下:

<insert id="insertOrder" parameterType="domain.Order">
		<!-- keyProperty:将主键值设置到哪个属性
		resultType: select LAST_INSERT_ID()的结果 类型
		order:属性值AFTER表示该字段在执行insert语句后才执行
		另外 我们需要借助LAST_INSERT_ID()函数 -->
		<selectKey keyProperty="id" order="AFTER" resultType="int">
		select LAST_INSERT_ID()
		</selectKey>
		insert into orders values(#{id},#{user_id},#{number},#{createtime},#{note})
	</insert>

此时,我们在测试类中就可以输出改Order对象插入在表中的记录id值了。

这里我们由于在建表时设置了id字段为自增长,采用自增长的形式生成主键,所以我们在传入User对象的id属性时可以将该属性设置为null。那么当我们使用uuid生成主键时又该怎么做呢?

只需要在OrderMapper.xml中添加如下字段:

<!-- keyProperty:将主键值设置到哪个属性
		resultType: select LAST_INSERT_ID()的结果 类型
		order:属性值“AFTER” 表示该字段在执行insert语句后才执行,属性值“BEFORE” 表示在执行插入时,会先调用uuid()函数得到主键,然后将主键设置到Order对象中,再插入到数据库。
		另外 我们需要借助LAST_INSERT_ID()函数 -->
		<selectKey keyProperty="id" order="BEFORE" resultType="java.lang.String">
		select uuid()
		</selectKey>
		insert into orders values(#{id},#{user_id},#{number},#{createtime},#{note})

但是需要注意的是,我们在数据库和映射对象中定义了id字段为int类型,如果要用uuid()生成的String类型值作为id字段的属性值,我们还需要修改orders表和Order对象的类型为String,否侧编译器会抛出异常。

3.2.使用Mybatis实现更行表中数据

1.在OrderMapper.xml 文件中添加如下字段:

    <update id="updateOrder" parameterType="domain.Order">
		update orders set user_id=#{user_id},number=#{number},createtime=#{createtime},note=#{note} where id=#{id}
    </update>

2.在OrderMapper.java 接口中添加对应方法:

public void updateOrder(Order order) throws Exception;

3.在Dao层中添加对应方法:

public void updateOrder(Order order) throws Exception{
		SqlSession sqlSession=sqlSessionFactory.openSession();
		OrderMapper orderMapper=sqlSession.getMapper(OrderMapper.class);
		orderMapper.updateOrder(order);
		sqlSession.commit();
		sqlSession.close();
	}

4.编写测试类:

package Demo;

import java.util.Date;

import dao.Dao;
import domain.Order;

public class Demo1 {

	public static void main(String[] args) throws Exception {
		
		Dao dao=new Dao();
		
		dao.init();//初始化
		
//		String result=dao.findOrderById(1);
//		System.out.println(result);
	
//		Order order=new Order();
                order.setId(5)
//		order.setUser_id(4);
//		order.setNumber(8);
//		order.setCreatetime(new Date());
//		order.setNote("ohye mybatis");
//		dao.insertOrder(order);
//		System.out.print("insert success!");
		
		Order order1=new Order();
		order1.setId(5);
		order1.setUser_id(4);
		order1.setNumber(8);
		order1.setCreatetime(new Date());
		order1.setNote("this is a update Order");
		dao.updateOrder(order1);
		System.out.print("update success!");
	}
}

控制台输出结果:

数据库更新前和更新后结果:

3.3 使用Mybatis 实现删除表中数据

基本和以上操作差不多

1.在Order.xml文件中添加如下字段:

    <delete id="deleteOrderById" parameterType="int">
		delete from orders where id=#{id}
    </delete>

2.在Order.java接口中添加对应方法:

public void deleteOrderById(int id) throws Exception;

3.在Dao层添加对应方法:

public void deleteOrderById(int id) throws Exception{
		SqlSession sqlSession=sqlSessionFactory.openSession();
		OrderMapper orderMapper=sqlSession.getMapper(OrderMapper.class);
		orderMapper.deleteOrderById(id);
		sqlSession.commit();
		sqlSession.close();
	}

4.测试类中编写对应代码:

package Demo;

import java.util.Date;

import dao.Dao;
import domain.Order;

public class Demo1 {

	public static void main(String[] args) throws Exception {
		
		Dao dao=new Dao();
		
		dao.init();//初始化
		
//		String result=dao.findOrderById(1);
//		System.out.println(result);

//		Order order=new Order();
//		order.setUser_id(4);
//		order.setNumber(8);
//		order.setCreatetime(new Date());
//		order.setNote("oh mybatis");
//		dao.insertOrder(order);
//		System.out.print("insert success!");
		
//		Order order1=new Order();
//		order1.setId(5);
//		order1.setUser_id(4);
//		order1.setNumber(8);
//		order1.setCreatetime(new Date());
//		order1.setNote("this is a update Order");
//		dao.updateOrder(order1);
//		System.out.print("update success!");
//		
		dao.deleteOrderById(5);
		System.out.print("delete success");
	}

}

查看数据库,发现对应id=5的记录已被删除

四、Mybatis利用代理开发流程小结

  1. 数据库建表
  2. 创建数据库中对应表的映射实体类
  3. 编写 SqlMapConfig.xml 配置文件
  4. 编写 mapper.xml
  5. 把mapper.xml文件注册到SqlMapConfig.xml配置文件中
  6. 编写mapper代理接口,添加对应statement方法
  7. 写Dao层对应操作方法

   在Dao层中:

  1. 编程通过配置文件创造SqlSessionFactory
  2. 通过SqlSessionFactory获取SqlSession对象
  3. 通过SqlSession对象获取代理类对象
  4. 通过代理类操作数据库(如果执行添加、更新、删除需要调用SqlSession.commit())
  5. SqlSesion使用完成要关闭

猜你喜欢

转载自blog.csdn.net/weixin_41072833/article/details/81161954