首先建一个maven项目
在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>com.spring3</groupId> <artifactId>spring3</artifactId> <version>1.0-SNAPSHOT</version> <properties> <spring-context.version>3.2.8.RELEASE</spring-context.version> <spring-aspects.version>3.1.4.RELEASE</spring-aspects.version> <spring-core.version>3.2.8.RELEASE</spring-core.version> <spring-aop.version>3.2.8.RELEASE</spring-aop.version> <aspectjrt.version>1.8.1</aspectjrt.version> <aspectjweaver.version>1.5.4</aspectjweaver.version> <spring-beans.version>3.2.8.RELEASE</spring-beans.version> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring-context.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>${spring-aspects.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring-core.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring-aop.version}</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>${aspectjrt.version}</version> </dependency> <dependency> <groupId>aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>${aspectjweaver.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${spring-beans.version}</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>3.1.2.RELEASE</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-expression</artifactId> <version>4.3.12.RELEASE</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.43</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.1</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.3.0</version> </dependency> <dependency> <groupId>commons-dbcp</groupId> <artifactId>commons-dbcp</artifactId> <version>1.4</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>4.3.10.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>3.1.1.RELEASE</version> </dependency> <dependency> <groupId>javax.persistence</groupId> <artifactId>persistence-api</artifactId> <version>1.0</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.25</version> </dependency> </dependencies> </project>
然后建一个实体类 如:User
package transactional.bean; import javax.persistence.*; /** * Created by 340092 on 2017/11/22. */ @Entity @Table(name = "user") public class User { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String name; private int age; public Long getId() { return id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + '}'; } }在建一个UserDaopackage transactional.dao; import transactional.bean.User; /** * Created by 340092 on 2017/11/22. */ public interface UserDao { void saveUser(User user); }然后一个 UserService :package transactional.service; import org.springframework.stereotype.Service; import transactional.bean.User; import transactional.dao.UserDao; import javax.annotation.Resource; /** * Created by 340092 on 2017/11/22. */ @Service public class UserService { @Resource UserDao userDao; public void saveUser(User user){ userDao.saveUser(user); } }加一个配置文件<?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" xmlns:tx="http://www.springframework.org/schema/tx" 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 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd "> <context:property-placeholder location="classpath:mybatis.properties"/> <context:component-scan base-package="transactional"/> <context:annotation-config /> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/test3"/> <property name="username" value="root"/> <property name="password" value="root"/> </bean> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="transactional.dao"/> </bean> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="mapperLocations" value="classpath:mapper/*.xml"/> </bean> <!-- 使用annotation定义事务 --> <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" /> <!-- 事务管理器配置, 使用jdbc事务 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> </beans>加一个Mapper文件<?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="transactional.dao.UserDao"> <insert id="saveUser" parameterType="transactional.bean.User"> INSERT INTO user(age,name)VALUES (#{age},#{name}) </insert> </mapper>编写一个测试类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 transactional.Impl.UserDaoImpl; import transactional.bean.Cat; import transactional.bean.User; import transactional.service.CatService; import transactional.service.TransactionalTest; import transactional.service.UserService; /** * Created by 340092 on 2017/11/22. */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath:springTransactional.xml"}) public class MybatisAndTransactional { @Autowired CatService catService; @Autowired UserService userService; @Autowired TransactionalTest transactionalTest; @Autowired UserDaoImpl userDao; @Test public void asdf(){ Cat cat = new Cat(); cat.setCatAge(10); cat.setName("zhandan"); catService.saveCat(cat); } @Test public void sad(){ User u = new User(); u.setName("yangwenfu"); u.setAge(24); userService.saveUser(u); } @Test public void testsj(){ User user = userDao.selectById(9L); System.out.println(user.toString()); } }如果没有问题的话就可以访问数据库了还有一种用法我看好多人这样用我也试了一下还是这个User类建一个抽象类继承SqlSessionDaoSupport 如:package transactional.util; import org.mybatis.spring.support.SqlSessionDaoSupport; import java.io.Serializable; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Created by 340092 on 2017/11/23. */ public abstract class AbstractMyBatisDAO<T, PK extends Serializable> extends SqlSessionDaoSupport{ protected static final Logger logger = LoggerFactory.getLogger(AbstractMyBatisDAO.class); protected Class<T> entityClass; protected String mapperNamespace; @SuppressWarnings("unchecked") public AbstractMyBatisDAO() { // 通过范型反射,取得在子类中定义的class.//getClass() 获得运行时子类例如本例中:class transactional.Impl.UserDaoImpl
this.entityClass = getSuperClassGenricType(getClass(),0); this.mapperNamespace = entityClass.getName();//获得全包名 } /** * @return the sqlmapNamespace */ public String getMapperNamespace() { return mapperNamespace; } public void setMapNamespace(String mapperNamespace) { this.mapperNamespace = mapperNamespace; } // 通过范型反射,取得在子类中定义的class. @SuppressWarnings("rawtypes") public Class getSuperClassGenricType(Class clazz, int index) {//获得Type实例 里面包含了泛型的信息 Type genType = clazz.getGenericSuperclass();//transactional.util.AbstractMyBatisDAO<transactional.bean.User, java.lang.Long> if (!(genType instanceof ParameterizedType)) { logger.warn("{}的父类非泛型类", clazz.getSimpleName()); return Object.class; }//获得所有泛型数组 Type[] params = ((ParameterizedType) genType).getActualTypeArguments(); if (index >= params.length || index < 0) { logger.warn("索引: {} 超出了 {} 的泛型参数长度:{}", new Object[]{index, clazz.getSimpleName(), params.length}); return Object.class; } if (!(params[index] instanceof Class)) { logger.warn("{} 在父类的泛型参数中不是真正的Class类型", clazz.getSimpleName()); return Object.class; } return (Class) params[index];//返回泛型的类 index代表哪一个泛型返回 } }定义一个类实现这个抽象方法package transactional.Impl; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Repository; import transactional.bean.User; import transactional.util.AbstractMyBatisDAO; /** * Created by 340092 on 2017/11/23. */ @Repository public class UserDaoImpl extends AbstractMyBatisDAO<User,Long> {//下面两个要有这个 不然会报Caused by: java.lang.IllegalArgumentException: Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required//因为mybatis-spring的版本号如果是1.1.0以上就要添加这个@Autowired(required = false) public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) { super.setSqlSessionFactory(sqlSessionFactory); } @Autowired(required = false) public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate){ super.setSqlSessionTemplate(sqlSessionTemplate); } public User selectById(Long id){ return this.getSqlSession().selectOne(this.getMapperNamespace()+".selectById",id); } }原因在这:1.10版本SqlSessionDaoSupport代码是这样的
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package org.mybatis.spring.support; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.support.DaoSupport; import org.springframework.util.Assert; public abstract class SqlSessionDaoSupport extends DaoSupport { private SqlSession sqlSession; private boolean externalSqlSession; public SqlSessionDaoSupport() { } @Autowired( required = false //区别在这 ) public final void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) { if(!this.externalSqlSession) { this.sqlSession = new SqlSessionTemplate(sqlSessionFactory); } } @Autowired( required = false //区别在这 ) public final void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) { this.sqlSession = sqlSessionTemplate; this.externalSqlSession = true; } public final SqlSession getSqlSession() { return this.sqlSession; } protected void checkDaoConfig() { Assert.notNull(this.sqlSession, "Property \'sqlSessionFactory\' or \'sqlSessionTemplate\' are required"); } }而之后版本是:// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package org.mybatis.spring.support; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionTemplate; import org.springframework.dao.support.DaoSupport; import org.springframework.util.Assert; public abstract class SqlSessionDaoSupport extends DaoSupport { private SqlSession sqlSession; private boolean externalSqlSession; public SqlSessionDaoSupport() { } 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; } protected void checkDaoConfig() { Assert.notNull(this.sqlSession, "Property \'sqlSessionFactory\' or \'sqlSessionTemplate\' are required"); } }当然,一般情况下,使用 @Autowired 的地方都是需要注入 Bean 的,使用了自动注入而又允许不注入的情况一般仅会在开发期或测试期碰到(如为了快速启动 Spring 容器,仅引入一些模块的 Spring 配置文件),所以 @Autowired(required = false) 会很少用到。Spring Autowired(required = false) 说明
当候选 Bean 数目不为 1 时的应对方法当不能确定 Spring 容器中一定拥有某个类的 Bean 时,可以在需要自动注入该类 Bean 的地方可以使用 @Autowired(required = false),这等于告诉 Spring:在找不到匹配 Bean 时也不报错
在默认情况下使用 @Autowired 注释进行自动注入时,Spring 容器中匹配的候选 Bean 数目必须有且仅有一个。当找不到一个匹配的 Bean 时,Spring 容器将抛出 BeanCreationException 异常,并指出必须至少拥有一个匹配的 Bean
和找不到一个类型匹配 Bean 相反的一个错误是:如果 Spring 容器中拥有多个候选 Bean,Spring 容器在启动时也会抛出 BeanCreationException 异常Spring 允许我们通过 @Qualifier 注释指定注入 Bean 的名称,这样歧义就消除了
@Autowired 和 @Qualifier 结合使用时,自动注入的策略就从 byType 转变成 byName 了。@Autowired 可以对成员变量、方法以及构造函数进行注释,而 @Qualifier 的标注对象是成员变量、方法入参、构造函数入参。正是由于注释对象的不同,所以 Spring 不将 @Autowired 和 @Qualifier 统一成一个注释类
然后是Mapper文件<?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="transactional.bean.User"> <select id="selectById" resultType="transactional.bean.User"> SELECT * FROM user WHERE id =#{id} </select> </mapper>注意:这里的namespace和之前的不同 原因在这this.getSqlSession().selectOne(this.getMapperNamespace()+".selectById",id)最后用测试类测试一下没有问题