您的位置:首页 > 编程语言 > Java开发

电商平台学习笔记(四)——Spring配置Mybatis简化DAO层省略Mybatis核心配置文件

2016-04-03 08:27 756 查看
今天看到电商视频教程第三天的时候,惊奇的发现,这个电商平台一共有16张表!加上MyBatis的模板Bean,一共32个Bean!如下图:





想到这里,如果有Mybatis的核心配置文件:mybatis-config.xml!仅对每一JavaBean使用<typeAliase>标签就得使用32个,使用<mapper>标签也得使用16个来包括对应的每一张表的配置文件!这种工作量是很大的!(关键还没有技术含量,只是不断的重复使用Ctrl+C和Ctrl+V组合键)。我们肯定不想做这种重复性且毫无技术含量的工作(以前写代码时的确做了不少!

)!所以没办法,自己也做了一个Demo去尝试另外一种省事的配置方式!别不说,直接上代码:
Demo主要目录结构(src下只是在web.xml中配置):

   


  Spring注解配置文件annotation.xml:

<?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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd ">
<!-- Spring扫包 @Service .... -->
<context:component-scan base-package="cn.ilxy.service"/>
</beans>
Spring数据库jdbc配置文件:jdbc.xml

<?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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd ">
<!-- 配置C3P0 -->
<!-- c3p0连接池 DBCP c3p0 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="user" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<!-- 连接池中的最大连接数 -->
<property name="maxPoolSize" value="40" />
<!-- 连接池中的最小连接数 -->
<property name="minPoolSize" value="3"></property>
<!-- 初始化连接池中的 连接数,取值 在 minPoolSize 和 maxPoolSize 之间,default:3 -->
<property name="initialPoolSize" value="1" />
<!-- 最大空闲时间,60s内该连接没有被使用则被丢弃,若为0 永不丢弃.default:0 -->
<property name="maxIdleTime" value="60" />
<!-- 当连接数不够时,每次同时创建多少个连接 -->
<property name="acquireIncrement" value="1" />
<!-- 每60s检查连接池中的所有空间连接,如果没有被使用,就被放弃, default:0 -->
<property name="idleConnectionTestPeriod" value="60" />
</bean>
</beans>

Spring整合Mybatis配置文件:mybatis.xml

<?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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd ">
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mapperLocations" value="classpath:cn/ilxy/dao/*.xml"/>
<property name="typeAliasesPackage" value="cn.ilxy.bean"/>
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="cn.ilxy.dao"/>
</bean>
</beans>
Spring加载jdbc连接数据库信息文件:property.xml

<?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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd ">
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<!-- jdbc的配置:使用这种方式list标签能写多个配置文件 -->
<value>classpath:properties/jdbc.properties</value>
</list>
</property>
</bean>
</beans>
Spring事务支持配置文件:transaction.xml

<?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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd ">
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<aop:aspectj-autoproxy />
<tx:annotation-driven transaction-manager="transactionManager" />
</beans>
数据库相关信息文件:jdbc.peoperties

jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/new_babasport?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true
jdbc.username=root
jdbc.password=950808
TestDBDao.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="cn.ilxy.dao.TestDBDAO">
<resultMap type="TestTb" id="testTb">
<id column="id" jdbcType="INTEGER" property="id" />
<result column="name" jdbcType="VARCHAR" property="name" />
<result column="birthday" jdbcType="VARCHAR" property="birthday" />
</resultMap>
<insert id="testSave" parameterT
c7da
ype="TestTb" useGeneratedKeys="true">
INSERT test_tb(name , birthday) VALUES(#{name} , #{birthday})
</insert>
</mapper>
TestTb.java代码:

package cn.ilxy.bean;

public class TestTb {
private int id;
private String name;
private String birthday;
/**************省略了get和set方法****************/
}
TestDBDAO.java代码:

package cn.ilxy.dao;
import cn.ilxy.bean.TestTb;

public interface TestDBDAO {
public void testSave(TestTb testTb);
}
TestDbService.java代码:

package cn.ilxy.service;
import cn.ilxy.bean.TestTb;

public interface TestDbService {
public void testDbSave(TestTb testTb) ;
}
TestDbServiceImpl.java代码:

package cn.ilxy.service;

import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.ilxy.bean.TestTb;
import cn.ilxy.dao.TestDBDAO;

