乱入Spring+Mybatis
新进入一个项目,写了一个功能,就是提供一个服务(service),该服务能够查询和插入。完成后,想要用junit测试一下;发现到了DAO底层注入的SqlSession字段为空;才意识到这是一个Spring注解的项目;之前经验主要是Spring MVC方式开发使用到Spring的注解和依赖注入。另外,这个字段被注解为@Autowired(required=true),在编译器都没有被报错实例化失败,也说明了以着这种测试的方式根本就没有走Spring的容器来管理对象。
看来是时候要好好研究一下Spring和Mybatis的一些功能本质。
想要在非Web工程使用Spring,那么需要通过于是添加了applicationContext.xml,定义了服务类bean,然后通过下面的方式获取容器获取对象:
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");// 读取bean.xml中的内容
SmallServiceImplsvr = ctx.getBean("service", SmallServiceImpl.class);// 创建bean的引用对象
Spring的思想就是容器管理bean,所以无论是他和谁组合,还是让他管理什么,都是向Spring的容器中放入对象。那么,这种放入就有了很多种方式,一种是通过向配置文件中添加配置的传统方式,比如,下面就是添加了service的引用。
<?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"
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-4.0.xsd">
<context:annotation-config />
<context:component-scan
base-package="com.a.b.component, com.a.b.service, com.a.b.dao" />
<bean id="service" class="com.a.b.service.impl.SmallServiceImpl"></bean>
</beans>
定义了bean就可以通过上面的代码来获取SmallServiceImpl了。但是对于这段xml有两点说明:
1. 其实是不需要对annotation-config进行声明,因为component-scan已经具有了annotation-config的职能;
2.component-scan可以一次性声明扫描多个包(Spring做的扫描是扫描class文件);我就是曾经有一次运行报错,就是因为有一个包没有添加到监视,导致了Spring容器创建bean失败;
扫描的本质是基于注解(@Service,@Component,@Repository)来发现bean(免于在xml文件进行配置),扫描之后,就是“装配”,类似于Autowired声明是为了Spring容器在实例化bean的过程中来装配字段,所以扫描和装配是两个阶段,后者是基于前者,也不完全依赖(还可以基于配置文件)。
你会发现一个现象:@Autowired声明的字段的类型都是接口,但是作为装配的类都是通过@Service/@Repository注解声明的实现类。
另外对于基于注解的说明,对于本例而言,可以不再配置文件中声明service,可以在定义的类头声明@Service(value="service")也可;如果不指定value值,默认的bean的名称为类名首字母小写(smallServiceImp)
@Service(value="service")
public class SmallServiceImpl {
通过getBean获取到了SmallService之后,在运行发现还是报错,因为执行到DAO的时候,发现那个SqlSession的字段(required=true)实例化失败,无法找到候选类;查找了很久原因;其实扫描的是指定的包,无法找到mybaits的类很正常,这个时候就是第三段那段话,和第三方组件配合的时候,第三方组件都是以bean形式定义到了Spring中;另外这个问题查了一段时间是因为我忘记了MyBatis的核心组件就是SqlSession以及SqlSessionFactory,早点想到就能知道需要将其以bean形式注入。
<bean id="dataSource" name="dataSource"
class="com.mchange.v2.c3p0.ComboPooledDataSource">
<!-- 指定连接数据库的驱动 -->
<property name="driverClass" value="dm.jdbc.driver.DmDriver" />
<!-- 指定连接数据库的URL -->
<property name="jdbcUrl" value="jdbc:dm://localhost:5236" />
<!-- 指定连接数据库的用户名 -->
<property name="user" value="user" />
<!-- 指定连接数据库的密码 -->
<property name="password" value="password" />
<!-- 指定连接池中保留的最大连接数. Default:15 -->
<property name="maxPoolSize" value="10" />
<!-- 指定连接池中保留的最小连接数 -->
<property name="minPoolSize" value="3" />
<!-- 指定连接池的初始化连接数 取值应在minPoolSize 与 maxPoolSize 之间.Default:3 -->
<property name="initialPoolSize" value="3" />
<!-- 最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。 Default:0 -->
<property name="maxIdleTime" value="0" />
<!-- 当连接池中的连接耗尽的时候c3p0一次同时获取的连接数. Default:3 -->
<property name="acquireIncrement" value="2" />
<!-- JDBC的标准,用以控制数据源内加载的PreparedStatements数量。 但由于预缓存的statements属于单个connection而不是整个连接池所以设置这个参数需要考虑到多方面的因数.如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default:0 -->
<property name="maxStatements" value="20" />
<!-- 每60秒检查所有连接池中的空闲连接.Default:0 -->
<property name="idleConnectionTestPeriod" value="60" />
</bean> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:sqlmapConfig.xml"></property>
<property name="mapperLocations" value="classpath:mapper/*Mapper.xml"></property>
<property name="typeAliasesPackage" value="com.a.b.vo"></property>
</bean> <!-- 配置SQLSession模板 -->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory" />
</bean>
增加了三个bean,定义数据源(dataSource),定义SqlSessionFactory以及SqlSession就不多说什么了。核心就是SqlSessionFactory,dataSource字段说明了数据源信息(此次项目使用的ComboPooledDataSource进行JDBC以及连接池管理);mapperLocation,就是告知mapper文件路径,注意这里路径指的是class路径,因为Spring容器的操作都是在部署之后的环境,所以一定是claas路径;configLocation,对于mybatis的配置(比如mapper参数对象,返回对象的别名,mybatis对于缓存的一些配置都是放置在这个配置文件中;至于typeAliasesPackage,不知。
<?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>
<settings>
<setting name="cacheEnabled" value="true" />
<setting name="lazyLoadingEnabled" value="true" />
<setting name="aggressiveLazyLoading" value="false" />
<setting name="multipleResultSetsEnabled" value="true" />
<setting name="useColumnLabel" value="true" />
<setting name="defaultExecutorType" value="REUSE" />
<setting name="defaultStatementTimeout" value="25000" />
</settings> <typeAliases>
<package name="com.zcm.mall.vo"/>
</typeAliases> </configuration>
上面这个就是mybatis的配置文件。
配置好了SqlSession/Factory信息之后,SqlSession字段可以被实例化,而且可以顺利的访问数据库了。
小记
1. 在mapper文件中,经常会有比较大小的情况">","<",对于这些特殊字符要么采用转义的方式,要么采用<![CDATA[ 这里写你的sql ]]> 这种方式;
2.在mapper的sql中,可以通过在sql语句中添加<include refid="whereClause" />来添加共通的sql,比如where的过来条件(根据查询bean字段进行拼sql),可能多个select语句会共用,这个时候可以考虑使用。比如分页是一个共同的sql,可以单独放置到一个文件中(比如CommonsqlMapper.xml),然后使用的地方通过include进行引用。
CommonSqlMapper.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="commonSql" >
<sql id="pageSql">
<if test="offset != null and limit != null">
limit #{offset}, #{limit}
</if>
</sql>
</mapper>
ASqlMapper.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.zcm.mall.vo.AuditLog">
<resultMap id="auditLog" type="com.a.b.vo.c">
<id column="id" property="id" jdbcType="BIGINT" />
<result column="log_type" property="logType" jdbcType="VARCHAR" />
<result column="log_msg" property="log" jdbcType="VARCHAR" />
<result column="oper_Id" property="userId" jdbcType="BIGINT" />
<result column="oper_name" property="userName" jdbcType="VARCHAR" />
<result column="create_date" property="createDate" jdbcType="VARCHAR" />
</resultMap>
<select id="select" parameterType="auditLog" resultMap="auditLog">
select * from AUDIT_LOG
<include refid="whereClause" />
<include refid="commonSql.pageSql" />
</select>
上面的xml中有一个地方定义了resultMap,这个定义用于将数据库中查询结果和实体类进行映射之用。如果你的数据库字段定义的和实体类名称不一致,需要通过这种方式进行映射。
乱入Spring+Mybatis的更多相关文章
- Idea SpringMVC+Spring+MyBatis+Maven调整【转】
Idea SpringMVC+Spring+MyBatis+Maven整合 创建项目 File-New Project 选中左侧的Maven,选中右侧上方的Create from archetyp ...
- SpringMVC+Spring+MyBatis+Maven调整【转】
Idea SpringMVC+Spring+MyBatis+Maven整合 创建项目 File-New Project 选中左侧的Maven,选中右侧上方的Create from archetyp ...
- Spring+MyBatis实践—工程配置
初次实践:Spring+MyBatis技术搭建框架,采用Bootstrap前端开源框架. 简介: MyBatis是支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis 消除 了几乎所 ...
- Spring+Mybatis+SpringMVC后台与前台分页展示实例(附工程)(转)
林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 摘要:本文实现了一个后台由Spring+Mybatis+SpringMVC组成,分页采用Pag ...
- 玩转SSH(四):Struts + Spring + MyBatis
一.创建 SSMDemo 项目 点击菜单,选择“File -> New Project” 创建新项目.选择使用 archetype 中的 maven-webapp 模版创建. 输入对应的项目坐标 ...
- Spring mybatis源码篇章-sql mapper配置文件绑定mapper class类
前言:通过阅读源码对实现机制进行了解有利于陶冶情操,承接前文Spring mybatis源码篇章-MybatisDAO文件解析(二) 背景知识 MappedStatement是mybatis操作sql ...
- Spring mybatis源码篇章-MybatisDAO文件解析(一)
前言:通过阅读源码对实现机制进行了解有利于陶冶情操,承接前文Spring mybatis源码篇章-SqlSessionFactory 加载指定的mybatis主文件 Mybatis模板文件,其中的属性 ...
- Spring mybatis源码篇章-NodeHandler实现类具体解析保存Dynamic sql节点信息
前言:通过阅读源码对实现机制进行了解有利于陶冶情操,承接前文Spring mybatis源码篇章-XMLLanguageDriver解析sql包装为SqlSource SqlNode接口类 publi ...
- Spring mybatis源码篇章-MapperScannerConfigurer关联dao接口
前言:Spring针对Mybatis的XML方式的加载MappedStatement,通过引入MapperScannerConfigurer扫描类来关联相应的dao接口以供Service层调用.承接前 ...
随机推荐
- laravel 学习之第一章
LTS : long time support. download url : http://www.golaravel.com/download/ 第一篇 目录介绍: resource:包含了原 ...
- linux 桥接模式下 固定ip 设置
DEVICE=eht0 #网卡名称BOOTPROTO=none #关闭自动获取 dhcp IPADDR=192.168.0.178 #ip地址GATEWAY=192.168.0.1 DN ...
- 【转】Android编译系统详解(一)——build/envsetup.sh
出处 http://www.cloudchou.com/android/post-134.html 本文原创作者:Cloud Chou. 欢迎转载,请注明出处和本文链接 准备好编译环境后,编译Rom的 ...
- crontab定时执行shell脚本
步骤一 首先我们先看一下是否安装了crontab.一般情况下linux系统会自带crontab及crond.如果没有安装,请使用以下指令安装:yum install vixie-cron ...
- AI换脸教程:DeepFaceLab使用教程(2.训练及合成)
如果前期工作已经准备完毕(DeepFaceLab下载(https://www.deepfacelabs.com/list-5-1.html),然后安装相应的显卡驱动,DeepFaceLab使用教程(1 ...
- setTimeout延迟加载
使用setTimeout延时计算 setTimeout当时间为0时
- wed.xml 中 filter、servlet 配置格式
1.wed.xml 中 filter 配置格式 <filter> <filter-name>filterName</filter-name> <filter- ...
- 【java工具类】对字节数组字符串进行Base64解码并生成图片
import java.io.File;import java.io.FileOutputStream;import java.io.OutputStream;import org.springfra ...
- pycharm如何添加固定代码块
1. file -- settings -- 搜索框输入live,找到 Live Templates 2. 选择你要添加到哪个语言中去,打开python组,并点击右上角 “+”,选择 1.Live T ...
- 序列式容器————string
目录 前言 1.构造函数 2.size() 3.length() 4.maxsize() 5.capacity() 6.reserve() 7.resize() 8.获取元素at() 9.字符串比较c ...