Java EE SSM框架整合开发(六)MyBatis

210 阅读6分钟

前排提醒:关于MyBatis配置文件和映射器详细讲解在这里

基本概念

1.1 ORM框架

ORM(Object/Relational Mapping,即对象关系映射)框架,通过描述Java对象与数据库表之间的映射关系,允许我们通过面向对象的方式操作数据库。 image.png 举个例子,不使用ORM的情况下,使用JAVA查询数据库是这样的

book_list = new List();
sql = "SELECT book FROM library WHERE author = 'Linus'";
data = query(sql); // I over simplify ...
while (row = data.next())
{
     book = new Book();
     book.setAuthor(row.get('author');
     book_list.add(book);
}

使用ORM可以允许你这样写

book_list = BookTable.query(author="Linus");

常见的ORM框架有Hibernate和MyBatis。

其中MyBatis 是一个基于Java的持久层框架,使用简单的 XML或注解用于配置和原始映射,将接口和Java的 POJOs(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录。 这两个框架的主要区别如下。

HibernateMyBatis
全表映射的框架,只需提供POJO和映射关系半自动映射的框架,需要手动匹配POJO、SQL和映射关系
强大、复杂、间接、全自动化的持久层框架小巧、简单、直接、半自动化的持久层框架

1.2 MyBatis工作过程

image.png

  1. 读取MyBatis配置文件:mybatis-config.xml为MyBatis的全局配置文件,配置了MyBatis的运行环境等信息,例如数据库连接信息。

  2. 加载映射文件:映射文件即SQL映射文件,该文件中配置了操作数据库的SQL语句,需要在MyBatis配置文件mybatis-config.xml中加载。mybatis-config.xml文件可以加载多个映射文件,每个文件对应数据库中的一张表。

  3. 构造会话工厂:通过MyBatis的环境等配置信息构建会话工厂SqlSessionFactory。

  4. 创建会话对象:由会话工厂创建SqlSession对象,该对象中包含了执行SQL语句的所有方法。

  5. Executor执行器:MyBatis底层定义了一个Executor接口来操作数据库,它将根据SqlSession传递的参数动态地生成需要执行的SQL语句,同时负责查询缓存的维护。

  6. MappedStatement对象:在Executor接口的执行方法中有一个MappedStatement类型的参数,该参数是对映射信息的封装,用于存储要映射的SQL语句的id、参数等信息。

  7. 输入参数映射:输入参数类型可以是Map、List等集合类型,也可以是基本数据类型和POJO类型。输入参数映射过程类似于JDBC对preparedStatement对象设置参数的过程。

  8. 输出结果映射:输出结果类型可以是Map、List等集合类型,也可以是基本数据类型和POJO类型。输出结果映射过程类似于JDBC对结果集的解析过程。

Mybatis实例

1.创建日志文件 在src/main/resource文件夹下创建log4j.properties

# Global logging configuration
log4j.rootLogger=ERROR, stdout
# MyBatis logging configuration...
log4j.logger.com.dao=DEBUG
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

如果后面报错找不到配置文件,在src/main/resource文件夹下创建log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>

<Configuration status="warn">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%m%n" />
        </Console>
    </Appenders>
    <Loggers>
        <Root level="INFO">
            <AppenderRef ref="Console" />
        </Root>
    </Loggers>
</Configuration>

2.创建持久化类

public class MyUser {
    private Integer uid;//主键
    private String uname;
    private String usex;
    public Integer getUid() {
        return uid;
    }
    //省略get和set方法,要不然太长了
    @Override
    public String toString() {
        return "User [uid=" + uid +",uname=" + uname + ",usex=" + usex +"]";
    }
}

3.创建映射文件

创建com.mapper包,在该包中创建映射文件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.mapper.UserMapper">
	<!-- 根据uid查询一个用户信息 -->
	<select id="selectUserById" parameterType="Integer"
		resultType="com.po.MyUser">
		select * from user where uid = #{uid}
	</select>
	<!-- 查询所有用户信息 -->
	<select id="selectAllUser" resultType="com.po.MyUser">
		select * from user
	</select>
	<!-- 添加一个用户 ,#{uname}为com.mybatis.po.MyUser的属性值 -->
	<insert id="addUser" parameterType="com.po.MyUser">
		insert into user (uid,uname,usex)
		values(#{uid},#{uname},#{usex})
	</insert>
	<!-- 修改一个用户 -->
	<update id="updateUser" parameterType="com.po.MyUser">
		update user set uname =
		#{uname},usex = #{usex} where uid = #{uid}
	</update>
	<!-- 删除一个用户 -->
	<delete id="deleteUser" parameterType="Integer">
		delete from user where uid
		= #{uid}
	</delete>
</mapper>
  • 映射文件中,<mapper>元素是配置文件的根元素,它包含了一个namespace属性,该属性值通常设置为“包名+SQL映射文件名”,指定了唯一的命名空间。

  • 子元素<select><insert><update>以及<delete>中的信息是用于执行查询、添加、修改以及删除操作的配置。(增删改查)

  • 定义的SQL语句中,“#{}”表示一个占位符,相当于“?”,而“#{uid}”表示该占位符待接收参数的名称为uid。

4.创建MyBatis的配置文件

在src目录下,创建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">
			<!-- 使用JDBC的事务管理 -->
			<transactionManager type="JDBC"/>
			<dataSource type="POOLED">
				<!-- MySQL数据库驱动 -->
				<property name="driver" value="com.mysql.jdbc.Driver"/>
				<!-- 连接数据库的URL -->
				<property name="url" value="jdbc:mysql://localhost:3306/sql_springtest?characterEncoding=utf8"/>
				<property name="username" value="root"/>
				<property name="password" value="20011017lh"/>
			</dataSource>
		</environment>
	</environments>
	<mappers>
	<!-- 映射文件的位置 -->
	<mapper resource="com/mapper/UserMapper.xml"/>
	</mappers>
</configuration>

5.创建测试类

使用输入流读取配置文件,根据配置信息构建SqlSessionFactory对象,通过SqlSessionFactory对象创建SqlSession对象,使用SqlSession对象的方法执行数据库操作。

package com.test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;

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 com.po.MyUser;
public class MyBatisTest {
	public static void main(String[] args) {
		try {
			//读取配置文件mybatis-config.xml
			InputStream config = Resources.getResourceAsStream("mybatis-config.xml");
			//根据配置文件构建SqlSessionFactory
			SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(config);
			//通过SqlSessionFactory创建SqlSession
			SqlSession ss = ssf.openSession();
			//SqlSession执行映射文件中定义的SQL,并返回映射结果
			//com.mapper.UserMapper.selectUserById为UserMapper.xml中的命名空间+select的id
			//查询一个用户
			MyUser mu = ss.selectOne("com.mapper.UserMapper.selectUserById", 1);
			System.out.println(mu);
			//添加一个用户
			MyUser addmu = new MyUser();
			addmu.setUid(1);
			addmu.setUname("陈恒2");
			addmu.setUsex("男2");
						//修改一个用户
			MyUser updatemu = new MyUser();
			updatemu.setUid(1);
			updatemu.setUname("张三");
			updatemu.setUsex("女1");
			ss.update("com.mapper.UserMapper.updateUser", updatemu);
			//删除一个用户
			ss.delete("com.mapper.UserMapper.deleteUser", 1);
			
			ss.insert("com.mapper.UserMapper.addUser",addmu);
			ss.insert("com.mapper.UserMapper.addUser",addmu);

			//查询所有用户
			List<MyUser> listMu = ss.selectList("com.mapper.UserMapper.selectAllUser");
			for (MyUser myUser : listMu) {
				System.out.println(myUser);
			}
			//提交事务
			ss.commit();
			//关闭SqlSession
			ss.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			
		}
	}
}

Mybatis与Spring整合

从上节可以看出直接使用MyBatis框架的SqlSession访问数据库并不简便。MyBatis框架的重点是SQL映射文件,为方便,进行MyBatis与Spring的整合。

  • 通过与Spring的整合,MyBatis的SessionFactory交由Spring来构建。需要在Spring配置文件里配置MyBatis工厂
<!-- 配置MyBatis工厂,同时指定数据源,与MyBatis整合 -->  
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">  
    <property name="dataSource" ref="dataSource" />  
    <!-- configLocation的属性值为MyBatis的核心配置文件 -->
    <property name="configLocation" value="classpath:com/mybatis/mybatis-config.xml"/>
</bean>  
  • 使用Spring管理MyBatis的数据操作接口最简洁的一种是基于MapperScannerConfigurer的整合。需要使用@Mapper注解标注数据访问层接口,并在XML中开启扫描
<!--Mapper代理开发,使用Spring自动扫描MyBatis的接口并装配
    (Spring将指定包中所有被@Mapper注解标注的接口自动装配为MyBatis的映射接口)  --> 
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
   <!-- mybatis-spring组件的扫描器 -->
   <property name="basePackage" value="com.dao"/>
   <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>

实例:

1.创建应用并导入相关JAR包

2.创建持久化类

3.创建SQL映射文件和MyBatis核心配置文件

创建com.mybatis包,在该包中创建MyBatis核心配置文件mybatis-config.xml和SQL映射文件UserMapper.xml。

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>
    <!-- 告诉 MyBatis到哪里去找映射文件 -->
	 <mappers>
        <mapper resource="com/mybatis/UserMapper.xml"/>
 	</mappers>
</configuration>

UserMapper.xml中的namespace与Spring整合后不再是com.mapper.UserMapper而是com.dao.UserDao,其余与上节相同

4.创建数据访问接口 创建com.dao包,在该包中创建UserDao接口,并将接口使用@Mapper注解为Mapper,接口中的方法与SQL映射文件一致。

package com.dao;
import java.util.List;

import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import com.po.MyUser;
@Repository("userDao")
@Mapper
/*使用Spring自动扫描MyBatis的接口并装配
(Spring将指定包中所有被@Mapper注解标注的接口自动装配为MyBatis的映射接口*/
public interface UserDao {
	/**
	 * 接口方法对应SQL映射文件UserMapper.xml中的id
	 */
	public MyUser selectUserById(Integer uid);
	public List<MyUser> selectAllUser();
	public int addUser(MyUser user);
	public int updateUser(MyUser user);
	public int deleteUser(Integer uid);
}

5.创建日志文件

创建日志文件log4j.properties

# Global logging configuration
log4j.rootLogger=ERROR, stdout
# MyBatis logging configuration...
log4j.logger.com.dao=DEBUG
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

6.创建控制层 创建com.controller包,创建UserController类,在该类中调用UserDao接口中的方法。

package com.controller;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import com.dao.UserDao;
import com.po.MyUser;
@Controller("userController")
public class UserController {
	@Autowired
	private UserDao userDao;
	public void test() {
		//查询一个用户
		MyUser auser = userDao.selectUserById(1);
		System.out.println(auser);
		System.out.println("================");
		//添加一个用户
		MyUser addmu = new MyUser();
		addmu.setUname("陈恒");
		addmu.setUsex("男");
		int add = userDao.addUser(addmu);
		System.out.println("添加了" + add + "条记录");
		System.out.println("================");
		//修改一个用户
		MyUser updatemu = new MyUser();
		updatemu.setUid(1);
		updatemu.setUname("张三");
		updatemu.setUsex("女");
		int up = userDao.updateUser(updatemu);
		System.out.println("修改了" + up + "条记录");
		System.out.println( "================");
		//删除一个用户
		int dl = userDao.deleteUser(9);
		System.out.println("删除了" + dl + "条记录");
		System.out.println("================");
		//查询所有用户
		List<MyUser> list = userDao.selectAllUser();
		for (MyUser myUser : list) {
			System.out.println(myUser);
		}
	}
}

7.创建Spring的配置文件

配置数据源、MyBatis工厂以及Mapper代理开发等信息。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:tx="http://www.springframework.org/schema/tx" 
	xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/tx
		http://www.springframework.org/schema/tx/spring-tx.xsd">
                
    <!-- 指定需要扫描的包(包括子包),使注解生效 -->
    <context:component-scan base-package="com.dao"/>
    <context:component-scan base-package="com.controller"/>
    
    
    <!-- 配置数据源 -->
    <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:3306/springtest?characterEncoding=utf8" />
        <property name="username" value="root" />
        <property name="password" value="root" />
        <!-- 最大连接数 -->
        <property name="maxTotal" value="30"/>
        <!-- 最大空闲连接数 -->
        <property name="maxIdle" value="10"/>
        <!-- 初始化连接数 -->
        <property name="initialSize" value="5"/>
    </bean>
    
    
    <!-- 添加事务支持(测试类好像妹用上事务管理) -->
    <bean id="txManager"   
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager">   
        <property name="dataSource" ref="dataSource" />   
    </bean> 
    
    <!-- 开启事务注解(测试类好像妹用上事务管理)-->
    <tx:annotation-driven transaction-manager="txManager" />
    
    
    <!-- 配置MyBatis工厂,指定数据源,与MyBatis整合 -->  
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">  
        <property name="dataSource" ref="dataSource" />  
        <!-- configLocation的属性值为MyBatis的核心配置文件 -->
        <property name="configLocation" value="classpath:com/mybatis/mybatis-config.xml"/>
    </bean>  
    
    
    <!--Mapper代理开发,使用Spring自动扫描MyBatis的接口并装配
    (Spring将指定包中所有被@Mapper注解标注的接口自动装配为MyBatis的映射接口)  --> 
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!-- mybatis-spring组件的扫描器 -->
        <property name="basePackage" value="com.dao"/>
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
    </bean>
</beans>

8.创建测试类 在包com.controller中,创建测试类TestController

package com.controller;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestController {
	public static void main(String[] args) {
		ApplicationContext appCon = new ClassPathXmlApplicationContext("applicationContext.xml");
		UserController uc = (UserController)appCon.getBean("userController");
		uc.test();
	}
}