发表于: 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">
   <!--因为会自动装配 SqlSessionFactorySqlSessionTemplate 所以没有必要去指定SqlSessionFactory  SqlSessionTemplate 因此可省略不配置;  -->
<!--但是,如果你使用了一个以上的DataSource,那么自动装配可能会失效。 这种情况下你可以使用sqlSessionFactoryBeanNamesqlSessionTemplateBeanName属性来设置正确的 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,那么自动装配可能会失效。 这种情况下你可以使用sqlSessionFactoryBeanNamesqlSessionTemplateBeanName属性来设置正确的 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,那么自动装配可能会失效。 这种情况下你可以使用sqlSessionFactoryBeanNamesqlSessionTemplateBeanName属性来设置正确的 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的配置

·@注解的好处又更多了解了







返回列表 返回列表
评论

    分享到