初学,记录自己学习整合两个框架的过程,里面也有很多踩过的坑,也有没有解决的问题,先记录下来。等待解决。
废话不多说,直接开始了。先上pom.xml配置文件。
This is my pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>Sping_Mybatis</groupId>
<artifactId>spring_mybatis_test</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
<dependency><!-- spring对测试框架的简单封装功能 -->
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.2.0.RELEASE</version>
<scope>test</scope>
</dependency>
<!-- 数据源 -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.0.8</version>
</dependency>
<!-- Mybatis3.4.1 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.1</version>
</dependency>
<!-- spring整合mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
<!-- Spring-4.2.0 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>4.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>4.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.8</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
</project>
贴上一张项目目录的图
再来看mybatisConfig.xml的配置
数据源在spring的配置文件里,同时spring文件里配置了自动扫描Mapper。故在此不用再次编写<mappers>中的内容
<?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="logImpl" value="LOG4J"/>
</settings>
<typeAliases>
<typeAlias type="com.lpp.test.entity.Car" alias="car"/>
</typeAliases>
<!--<mappers>
<mapper url="config/sqlMapper/CarMapper.xml"/>
</mappers>-->
</configuration>
此时再来看spring_mybatis.xml的配置,在这里面有个问题暂时还未解决。把jdbc.properties放在resource目录下之后,在spring配置中引入失败。在配置数据源时候,变量失效,暂时没有解决是什么问题,先放在这里吧。等待以后回过头解决。配置的很简单。解决方法在一篇博客中找到了,具体原因和解决方案放在最下边。
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
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.xsd">
<context:component-scan base-package="com.lpp.test"/>
<!--<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:jdbc.properties" />
</bean>-->
<!--配置数据源-->
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"
p:driverClassName="com.mysql.jdbc.Driver"
p:url="jdbc:mysql://localhost:3306/test"
p:username="root"
p:password=""
/><!--${driverClasss}${jdbcUrl}${username}com.mysql.jdbc.Driver-->
<bean id="sqlSessionFactory"
class="org.mybatis.spring.SqlSessionFactoryBean"
p:dataSource-ref="dataSource"
p:configLocation="classpath:config/mybatisConfig.xml"
p:mapperLocations="classpath:config/sqlMapper/*.xml"/>
<!--这里使用spring提供的SQLSessionTemplate-->
<bean class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg ref="sqlSessionFactory"/>
</bean>
<!-- 扫描直接使用mapper接口类操作dao,并直接纳入IOC容器管理 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"
p:sqlSessionFactory-ref="sqlSessionFactory"
p:basePackage="com.lpp.test.dao">
</bean>
</beans>
接下来是Mapper.xml的配置,三种配置效果差不多是一样的,写法上不太相同,跟carMapper接口对比来看就知道是三种方式。
<?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.lpp.test.dao.carMapper">
<select id="findCarbyId" parameterType="int" resultType="Car">
SELECT id,car_name AS carName,maxSpeed FROM t_car WHERE id = #{id}
</select>
<select id="findCarbyIdAndName" resultType="Car">
SELECT * FROM t_car WHERE id = #{id} AND car_name = #{car_name};
</select>
<select id="findCarbyIdAndSpeed" resultType="Car">
SELECT * FROM t_car WHERE id = #{id} AND maxSpeed = #{maxSpeed};
</select>
</mapper>
carMapper接口
package com.lpp.test.dao;
import com.lpp.test.entity.Car;
import org.apache.ibatis.annotations.Param;
/**
* Created with IntelliJ IDEA.
* Description:
* User: lpp
* Date: 2018-04-17
* Time: 19:44
*/
public interface carMapper {
public Car findCarbyId(int id);
public Car findCarbyIdAndName(@Param("id") int id, @Param("car_name") String car_name);
public Car findCarbyIdAndSpeed(Car car);
}
贴上log4j.properties的配置
# Global logging configuration\uff0c\u5efa\u8bae\u5f00\u53d1\u73af\u5883\u4e2d\u8981\u7528debug
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
entity下的实体 car.java
package com.lpp.test.entity;
/**
* Created with IntelliJ IDEA.
* Description:
* User: lpp
* Date: 2018-04-16
* Time: 11:06
*/
public class Car {
int id;
String carName;
int maxSpeed;
public Car() {
}
public Car(int id, String carName, int maxSpeed) {
this.id = id;
this.carName = carName;
this.maxSpeed = maxSpeed;
}
public int getId() {
return id;
}
public String getCarName() {
return carName;
}
public int getMaxSpeed() {
return maxSpeed;
}
public void setId(int id) {
this.id = id;
}
public void setName(String car_name) {
this.carName = carName;
}
public void setMaxSpeed(int maxSpeed) {
this.maxSpeed = maxSpeed;
}
@Override
public String toString() {
return "Car{" +
"id=" + id +
", name='" + carName + '\'' +
", maxSpeed=" + maxSpeed +
'}';
}
}
最后是测试方法,我创建了一个测试方法和一个主方法测试,代码分别如下。
test方法
package com.lpp.test.dao;
import com.lpp.test.entity.Car;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static org.junit.Assert.*;
/**
* Created with IntelliJ IDEA.
* Description:
* User: lpp
* Date: 2018-04-27
* Time: 17:36
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:config/spring-mybatis.xml")
public class carMapperTest {
@Autowired
carMapper carMapper;
@Test
public void findCarbyIdAndName() {
Car car = carMapper.findCarbyIdAndName(1,"aodi");
System.out.println(car);
}
}
主方法
package com.lpp.test.main;
import com.lpp.test.dao.carMapper;
import com.lpp.test.entity.Car;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Created with IntelliJ IDEA.
* Description:
* User: lpp
* Date: 2018-04-25
* Time: 17:44
*/
public class testMain {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("config/spring-mybatis.xml");
carMapper carMapper = ctx.getBean(com.lpp.test.dao.carMapper.class);
Car car = null;
car = carMapper.findCarbyId(1);
System.out.println(car.toString());
}
}
两种测试方法结果是相同的,调用了不同的查询函数。以上就是我做整合的步骤,初次尝试,难免有些问题,希望能让大家收获一些东西。
附:引入jdbc属性文件之后报错,Cannot load JDBC driver class ${jdbc.driverClassName}
引起原因:在spring里使用org.mybatis.spring.mapper.MapperScannerConfigurer 进行自动扫描的时候,设置了sqlSessionFactory 的话,可能会导致PropertyPlaceholderConfigurer失效,也就是用${jdbc.username}这样之类的表达式,将无法获取到properties文件里的内容。
导致这一原因是因为,MapperScannerConigurer实际是在解析加载bean定义阶段的,这个时候要是设置sqlSessionFactory的话,会导致提前初始化一些类,这个时候,PropertyPlaceholderConfigurer还没来得及替换定义中的变量,导致把表达式当作字符串复制了。
解决思路
1. 如果不设置sqlSessionFactory 属性的话,就必须要保证sessionFactory在spring中名称一定要是sqlSessionFactory ,否则就无法自动注入。
2. 直接定义 MapperFactoryBean
3. 放弃自动代理接口方式。
我理解的解决方案:
单数据源下删除下列属性
<property name="sqlSessionTemplate" value="sqlSessionFactory" />或者default-autowire="byName"
多数据源下改用sqlSessionFactoryBeanName。多数据源解决方案暂时不太理解,后续继续学习
附上gitee地址:https://gitee.com/LL7_s/personal_test_code_sorting/tree/master/spring_mybatis_test