@Service
@Transactional
public class TestDbServiceImpl implements TestDbService{

@Resource
private TestDBDAO dao;

public void testDbSave(TestTb testTb) {
dao.testSave(testTb);
}
}
好了,到这里,主要的文件源码都在这里了!经过测试,证明是没有问题的!

不过在配置这个的过程中,也是蛮曲折的!主要是一直要这个异常,如下:

Caused by: java.lang.IllegalArgumentException: org.apache.ibatis.builder.BuilderException: Error parsing Mapper XML. Cause: org.apache.ibatis.builder.BuilderException: Wrong namespace. Expected 'cn.ilxy.dao.TestDBDao' but found 'cn.ilxy.bean.TestTb'.
at org.mybatis.spring.mapper.MapperFactoryBean.checkDaoConfig(MapperFactoryBean.java:83)
at org.springframework.dao.support.DaoSupport.afterPropertiesSet(DaoSupport.java:44)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1637)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1574)
... 40 more
Caused by: org.apache.ibatis.builder.BuilderException: Error parsing Mapper XML. Cause: org.apache.ibatis.builder.BuilderException: Wrong namespace. Expected 'cn.ilxy.dao.TestDBDao' but found 'cn.ilxy.bean.TestTb'.
at org.apache.ibatis.builder.xml.XMLMapperBuilder.configurationElement(XMLMapperBuilder.java:120)
at org.apache.ibatis.builder.xml.XMLMapperBuilder.parse(XMLMapperBuilder.java:92)
at org.apache.ibatis.builder.annotation.MapperAnnotationBuilder.loadXmlResource(MapperAnnotationBuilder.java:167)
at org.apache.ibatis.builder.annotation.MapperAnnotationBuilder.parse(MapperAnnotationBuilder.java:118)
at org.apache.ibatis.binding.MapperRegistry.addMapper(MapperRegistry.java:72)
at org.apache.ibatis.session.Configuration.addMapper(Configuration.java:685)
at org.mybatis.spring.mapper.MapperFactoryBean.checkDaoConfig(MapperFactoryBean.java:80)
... 43 more
Caused by: org.apache.ibatis.builder.BuilderException: Wrong namespace. Expected 'cn.ilxy.dao.TestDBDao' but found 'cn.ilxy.bean.TestTb'.
at org.apache.ibatis.builder.MapperBuilderAssistant.setCurrentNamespace(MapperBuilderAssistant.java:78)
at org.apache.ibatis.builder.xml.XMLMapperBuilder.configurationElement(XMLMapperBuilder.java:112)
... 49 more
这个异常(最后面,加粗部分)意思是说,错误的命名空间,本来该命名空间(namespace)应该是填cn.ilxy.dao.TestDBDao,但是实际上是cn.ilxy.bean.TestTb!后来照着视频再看一遍才知道答案!在TestDBDao.xml文件中的namespace属性我填错了(填成了cn.ilxy.bean.TestTb,有核心配置文件时可以填这个)!后来改成cn.ilxy.dao.TestDBDao就能正常运行了!

之后在百度上百度了一下,才明白其中真正的原因!这个namespace属性一定要写成表对应的接口,并且接口中的方法一定要和增删改查语句的id对应:即没对应的话,最终执行的操作并不是你预期的操作,不存在的话则直接报异常(我做过测试了:将接口中的唯一方法改成了testAdd,报错信息如下:org.apache.ibatis.binding.BindingException:
Invalid bound statement (not found): cn.ilxy.dao.TestDBDAO.testAdd
)!这里我就有一个大胆的猜测:Spring的底层实现机制使用了反射!

果然,网上百度了一下MapperScannerConfigurer的实现原理!看了别人的博客发现:Spring在底层的确是根据以上的两项信息,利用JDK的代理!继承实现InvokeHandler接口并注入了SqlsessionFactory)而帮我们产生了代理动态代理类,我们才能只定义接口而不需要去实现该接口了!在这里,我们不得不感叹Spring的神奇之处了!我也是深深的体会到了编程之美!

另附上另外一篇文章的地址!http://blog.csdn.net/hupanfeng/article/details/21454847!感谢这位大神,通过他写的博客证实了我的猜测!

今天也是花了很长时间才解决那个Bug,觉得很有价值所以写这篇博客记录下来,分享给大家!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Spring