文章目录
- 前言
- 一、MyBatis
- MyBatis所需的jar包
- ORM
- MyBatis的基本要素
- a:核心接口和类
- b:MyBatis核心配置文件(MyBatis-config.xml):
- c:SQL映射文件(mapper.xml)
- resultMap和resultType区别
- 动态SQL
- 二、Spring
- 所需的jar包
- IoC
- AOP
- 面向切面编程
- 注解
- 三、MyBatis与Spring的整合
- 整合思路
- 具体操作
前言
以下内容是我在初学Spring与Mybatis时候做的笔记,当时放在了备忘录里面,如今把笔记重整到CSDN上,为了以后复习也为了分析给大家,笔记写的算是比较完整,回看自己做的还是有点羞涩。如有错误之处,欢迎指正,当我日后更强大的时候,我会不断的对内容进行补充和完善。当然学习也就是这么一个过程,学习-实践-总结-实践-总结… 转载请申明原文地址,希望大家支持,谢谢。
Wink小提示:以下是本篇文章正文内容,下面案例可供参考
一、MyBatis
MyBatis框架是一个开源的数据持久层框架;内部封装了通过JDBC访问数据库的操作,支持普通的SQL查询、存储过程和高级映射,几乎消除了所有的JDBC代码和参数配置以及结果集的检索。
核心思想:将程序中的大量SQL语句剥离出来,配置在配置文件中,实现SQL的灵活配置。优点:在不修改程序代码的情况下,直接在配置文件中修改SQL语句。
MyBatis所需的jar包
ORM
ORM :对象/关系映射
O:程序中的实体类
R:数据库中的实体表格
M:在对象模型和关系型数据库中建立起对应关系,并提供一种机制,通过JavaBean对象去操作数据库表中的数据。
在实际开发中,程序员使用面向对象的技术操作数据,而当存储数据时,使用的却是关系型数据库,这时使用ORM在对象模型和关系型数据库中的表建立一座桥梁,使用API直接操作JavaBean 对象就可以实现数据的存储、查询、更改、删除等操作。
Mybatis通过简单的XML或者注解进行配置和原始映射,将实体类和SQL语句之间建立映射关系,是一种半自动化的ORM实现。
MyBatis的基本要素
a:核心接口和类
SqlSessionFactoryBuilder:负责构建SqlSessionFactory,并提供多个build()方法的重载;
特点:用过即丢,一旦创建了SqlSessionFactory对象之后,这个类就不存在了,因此SqlSessionFactoryBuilder的最佳范围就是存在于方法体内;
可以通过XML配置文件或者Configuration类的实例获取SqlSessionFactoryBuilder对象;
InputStream is =
Resources.getResourceAsStream(“mybatis-config”);
SqlSessionFactory factory = new SqlSessionFactoryBuilder()
.build(is);
SqlSessionFactory:每个MyBatis的应用程序都以一个SqlSessionFactory对象的实例为核心;
作用:创建SqlSession实例对象,通过openSession()方法来获取该对象实例。
SqlSession:用于执行持久化操作的对象,类似于JDBC中的Connection,它提供了执行SQL命令所需的所有方法,可以通过SqlSession实例直接运行已映射的SQL语句。
sqlSession = factory.openSession();
SqlSession的使用方式:基于mapper接口方式操作数据
分页:
List list=sqlSession.getMapper(UserMapper.class)
.getUser_FenYe(userName,userRole,currentNo,pageSize);
b:MyBatis核心配置文件(MyBatis-config.xml):
基本元素:
1、Configuration:整个XML配置文件的根节点
1.1 properties:描述的都是外部化、可替代的属性,比如引入database.properties文件
<!--引入外部文件:database.properties(数据库连接的相关配置)-->
<properties resource="database.properties"/>
1.2 settings:设置一些非常重要的设置选项,用于设置和改变MyBatis运行中的行为,比如设置懒加载或者对于resultMap自动映射的匹配级别。
<settings>
<setting name="logImpl" value="LOG4J"/>
<setting name="autoMappingBehavior" value="PARTIAL"/>
<setting name="cacheEnabled" value="true"/>
</settings>
1.3 typeAliases:配置类型别名,通过与Mybatis的SQL 映射文件相关联,减少输入多余的完整类名,以简化操作。
<typeAliases>
<package name="cn.bdqn.pojo"/>
</typeAliases>
1.4 environments元素:配置多套运行环境:开发环境、测试环境、生产环境等,
<environments default="development">
<!--运行ID:通过default属性指定当前的运行环境ID为development,对于环境ID一定要唯一-->
<environment id="development">
<!--配置事务管理类型为JDBC类型-->
<transactionManager type="JDBC"></transactionManager>
<!--mybatis自带的数据源:JNDI:基于tomcat的数据源-->
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${user}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
1.5 mappers元素:用来定义SQL的映射语句
<mappers>
<!--将mapper文件(SQL映射文件)加入到配置文件中-->
<mapper resource="cn/bdqn/dao/UserMapper.xml"/>
</mappers>
c:SQL映射文件(mapper.xml)
顶级元素:
1、mapper:映射文件的根元素节点,只有一个属性(namespace)命名空间,作用:用于区分不同的mapper,全局唯一;绑定DAO接口,即面向接口编程,当namespace绑定某一接口之后,可以不用写该接口的实现类,Mybatis会通过接口的完整限定名查找到对应的mapper配置来执行SQL语句,因此namespace必须与接口同名。
2、cache:配置给定命名空间的缓存
3、cache-ref:从其它命名空间引用缓存配置。
4、resultMap:用来描述数据库结果集和对象的对应关系。
5、sql:可以重用的SQL语句块
6、insert:映射插入语句
7、delete:映射删除语句
8、update:映射更新语句
9、select:映射查询语句
<mapper namespace="cn.bdqn.dao.UserMapper">
<cache flushInterval="60000" size="512"
readOnly="true" eviction="FIFO"/>
<!--使用select完成单条件查询-->
<select id="count" resultType="int">
select count(1) from smbms_user
</select>
<!--使用select完成多条件查询-->
<select id="getUserByUserName"
parameterType="String" resultType="User">
select * from smbms_user
userName like concat('%',#{userName},'%')
and userRole=#{userRole}
</select>
<!--使用resultMap完成查询结果的展现-->
<resultMap id="userRoleResult" type="Role">
<id property="id" column="r_id"/>
<result property="roleCode" column="roleCode"/>
<result property="roleName" column="roleName"/>
</resultMap>
<select id="getUserByRoleId" parameterType="int"
resultMap="userRoleResult">
select u.*,r.id as r_id,r.roleCode,r.roleName
from smbms_user u,smbms_role r
where u.userRole=r.id
and u.userRole=#{userRole}
</select>
</mapper>
resultMap和resultType区别
resultType:直接表示返回类型,包括基础数据类型和复杂数据类型;
resultMap:是对外部resultMap定义的引用,对应外部resultMap的id,表示返回结果映射到哪一个resultMap上。使用场景:数据库字段与对象属性不一致或者需要做复杂的联合查询以便自由控制映射结果。
<resultMap id=”resultMap的唯一标识” type=”映射结果类型”>
<id column=”数据库主键id” property=”” />
<result column=””property=”” />
</resultMap>
3、resultMap自动映射级别:
<settings>
<setting name="autoMappingBehavior" value="PARTIAL"/>
</settings>
默认的映射级别为:PARTIAL
NONE:禁止自动匹配
4、使用@Param注解实现参数入参
public int updatepwd1(User user);
//将以上方法改为:
public int updatepwd2(@Param("id")Integer id,
@Param("userPassword") String pwd);
优点:代码可读性较高。
5、resultMap高级结果映射
assiciation:映射到JavaBean的某个复杂类型,例如在User类中有个(Role role)角色属性;
<resultMap id="userRoleResult" type="User">
<id property="id" column="id"></id>
<result property="userCode" column="userCode"/>
<result property="userName" column="userName"/>
<!--property:User类中角色属性名;javaType:完整的Java类名;resultMap:映射角色表的对应字段-->
<association property="role" javaType="Role"
resultMap="roleResult"/>
</resultMap>
<select id="getUserByRoleId" parameterType="int"
resultMap="userRoleResult">
select u.*,r.id as r_id,r.roleCode,r.roleName
from smbms_user u,smbms_role r
where u.userRole=r.id
and u.userRole=#{userRole}
</select>
collection:映射到JavaBean的某个复杂类型是集合列表
例如在User类中有个集合属性名(List
addressList)
<resultMap id="UserAddress" type="User">
<id property="id" column="id"/>
<result property="userName" column="userName"/>
<!--ofType:完整的Java类名,property:映射数据库列的实体对象的属性-->
<collection property="addressList" ofType="Address">
<id property="id" column="a_id"/>
<result property="contact" column="contact"/>
<result property="addressDesc" column="addressDesc"/>
</collection>
</resultMap>
<select id="getUserAndAddress" parameterType="int"
resultMap="UserAddress">
select u.*,a.id as a_id,a.contact,a.addressDesc,a.tel
from smbms_user u,smbms_address a
where a.userId=u.id and u.id=#{id}
</select>
动态SQL
元素:1、if:实现简单的条件选择
2、choose:相当于Java中的switch语句
3、where:简化SQL语句中where的条件判断
4、set:解决动态更新语句
5、trim:可以灵活去除多余的关键字
trim属性:
prefix:前缀,通过自动识别是否有返回值后,在trim包含的内容上加上前缀,例如where
suffix:后缀,在trim包含的内容上加上后缀
prefixOverrides:对于trim包含内容的首部进行指定内容的忽略,例如:and | or
suffixOverrides:对于trim包含内容的尾部进行指定内容的忽略
6、foreach:迭代一个集合,通常用于in条件。
foreach属性:
item:集合中每一个元素进行迭代时的别名
index:指定一个名称,用于表示在迭代过程中,每次迭代到的位置
open:表示该语句以什么开始(既然是in语句,是以(开始)
separator:每次进行迭代之间以什么为分隔符,既然是in语句,是以,作为分隔符。
colse:表示该语句以什么结束(既然是in语句,是以)结束)
collection:该属性的值不一样,有三种情况:
list:入参为单参数且参数类型是一个List集合
array:入参为单参数且参数类型为一个数组
Map:传入参数为多参数
<select id="getUserByUserName"
parameterType="String" resultType="User">
select * from smbms_user
<where>
<if test="userName!=null and userName!=''">
userName like concat('%',#{userName},'%')
</if>
<if test="userRole!=0">
and userRole=#{userRole}
</if>
</where></select>
//<trim>标签
<select id="getUserByUserName"
parameterType="String" resultType="User">
select * from smbms_user
<trim prefix="where" suffixOverrides="and | or">
<if test="userName!=null and userName!=''">
userName like concat('%',#{userName},'%')
</if>
<if test="userRole!=0">
userRole=#{userRole}
</if>
</trim></select>
//更新SQL语句
<update id="updateUser" parameterType="User">
update smbms_user
<trim prefix="set" suffixOverrides=","
suffix="where id=#{id}">
<if test="userCode!=null and userCode!=''">userCode=#{userCode},</if>
<if test="userName!=null and userName!=''">userName=#{userName},</if>
<if test="userPassword!=null and userPassword!=''">userPassword=#{userPassword},</if>
<if test="gender!=0">gender=#{gender},</if>
<if test="birthday!=null and birthday!=''">birthday=#{birthday},</if>
<if test="phone!=null and phone!=''">phone=#{phone},</if>
<if test="userRole!=null and userRole!=''">userRole=#{userRole},</if>
<if test="modifyDate!=null and modifyDate!=''">modifyDate=#{modifyDate},</if>
<if test="modifyBy!=0">modifyBy=#{modifyBy}</if>
</trim>
</update>
迭代集合:(业务功能返回的数据是多行语句)
//<List>集合
<select id="getUserListByRoleId" resultMap="userLists">
select * from smbms_user
where userRole in
<foreach collection="list" item="roleIds"
open="(" separator="," close=")">
#{roleIds}
</foreach>
</select>
//<Map>集合
<select id="getUser_map" resultMap="userLists">
select * from smbms_user where userRole in
<foreach collection="rKey" open="("
separator="," close=")"
item="roleMap">
#{roleMap}
</foreach>
</select>
二、Spring
所需的jar包
IoC
IoC:控制反转,也叫依赖注入,是面向对象编程中的一种设计理念,用来降低程序代码之间的耦合度。
依赖(也叫耦合度):在代码中一般通过局部变量、方法参数、返回值等建立的对于其他对象的调用关系。
AOP
AOP:面向切面编程,AOP一般适用于具有横切逻辑的场合,如访问控制,事务管理,性能检测等。
理解横切逻辑:
为了保证系统健壮可用,就要在众多的业务方法中加入如日志、事务控制、异常处理等代码,使得原本很复杂的业务处理代码变得跟为复杂,那么穿插在既定业务中的这些额外的操作就是所谓的“横切逻辑”,也成为“切面”。
开发者如何才能不受这些附加要求的干扰?
使用面向切面编程:在不改变原程序的基础上为代码段增加新的功能,对代码进行增强处理。
面向切面编程
面向切面编程的基本概念:
1、切面(Aspect):一个模块化的横切逻辑,或称为横切关注点。
2、连接点(Join point):程序执行中的某个具体的执行点,如程序中原本要执行的业务方法,例如增删改
3、切入点(Pointcut):对连接点的特征进行描述
4、增强处理(Advice):切面在某个特定连接点上执行的代码逻辑,
5、AOP代理:由AOP创建的对象,实现执行增强处理方法等功能。
6、织入:将增强处理连接到应用程序中的类型或对象上的过程。
注解
使用注解实现IoC配置
1、使用注解定义Bean
@Component(“userDao”):相当于XML配置文件中
<bean id=”userDao”class=”dao.impl.UserDaoImpl”/>
@Repository:标注DAO类
@Service:标注业务类
@Controller:标注控制器类
@Service("userService")
public class impl implements UserService {
//使用Autowired为dao属性注入所依赖的对象,Spring将直接对dao 属性进行赋值,可省略setter方法
@Autowired
//使用Qualifier指定所需的Bean的名称。
@Qualifier(“userDao”)
private UserDao dao;
}
加载注解定义的Bean
<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"
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-3.2.xsd">
<!--使用context命名空间下的component-scan 标签扫描注解标注类;base-package属性指定了需要扫描的基准包-->
<context:component-scan base-package="cn.bdqn.service,cn.bdqn.dao"/>
</beans>
//java标准注解
@Resource
@Service("userService")
public class impl implements UserService {
@Resource(name=”userDao”)
private UserDao dao;
}
2、使用注解定义切面
//Spring通过AspectJ实现了以注解的方式定义切面,大大减少了代码量。使用@Aspect注解将UserServiceLogger定义为切面,使用@Before注解将before()定义为前置增强;使用@AfterReturning注解将after()方法定义为后置增强。
@Aspect
public class UserServiceLogger {
private Logger logger=Logger.getLogger(UserServiceLogger.class);
@Before("execution(* cn.bdqn.service.UserService.*(..))")
public void before(JoinPoint joinPoint){
logger.info("调用"+joinPoint.getTarget()+"的"+joinPoint.getSignature().getName()+"方法。方法入参:"
+Arrays.toString(joinPoint.getArgs()));
}
@AfterReturning(pointcut="execution(* cn.bdqn.service.UserService.*(..))",returning = "result")
public void after(JoinPoint joinPoint,Object result){
logger.info("调用"+joinPoint.getTarget()+"的"+joinPoint.getSignature().getName()+"方法。方法的返回值为:"+result);
}
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd”>
<bean id="theLogger" class="cn.bdqn.aop.UserServiceLogger"></bean>
<!--支持对于@Aspect注解的支持,Spring将自动为Bean创建代理-->
<aop:aspectj-autoproxy/>
</beans>
三、MyBatis与Spring的整合
整合思路
作为Bean容器,Spring框架提供了IoC机制,可以接管所有组件的创建工作并进行依赖管理,整合的主要工作就是把MyBatis框架使用中所涉及的核心组件配置到Spring容器中,交由Spring来创建和管理。
具体操作
1、在项目中加入Spring、MyBtis以及整合所需要的jar文件
2、创建实体类User.java
3、创建数据访问接口UserMapper.java(包含所需的抽象方法)
public interface UserMapper {
public List<User> getUserList(User user);
public User getUserListById(Integer id);
public int add(User user);
public int updateUser(User user);
public int delUser(Integer id);
}
4、配置SQL映射文件UserMapper.xml
<mapper namespace="cn.smbms.dao.UserMapper">
<resultMap id="UserList" type="User">
<result property="userName" column="userName"/>
<result property="userCode" column="userCode"/>
<result property="userRoleName" column="roleName"/>
</resultMap>
<select id="getUserList" resultMap="UserList">
select u.*,r.roleName
from smbms_user u,smbms_role r
where u.userRole=r.id
and u.userName like concat('%',#{userName},'%')
and u.userRole=#{userRole}
</select>
</mapper>
5、配置MyBatis配置文件 mybatis-config.xml
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--类型别名-->
<typeAliases>
<package name="cn.smbms.entity"/>
</typeAliases>
</configuration>
6、配置数据源applicationContext-mybatis.xml
<beans>
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName"value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${user}"/>
<property name="password" value="${password}"/>
</bean>
</beans>
7、配置SqlSessionFactoryBean
<bean id="sqlSessionFactory"
class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation"
value="classpath:mybatis-config.xml"/>
</bean>
8、使用MapperScannerConfigurer注射器实现,简化DAO模块的编码
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage"
value="cn.smbms.dao"/>
</bean>
9、
<!--扫描注解定义的业务类的bean-->
<context:component-scan base-package="cn.smbms.service"/>
10、配置声明式事务
//@Transactional //可以为该类的所有业务方法同意添加事务处理,
@Transactional
@Service("userService")
public class UserServiceImpl implements UserService {
@Resource
private UserMapper userMapper;
@Transactional(propagation = Propagation.SUPPORTS)
@Override
public List<User> findUserList(User user) {
try{
return userMapper.getUserList(user);
}catch (Exception ex){
ex.printStackTrace();
throw ex;
}}
<beans>
<!--扫描注解定义的业务类的bean-->
<context:component-scan base-package="cn.smbms.service"/>
</beans>