基本概念
1.1 ORM框架
ORM(Object/Relational Mapping,即对象关系映射)框架,通过描述Java对象与数据库表之间的映射关系,允许我们通过面向对象的方式操作数据库。
举个例子,不使用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对象)映射成数据库中的记录。 这两个框架的主要区别如下。
| Hibernate | MyBatis |
|---|---|
| 全表映射的框架,只需提供POJO和映射关系 | 半自动映射的框架,需要手动匹配POJO、SQL和映射关系 |
| 强大、复杂、间接、全自动化的持久层框架 | 小巧、简单、直接、半自动化的持久层框架 |
1.2 MyBatis工作过程
-
读取MyBatis配置文件:mybatis-config.xml为MyBatis的全局配置文件,配置了MyBatis的运行环境等信息,例如数据库连接信息。
-
加载映射文件:映射文件即SQL映射文件,该文件中配置了操作数据库的SQL语句,需要在MyBatis配置文件mybatis-config.xml中加载。mybatis-config.xml文件可以加载多个映射文件,每个文件对应数据库中的一张表。
-
构造会话工厂:通过MyBatis的环境等配置信息构建会话工厂SqlSessionFactory。
-
创建会话对象:由会话工厂创建SqlSession对象,该对象中包含了执行SQL语句的所有方法。
-
Executor执行器:MyBatis底层定义了一个Executor接口来操作数据库,它将根据SqlSession传递的参数动态地生成需要执行的SQL语句,同时负责查询缓存的维护。
-
MappedStatement对象:在Executor接口的执行方法中有一个MappedStatement类型的参数,该参数是对映射信息的封装,用于存储要映射的SQL语句的id、参数等信息。
-
输入参数映射:输入参数类型可以是Map、List等集合类型,也可以是基本数据类型和POJO类型。输入参数映射过程类似于JDBC对preparedStatement对象设置参数的过程。
-
输出结果映射:输出结果类型可以是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();
}
}