MyBatis框架简介
MyBatis框架可以简化数据库编程!
在使用MyBatis实现数据库编程时,只需要定义每个数据操作功能的抽象方法,并配置这个抽象方法对应的SQL语句即可!
当然,MyBatis框架还实现了数据库编程的其它细节,例如对查询结果的缓存等等。
通过MyBatis实现插入用户数据
3.1. 创建项目
创建新的项目,需要在pom.xml中添加多项依赖,首先,应该添加mybatis依赖:
<!-- Mybatis框架 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.0</version>
</dependency>
MyBatis本身是可以独立使用的,但是,推荐结合Spring框架一起使用,所以,还需要添加mybatis-spring依赖:
<!-- MyBatis整合Spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.1</version>
</dependency>
整合后,框架的底层实现需要使用到spring-jdbc的依赖:
<!-- Spring JDBC依赖,必须与其它Spring依赖使用完全相同的版本 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
注意:同一个项目中如果添加多个spring-为前缀的依赖,这些依赖必须使用相同的版本!
由于本次将使用MySQL数据库,所以,还需要添加MySQL数据库连接的mysql-connector-java依赖:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.15</version>
</dependency>
然后,还需要添加数据库连接池commons-dbcp的依赖:
<!-- 数据库连接池 -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
最后,在编程时,为了及时检测代码,还应该添加单元测试junit的依赖:
<!-- 单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>
所以,当前项目中需要添加的完整的依赖的代码是:
<dependencies>
<!-- SpringMVC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
<!-- Spring JDBC依赖,必须与其它Spring依赖使用完全相同的版本 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
<!-- Mybatis框架 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.0</version>
</dependency>
<!-- MyBatis整合Spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.1</version>
</dependency>
<!-- Thymeleaf -->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>3.0.7.RELEASE</version>
</dependency>
<!-- Thymeleaf整合Spring -->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring4</artifactId>
<version>3.0.7.RELEASE</version>
</dependency>
<!-- 连接MySQL数据库的依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.15</version>
</dependency>
<!-- 数据库连接池 -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<!-- 单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>
</dependencies>
然后,将spring.xml改名为spring-mvc.xml,将spring-mvc.xml复制得到spring-dao.xml,并删除spring-dao.xml中原有的配置信息,接下来,本项目所有的配置都将编写在spring-dao.xml文件中,而spring-mvc.xml只用于保存前续项目中的配置,供后续的参考使用。
3.2. 配置数据库连接
在src/main/resources/下创建db.properties配置文件,并在该文件中配置连接数据库的信息:
url=jdbc:mysql://localhost:3306/tedu_ums?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Chongqing
driver=com.mysql.cj.jdbc.Driver
username=root
password=root
initialSize=2
maxActive=10
接下来,就需要在spring-dao.xml中读取以上配置信息,以便于后续可以通过Spring获取这些配置的值!所以,添加配置:
<util:properties id="config" location="classpath:db.properties"/>
以上读取到的配置将应用于获取数据库连接的数据源,所以,还需要在spring-dao.xml中配置BasicDataSource:
<!-- 配置数据源 -->
<bean class="org.apache.commons.dbcp.BasicDataSource">
<!-- 以下注入属性的各节点中 -->
<!-- name的值是BasicDataSource中的属性值 -->
<!-- value的值是Spring表达式,config是以上读取配置文件的节点的id,右侧名称是db.properties中定义的属性名 -->
<property name="url" value="#{config.url}"/>
<property name="driverClassName" value="#{config.driver}"/>
<property name="username" value="#{config.username}"/>
<property name="password" value="#{config.password}"/>
<property name="initialSize" value="#{config.initialSize}"/>
<property name="maxActive" value="#{config.maxActive}"/>
</bean>
然后,执行单元测试:
BasicDataSource dataSource;
@Test
public void getConnection() throws SQLException {
// 加载Spring配置文件,获得Spring容器
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("spring-dao.xml");
// 从Spring容器中获取对象
dataSource = ac.getBean("dataSource", BasicDataSource.class);
// 测试
System.out.println(dataSource.getConnection());
// 释放资源
ac.close();
}
}
3.3. 编写抽象方法
MyBatis框架要求抽象方法都必须声明在接口中,所以,先创建cn.tedu.mybatis包,并在这个包中创建UserMapper接口:
package cn.tedu.mybatis;
public interface UserMapper {
}
为了便于处理数据,应该将用户信息相关的属性封装为一个类,所以,在cn.tedu.mybatis包下创建User类,并且根据t_user数据表的字段来设计User类中的属性:
private Integer id;
private String username;
private String password;
private Integer age;
private String phone;
private String email;
// 生成SET/GET方法,toString()方法
}
然后,需要在接口中添加“插入用户数据”的抽象方法,关于MyBatis框架使用的抽象方法的声明原则:
如果即将执行的是INSERT、UPDATE、DELETE类型的操作,则使用Integer/int作为返回值类型,表示受影响的行数,当然,如果不关心这个返回值,也可以将返回值类型声明为void,但是,并不推荐;
方法名称可以自定义;
参数列表可按需设计。
所以,在UserMapper接口中添加“插入用户数据”的抽象方法:
public interface UserMapper {
Integer addnew(User user);
}
完成后,还需要在spring-dao.xml中配置接口文件的位置,否则,MyBatis框架将不知道在哪里找接口及接口的抽象方法!(即使此前配置了组件扫描,也要做这项配置),所以,在spring-dao.xml中添加关于MapperScannerConfigurer的配置:
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 配置接口文件的位置 -->
<property name="basePackage" value="cn.tedu.mybatis" />
</bean>
3.4. 配置抽象方法对应的SQL语句
下载http://doc.canglaoshi.org/config/mybatis-mapper.zip文件,解压得到SomeMapper.xml文件。
在src/main/resources下创建mappers文件夹,并将SomeMapper.xml复制到mappers文件夹中。
这个SomeMapper.xml文件就是用于配置SQL语句的文件!该文件的顶部有相关声明:
<!DOCTYPE mapper PUBLIC "-//ibatis.apache.org//DTD Mapper 3.0//EN"
"http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd">
注意:以上声明是必须存在的,且不可修改!
该文件的根节点必须是节点,且必须配置namespace属性:
<mapper namespace="cn.tedu.mybatis.UserMapper">
</mapper>
然后,在的子级添加节点,以对应抽象方法,可以使用、、、,应该根据将要执行的SQL语句的类型来选择子级节点!
本次要执行的是INSERT类型的操作,所以,选择节点进行配置,该节点的id属性值就是对应的抽象方法的名称:
<insert id="addnew">
</insert>
在以上节点的内部,就可以开始配置SQL语句,各值使用#{}格式的占位符,占位符中的名称就是抽象方法的参数User类型中的属性名:
<insert id="addnew">
INSERT INTO t_user (
username, password, age, phone, email
) VALUES (
#{username}, #{password}, #{age}, #{phone}, #{email}
)
</insert>
然后,还需要配置SqlSessionFactoryBean类,以指定这些配置SQL语句的XML文件在哪里,及框架执行数据访问时通过哪个数据源连接到数据库,所以,在spring-dao.xml中添加:
<bean class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 配置XML文件在哪里 -->
<property name="mapperLocations" value="classpath:mappers/*.xml" />
<!-- 指定访问数据时使用的数据源 -->
<property name="dataSource" ref="dataSource" />
</bean>
最后,在Tests测试类中编写并执行单元测试:
BasicDataSource dataSource;
ClassPathXmlApplicationContext ac;
// 关于单元测试的方式,必要的4个条件:
// 1. 必须添加@Test注解
// 2. 必须使用public权限
// 3. 必须使用void作为返回值类型
// 4. 必须是空的参数列表
@Test
public void getConnection() throws SQLException {
// 从Spring容器中获取对象
dataSource = ac.getBean("dataSource", BasicDataSource.class);
// 测试
System.out.println(dataSource.getConnection());
}
@Test
public void addnew() {
// 获取MyBatis框架生成的接口的代理对象
UserMapper userMapper = ac.getBean("userMapper", UserMapper.class);
// 测试
User user = new User();
user.setUsername("mybatis");
user.setPassword("1234");
user.setAge(35);
user.setEmail("mybatis@163.com");
Integer rows = userMapper.addnew(user);
System.out.println("rows=" + rows);
}
@Before
public void doBefore() {
// 加载Spring配置文件,获得Spring容器
ac = new ClassPathXmlApplicationContext("spring-dao.xml");
}
@After
public void doAfter() {
// 释放资源
ac.close();
}
}
附:关于Invalid bound statement (not found)错误的解决方案
出现该错误,主要是因为MyBatis无法将抽象方法与配置的SQL语句对应所导致的,在查看错误时,应该检查Invalid bound statement (not found)右侧的信息,以确定是哪个抽象方法的对应关系出了问题,然后,再排查:
配置的mapperLocations属性指定了XML文件的位置,但是,XML文件并不在指定的位置;
在配置SQL语句的XML文件中,根节点的namespace属性值错误;
在配置SQL语句的XML文件中,各配置SQL语句的节点,例如节点的id属性值不是抽象方法的名字;