发表于: 2018-04-01 21:32:28
2 509
今天完成的事情:
spring-mybatis的整合方式
1.1 遇到的错误
a.关于注入配置文件报错:
<context:property-placeholder location="classpath:c3p0.properties"/>
文件头已经插入:
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context/spring-context.xsd"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd"
改为(更改context后面连接)
<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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="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/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.0.xsd">
文件头是获取配置的命名空间,用来解析文中的配置!需要就配置,不需要就不用配置!
b.映射语句值重复错误:
Mapped Statements collection already contains value for mybatis.mapper.PersonMapper.selectById
原因:Mapper类里注解了@Select("……") ,它和xml文件里的<Select>标签重复,所以会报映射语句已经包含值的错误。如果使用映射这里就不用注解。
@Select(" SELECT * FROM person WHERE id = #{id}")
Person selectById(int id);
其它原因:parameterType或者resultMap未标明值,或者id重复
<select id="selectById" parameterType="int" resultMap="personMap" >
SELECT * FROM person WHERE id = #{id}
</select>
c.关于getBean()错误:
找不到bean“mybatisAceion”
连接上下文
MybatisAction mybatisAction = (MybatisAction) context.getBean("mybatisAction");
原因:自动扫描,添加文件夹,用‘ , ’隔开
<context:component-scan base-package="mybatis,action"/>
d.莫名其妙的错误:
Connections could not be acquired from the underlying database!
Access denied for user 'root '@'182.xx.xx.xx' (using password: YES)
这个错误真是匪夷所思,因为我的数据库从来没有配置过这个地址,调用的xml文件也是,除了我的远程数据库119.地址之外没写过任何其它地址。
后来发现这是我宽带的ip地址,也就是我本机的地址……
然后又运行了两次就成功连上了,唯一的改动就是把配置文件c3p0.properties里参数后面的空格去掉了。
其它错误自动忽略
1.2 整合Spring-Mybatis
整合Spring-mybatis可以使用MapperScannerConfigurer方式装配bean(xml),也可以使用SqlSessionDaoSupport类获得sqlsession(继承SqlSessionDaoSupport)来执行sql查询。它们都需要通过Mybatis的工厂bean(org.mybatis.spring.SqlSessionFactoryBean)来实现,Mybatis跟spring整合后,使用FactoryBean代替自己的SqlSessionFactoryBuilder方法创建SqlSessionFactory :
<!--要和 Spring 一起使用 MyBatis,你需要在 Spring 应用上下文中定义至少两样东西:一个 SqlSessionFactory 和至少一个数据映射器类。-->
<!--在 MyBatis-Spring 中,SqlSessionFactoryBean 是用于创建 SqlSessionFactory 的。 SqlSessionFactory 需要一个 DataSource(数据源)-->
<!--配置这个工厂 bean: 1.导入数据源 2.配置mapper.xml 3.可以配置mybatis-config文件,但是不需要-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="mapperLocations" value="classpath:mybatis/mapper/*.xml"/>
</bean>
两个必备的属性,一个是数据源,一个是映射配置文件
需要的映射文件注入:
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--因为会自动装配 SqlSessionFactory和SqlSessionTemplate 所以没有必要去指定SqlSessionFactory 或 SqlSessionTemplate 因此可省略不配置; -->
<!--但是,如果你使用了一个以上的DataSource,那么自动装配可能会失效。 这种情况下你可以使用sqlSessionFactoryBeanName或sqlSessionTemplateBeanName属性来设置正确的 bean名称来使用-->
<!--<property name="sqlSessionFactoryBeanName" ref="sqlSessionFactory"/>-->
<!--basePackage 是映射器接口文件的包路径,会扫描路径下面的所有文件注册成bean-->
<property name="basePackage" value="mybatis/mapper"/>
</bean>
Mybatis3以后也可以直接使用注解的方式来使用映射语句。之前报错的时候就是因为同时使用了映射文件和注解:
@Select(" SELECT * FROM person WHERE id = #{id}")
Person selectById(int id);
A.使用xml配置MapperScannerConfigurer,用SqlSessionFactory获取session查询:
目录:
配置文件里有三个主要的部分:
开启扫描(扫描@注解),装入配置:
<!--开启自动扫描-->
<context:component-scan base-package="mybatis,action"/>
<!--载入配置文件-->
<context:property-placeholder location="classpath:c3p0.properties"/>
配置数据源:
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="${driverClass}"/>
<property name="jdbcUrl" value="${jdbcUrl}"/>
<property name="user" value="${user}"/>
<property name="password" value="${password}"/>
<!--初始化和最大最小连接数-->
<property name="initialPoolSize" value="${initialPoolSize}"/>
<property name="maxPoolSize" value="${max_size}"/>
<property name="minPoolSize" value="${min_size}"/>
……
</bean>
注册SqlSessionFactoryBean和映射文件:
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--因为会自动装配 SqlSessionFactory 和 SqlSessionTemplate 所以没有必要去指定SqlSessionFactory或 SqlSessionTemplate 因此可省略不配置; -->
<!--但是,如果你使用了一个以上的DataSource,那么自动装配可能会失效。 这种情况下你可以使用sqlSessionFactoryBeanName或sqlSessionTemplateBeanName属性来设置正确的 bean名称来使用-->
<!--<property name="sqlSessionFactoryBeanName" ref="sqlSessionFactory"/>-->
<!--basePackage 是映射器接口文件的包路径,会扫描路径下面的所有文件注册成bean-->
<property name="basePackage" value="mybatis/mapper"/>
</bean>
<!--<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">-->
<!--<constructor-arg index="0" ref="sqlSessionFactory"/>-->
<!--</bean>-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--因为会自动装配 SqlSessionFactory 和 SqlSessionTemplate 所以没有必要去指定SqlSessionFactory或 SqlSessionTemplate 因此可省略不配置; -->
<!--但是,如果你使用了一个以上的DataSource,那么自动装配可能会失效。 这种情况下你可以使用sqlSessionFactoryBeanName或sqlSessionTemplateBeanName属性来设置正确的 bean名称来使用-->
<!--<property name="sqlSessionFactoryBeanName" ref="sqlSessionFactory"/>-->
<!--basePackage 是映射器接口文件的包路径,会扫描路径下面的所有文件注册成bean-->
<property name="basePackage" value="mybatis/mapper"/>
</bean>
测试1:使用ApplicationContext
@Controller
public class MybatisAction {
@Autowired
private PersonMapper personMapper;
org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(MybatisAction.class.getName());
@Test
public void testMybatis(){
// 获取上下文连接配置
ApplicationContext context = new ClassPathXmlApplicationContext("mybatis/springmybatis.xml");
// 获取bean
MybatisAction mybatisAction = (MybatisAction) context.getBean("mybatisAction");
// System.out.print( mybatisAction.personMapper.selectById(1));
logger.debug(mybatisAction.personMapper.selectById(1));
}
}
测试2:使用注解:
//自动化 测试运行器 打包测试,可以看到全部的测试结果
@RunWith(SpringJUnit4ClassRunner.class)
//注解方式获取xml配置
@ContextConfiguration(locations = {"classpath*:mybatis/springmybatis.xml"})
public class MybatisActionB {
static Logger logger = Logger.getLogger(MybatisAction.class.getName());
@Autowired
private PersonMapper personMapper;
@Test
public void testAction(){
// System.out.print(personMapper.selectById(1));
logger.debug(personMapper.selectById(1));
}
}
B.使用SqlSessionDaoSupport获取SqlSession查询:
可以看到SqlSessionDaoSupport继承了DaoSupport类:
里面有两个属性:SqlSession 和 boolean externalSqlSession 。还有Get Set方法,这意味着我们就可以使用它获取SqlSession。
public abstract class SqlSessionDaoSupport extends DaoSupport {
private SqlSession sqlSession;
private boolean externalSqlSession;
public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
if (!this.externalSqlSession) {
this.sqlSession = new SqlSessionTemplate(sqlSessionFactory);
}
}
public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
this.sqlSession = sqlSessionTemplate;
this.externalSqlSession = true;
public SqlSession getSqlSession() {
return this.sqlSession;
}
@Override
protected void checkDaoConfig() {
notNull(this.sqlSession, "Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required");
}
}
DaoSupport 是 InitializingBean 接口的实现类:
public abstract class DaoSupport implements InitializingBean {
protected final Log logger = LogFactory.getLog(this.getClass());
public DaoSupport() {
}
public final void afterPropertiesSet() throws IllegalArgumentException, BeanInitializationException {
this.checkDaoConfig();
try {
this.initDao();
} catch (Exception var2) {
throw new BeanInitializationException("Initialization of DAO failed", var2);
}
}
protected abstract void checkDaoConfig() throws IllegalArgumentException;
protected void initDao() throws Exception {
}
}
而InitializingBean只有一个方法: void afterPropertiesSet();
public interface InitializingBean {
void afterPropertiesSet() throws Exception;
}
DaoSupport里实现afterPropertiesSet的方法是初始化Dao: 原来只是初始化(init)方法。
……当然重点在于可以通过SqlSessionDaoSupport来获取SqlSession:
这里继承了SqlSessionDaoSupport
@Service
public class PersonService extends SqlSessionDaoSupport implements PersonMapper{
@Autowired
public void setSessionFactory(SqlSessionFactory sqlSessionFactory){
super.setSqlSessionFactory(sqlSessionFactory);
}
public Person selectById(int id) {
return this.getSqlSession().selectOne("mybatis.mapper.PersonMapper.selectById",id);
}
这样可以使用getSqlSession来查询语句,这是主要的目的
this.getSqlSession().selectOne("mybatis.mapper.PersonMapper.selectById",id);
关于selectOne()方法,之前没弄明白里面的值,看了源码之后发现其实就是是传配置
/**
* Retrieve a single row mapped from the statement key and parameter.
* @param <T> the returned object type
* @param statement Unique identifier matching the statement to use.
* @param parameter A parameter object to pass to the statement.
* @return Mapped object
*/
<T> T selectOne(String statement, Object parameter);
翻译过来: (里面的statement 就是 mapper.xml 里的 namespace)
/**
* *从语句键和参数中检索单个行。
* @param <T>返回的对象类型。
* @param语句唯一标识符匹配使用的语句。
* @param参数一个参数对象传递到语句。
* @return映射对象
* <T> T selectOne(String statement, Object parameter);
*/
测试类:
@Autowired
private PersonMapper personMapper;
@Test
public void testDaoSuport(){
logger.debug(personMapper.selectById(1));
}
·这里还没测试完,因为xml里已经配置了,所以需要整理下再测试
明天计划的事情:
学习maven
学习Spring
写完main方法再打包测试
学习测试连接池
遇到的问题:
1.映射语句重复/映射语句无参数
2.扫描文件的配置/文件头的配置
3.SqlSessionDaoSupport使用Sqlsession查询对象
4.使用注解映射语句配置的问题@select("select * from tabel")
收获:
·Mybatis的几种整合方式(注解,xml配置,通过SqlSessionDaoSupport查询(有些多余的感觉,理解错了吗))
·SqlSession的常用增删改查方法
·进一步了解xml的配置
·@注解的好处又更多了解了
评论