可能遇到的问题:
-
idea的层级目录创建时如果直接按照xx.xx.xx创建事实上是视为同一个文件夹的名称,还是应当逐层创建,此项易造成org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: java.io.IOException: Could not find resource.且注意最好将xml目录和Dao文件保持一致。否则容易出现填错的情况,如图所示:
-
目前使用的MYSQL往往是8.0+,使用较低版本的mysql-connector-java会导致无法连接MYSQL,可以使用以下版本:
mysql mysql-connector-java 8.0.12 当然还有常见的时区等问题,建议使用以下配置:
注意xml中不能直接使用&,需要使用&代替。
-
关于映射文件配置如下:
-
配置使用LOG4J输出日志:
-
元素下面配置了一个包的别名。通常确定一个类的时候需要使用类的全限定名称,例如mybatis.simple.model.Country,在MyBatis中需要频繁的使用类的权限定名称,为了方便使用,我们配置了mybatis.simple.model包,这样配置以后,我们再使用该包下的类的时候就不用再写上包名了,直接使用类名接口,如 Country 。 -
建立SqlSession:
// 根据 mybatis-config.xml 配置的信息得到 sqlSessionFactory String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactoryBuilder factoryBuilder = new SqlSessionFactoryBuilder(); SqlSessionFactory factory = factoryBuilder.build(inputStream); SqlSession session = factory.openSession(); StudentDao studentDao = session.getMapper(StudentDao.class); List
studentList = studentDao.findAll();
现在我们根据用户id和角色的enable状态来查询用户所有的角色,定义一个接口方法(此时接口参数前未加@param注解)
public ListselectRolesByUserIdAndRoleEnabled(Long userId, Integer enabled);
这个接口方法对应的UserMapper.xml中的代码为:
然后在测试类UserMapperTest中添加测试方法:
@Test
public void testSelectRolesByUserIdAndRoleEnabled() {
// 获取SqlSession
SqlSession sqlSession = getSqlSession();
// 获取UserMapper接口
try {
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 调用selectById方法,查询id=1的用户
List roleList = userMapper.selectRolesByUserIdAndRoleEnabled(1L,1);
} catch(Exception e){
e.printStackTrace();
}finally {
// 关闭SqlSession
sqlSession.close();
}
}
右键单击测试类,在Run As选项中选择JUnit Test执行测试,测试输出日志会显示错误如下。
org.apache.ibatis.exceptions.PersistenceException: ### Error querying database. Cause: org.apache.ibatis.binding.BindingException: Parameter 'userId' not found. Available parameters are [0, 1, param1, param2]
这个错误的意思是,XML可以使用的参数只有0,1,param1,param2,没有userId。0和1,param1和param2都是MyBatis根据参数位置自定义的名字,这时如果将XML中的#{userId}改为#{0} 或者#{param1},将#{enabled}改成#{1}或者#{param2},这个方法就可以被正常执行了,但是,我们通常情况下采用这种方式来实现。
现在我们修改接口方法中的参数,添加@param注解:
public List三、Mybatis 注解方式的基本用法 @Select 注解selectRolesByUserIdAndRoleEnabled(@Param("userId")Long userId, @Param("enabled")Integer enabled);
我们现在有个接口方法的作用是根据用户id,查询用户的信息,则我们只需要在接口方法之前添加注解:
@Select({"select id,user_name userName,user_password userPassword,user_email userEmail,user_info userInfo,head_img headImg,create_time createTime from sys_user where id = #{id}"})
public SysUser selectById(Long id);
使用注解方式我们也需要考虑表字段和JavaBean属性字段的映射问题。在注解方式中,我们有三种方式来实现字段映射关系。
@Insert 注解第一种:通过SQL语句使用别名来实现,别名为JavaBean中的属性字段
上面我们使用的就是此方式。第二种:使用mapUnderscoreToCamelCase配置
在数据库中,由于大多数数据库设置不区分大小写,因此下划线方式的命名很常见,如user_name 、user_password 、user_email 。在Java中,一般都使用驼峰命名方式,如userName、userPassword、userEmail。因为数据库和Java中的这两种命名方式很常见,因此MyBatis还提供了一个全局属性mapUnderscoreToCamelCase,通过配置这个属性为true可以将以下划线方式命名的数据库列映射到Java对象的驼峰式命名属性中,这个属性默认为false,如果想要使用该配置,我们只需要在MyBatis的配置文件中增加如下配置
返回自增主键
如果我们数据库中的主键字段是自增的方式生成的,那么我们除了必须的@Insert注解外,还需要添加一个@Option注解
@Insert({"INSERT INTO sys_user (user_name, user_password,user_email, user_info,head_img, create_time)VALUES (#{userName},#{userPassword},#{userEmail},#{userInfo},#{headImg,jdbcType=BLOB},#{createTime,jdbcType=TIMESTAMP})"})
@Options(useGeneratedKeys=true,keyProperty="id")
public int insert(SysUser sysUser);
配置SQL语句时我们可以看到,最后两个字段(#{headImg和 jdbcType=BLOB},#{createTime,jdbcType=TIMESTAMP})中添加了jdbcType,这里的作用是为了防止类型错误,对于一些特殊的数据类型,需要指定具体的jdbcType值。
useGeneratedKeys设置为true后,MyBatis会使用JDBC的getGeneratedKeys方法来取出由数据库内部生成的主键。获得主键后将其赋值给keyProperty配置的id属性。当需要配置多个属性时,使用逗号隔开,这种情况下通常还需要设置keyColumn属性,按顺序指定数据库的列,这里的值会和keyProperty配置的属性一一对应。
返回非自增主键
如果我们数据库中的主键不是自增方式产生的,但是当我们插入新数据后,需要返回该条数据的主键,那么我们可以使用如下方法:
@Insert({"INSERT INTO sys_user (id,user_name, user_password,user_email,user_info, head_img, create_time)VALUES(#{id},#{userName},#{userPassword},#{userEmail},#{userInfo},#{headImg, jdbcType=BLOB},#{createTime,jdbcType=TIMESTAMP})"})
@SelectKey(statement="SELECT LAST_INSERT_ID()",
keyProperty="id",
resultType=Long.class,
before=false)
public int insert3(SysUser sysUser);
使用@SelectKey注解,以下代码是使用XML配置时的selectKey。
SELECT LAST_INSERT_ID()
注解方式和XML方式配置的属性基本相同,其中before为false时功能等同于order=“AFTER”,before=true时功能等同于order=“BEFORE”。
@Update注解和@Delete注解order属性的设置和使用的数据库有关。在MySQL数据库中,order属性设置的值是AFTER,因为当前记录的主键是在insert语句执行成功后才获取到的。而在Oracel数据库中,order属性的值要设置为BEFORE,这是因为Oracle数据库中需要先从序列获取值,然后将值作为主键插入到数据库中。
@Update注解和@Delete注解使用都很简单,不多做说明。
Mybatis-Spring 一、 依赖及快速上手注意:我们在使用MyBatis注解方式时,可以不使用Mapper.xml配置文件,也可以和Mapper.xml配合使用。不管我们采用何种方式,我们都必须在MyBatis的配置文件中添加
用来指定接口类的位置,如果同时使用Mapper.xml,那么我们的Mapper.xml文件也必须在此配置包下(Mapper.xml可以放在src/main/java下,也可以放在src/main/resources下)
使用maven:
org.mybatis mybatis-spring 2.0.6
要和Spring一起使用Mybatis需要在Spring上下文中至少定义两样东西:一个SqlSessionFactory和至少一个数据映射器类。
在 MyBatis-Spring 中,可使用 SqlSessionFactoryBean来创建 SqlSessionFactory。 要配置这个工厂 bean,只需要把下面代码放在 Spring 的 XML 配置文件中:
@Configuration
public class MyBatisConfig {
@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSource());
return factoryBean.getObject();
}
}
注意:SqlSessionFactory 需要一个 DataSource(数据源)。这可以是任意的 DataSource,只需要和配置其它 Spring 数据库连接一样配置它就可以了。
假设你定义了一个如下的 mapper 接口:
public interface UserMapper {
@Select("SELECT * FROM users WHERe id = #{userId}")
User getUser(@Param("userId") String userId);
}
那么可以通过 MapperFactoryBean 将接口加入到 Spring 中:
需要注意的是:所指定的映射器类必须是一个接口,而不是具体的实现类。在这个示例中,通过注解来指定 SQL 语句,但是也可以使用 MyBatis 映射器的 XML 配置文件。
配置好之后,你就可以像 Spring 中普通的 bean 注入方法那样,将映射器注入到你的业务或服务对象中。MapperFactoryBean 将会负责 SqlSession 的创建和关闭。 如果使用了 Spring 的事务功能,那么当事务完成时,session 将会被提交或回滚。最终任何异常都会被转换成 Spring 的 DataAccessException 异常。
使用 Java 代码来配置的方式如下:
@Configuration
public class MyBatisConfig {
@Bean
public UserMapper userMapper() throws Exception {
SqlSessionTemplate sqlSessionTemplate = new SqlSessionTemplate(sqlSessionFactory());
return sqlSessionTemplate.getMapper(UserMapper.class);
}
}
要调用 MyBatis 的数据方法,只需一行代码:
public class FooServiceImpl implements FooService {
private final UserMapper userMapper;
public FooServiceImpl(UserMapper userMapper) {
this.userMapper = userMapper;
}
public User doSomeBusinessStuff(String userId) {
return this.userMapper.getUser(userId);
}
}
二、SQLSessionFactoryBean
SqlSessionFactory 有一个唯一的必要属性:用于 JDBC 的 DataSource。这可以是任意的 DataSource 对象,它的配置方法和其它 Spring 数据库连接是一样的。
一个常用的属性是 configLocation,它用来指定 MyBatis 的 XML 配置文件路径。它在需要修改 MyBatis 的基础配置非常有用。通常,基础配置指的是
还有mapperLocations 属性接受多个资源位置。这个属性可以用来指定 MyBatis 的映射器 XML 配置文件的位置。属性的值是一个 Ant 风格的字符串,可以指定加载一个目录中的所有文件,或者从一个目录开始递归搜索所有目录。比如:
这会从类路径下加载所有在 sample.config.mappers 包和它的子包中的 MyBatis 映射器 XML 配置文件。
在容器管理事务的时候,你可能需要的一个属性是 transactionFactoryClass。请参考事务一章的相关章节。
如果你使用了多个数据库,那么需要设置 databaseIdProvider 属性:
三、事务sqlserver db2 oracle mysql
要开启 Spring 的事务处理功能,在 Spring 的配置文件中创建一个 DataSourceTransactionManager 对象:
@Configuration public class DataSourceConfig { @Bean public DataSourceTransactionManager transactionManager() { return new DataSourceTransactionManager(dataSource()); } }
传入的 DataSource 可以是任何能够与 Spring 兼容的 JDBC DataSource。包括连接池和通过 JNDI 查找获得的 DataSource。
四、 SqlSession 1. SqlSessionTemplate注意:为事务管理器指定的 DataSource 必须和用来创建 SqlSessionFactoryBean 的是同一个数据源,否则事务管理器就无法工作了。
SqlSessionTemplate 是 MyBatis-Spring 的核心。作为 SqlSession 的一个实现,这意味着可以使用它无缝代替你代码中已经在使用的 SqlSession。 SqlSessionTemplate 是线程安全的,可以被多个 DAO 或映射器所共享使用。
当调用 SQL 方法时(包括由 getMapper() 方法返回的映射器中的方法),SqlSessionTemplate 将会保证使用的 SqlSession 与当前 Spring 的事务相关。 此外,它管理 session 的生命周期,包含必要的关闭、提交或回滚操作。另外,它也负责将 MyBatis 的异常翻译成 Spring 中的 DataAccessExceptions。
可以使用 SqlSessionFactory 作为构造方法的参数来创建 SqlSessionTemplate 对象。
@Configuration
public class MyBatisConfig {
@Bean
public SqlSessionTemplate sqlSession() throws Exception {
return new SqlSessionTemplate(sqlSessionFactory());
}
}
2. SqlSessionDaoSupport
SqlSessionDaoSupport 是一个抽象的支持类,用来为你提供 SqlSession。调用 getSqlSession() 方法你会得到一个 SqlSessionTemplate,之后可以用于执行 SQL 方法,就像下面这样:
public class UserDaoImpl extends SqlSessionDaoSupport implements UserDao {
public User getUser(String userId) {
return
getSqlSession().selectOne("org.mybatis.spring.sample.mapper.UserMapper.getUser",
userId);
}
}
在这个类里面,通常更倾向于使用 MapperFactoryBean,因为它不需要额外的代码。但是,如果你需要在 DAO 中做其它非 MyBatis 的工作或需要一个非抽象的实现类,那么这个类就很有用了。
SqlSessionDaoSupport 需要通过属性设置一个 sqlSessionFactory 或 SqlSessionTemplate。如果两个属性都被设置了,那么 SqlSessionFactory 将被忽略。
假设类 UserMapperImpl 是 SqlSessionDaoSupport 的子类,可以编写如下的 Spring 配置来执行设置:



