在学习MyBatis之前,需要先了解一下Spring对JDBC的支持
示例工程:mybatis-demo01
该工程主要描述的是Spring框架对JDBC的支持,并编写相关的实现类
在idea中新建一个普通的maven项目,项目的目录结构如下
└── mybatis-demo1
├── docs
│ └── db.sql
├── pom.xml
├── README.md
├── src
│ ├── main
│ │ ├── java
│ │ │ └── com
│ │ └── resources
│ │ └── config
│ └── test
│ └── java
│ └── com
a)resources/config 目录下存放的是配置文件,包括spring的核心配置文件mybatis-01.xml和数据库配置文件db.properties
b)项目的docs目录下,存放了当前工程示例中的建表脚本db.sql
我们在pom.xml中引入项目中所使用到的外部jar包
<properties>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
<maven.compiler.source>1.8maven.compiler.source>
<maven.compiler.target>1.8maven.compiler.target>
<spring.version>4.3.26.RELEASEspring.version>
<spring.data.jpa.version>1.3.5.RELEASEspring.data.jpa.version>
properties>
<dependencies>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.10version>
<scope>testscope>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-coreartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-beansartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-jdbcartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframework.datagroupId>
<artifactId>spring-data-jpaartifactId>
<version>${spring.data.jpa.version}version>
dependency>
<dependency>
<groupId>commons-dbcpgroupId>
<artifactId>commons-dbcpartifactId>
<version>1.2.2version>
dependency>
<dependency>
<groupId>commons-collectionsgroupId>
<artifactId>commons-collectionsartifactId>
<version>3.1version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.30version>
dependency>
dependencies>
我们使用mysql数据库,这里我们为了演示原理,id没有设置为自增,而是手工设置主键,建表脚本的内容如下:
-- mysql的建表脚本
create table t_student_info(
id varchar(20) not null comment '主键',
name varchar(50) default ' ' comment '姓名',
age decimal(3) default 20 comment '年龄',
sex char(1) default 'M' comment '性别 M-男,W-女',
phone varchar(20) comment '手机号',
email varchar(30) comment '电子邮箱',
rsv1 varchar(100) comment '备注字段',
primary key (id)
) engine=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8 COMMENT '学生信息表';
有两种方式来编写Dao组件,分别如下:
1、Dao继承JdbcDaoSupport,通过getJdbcTemplate() 方法获取JdbcTemplate对象,需要在DAO实现类中注入一个DataSource对象来实现JDBCTemplate的实例化
2、Dao不继承JdbcDaoSupport,在Spring容器中配置一个JdbcTemplate的bean,然后注入给Dao实现类
我们编写公共接口
StudentInfoDao
,并定义相关的CRUD方法供子类实现,接口的方法列表如下:
StudentInfoDao
package com.iambest.study.dao;
import com.iambest.study.entity.StudentInfoDo;
import java.util.List;
/**
* 公共接口
*/
public interface StudentInfoDao {
void save(StudentInfoDo studentInfoDo);
void update(StudentInfoDo studentInfoDo);
void deleteById(String id);
StudentInfoDo findById(String id);
List<StudentInfoDo> findAll();
}
我们的实现类需要继承JdbcDaoSupport类,同时实现StudentInfoDao接口,并实现所有的CRUD方法
JdbcStudentInfoDao
package com.iambest.study.dao;
import com.iambest.study.entity.StudentInfoDo;
import com.iambest.study.mapper.StudentInfoMapper;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import java.util.List;
/**
* 继承自jdbcDaoSupport
*/
public class JdbcStudentInfoDao extends JdbcDaoSupport implements StudentInfoDao {
@Override
public void save(StudentInfoDo studentInfoDo) {
String sql = "insert into t_student_info (id,name,age,sex,phone,email,rsv1) values (?,?,?,?,?,?,?)";
Object[] params = {studentInfoDo.getId(), studentInfoDo.getName(), studentInfoDo.getAge(), studentInfoDo.getSex(), studentInfoDo.getPhone(), studentInfoDo.getEmail(), studentInfoDo.getRsv1()};
super.getJdbcTemplate().update(sql, params);
}
@Override
public void update(StudentInfoDo studentInfoDo) {
String sql = "update t_student_info set name=?,age=?,sex=?,phone=?,email=?,rsv1=? where id=?";
Object[] params = {studentInfoDo.getName(), studentInfoDo.getAge(), studentInfoDo.getSex(), studentInfoDo.getPhone(), studentInfoDo.getEmail(), studentInfoDo.getRsv1(), studentInfoDo.getId()};
super.getJdbcTemplate().update(sql, params);
}
@Override
public void deleteById(String id) {
String sql = "delete from t_student_info where id=?";
Object[] params = {id};
super.getJdbcTemplate().update(sql,params);
}
@Override
public StudentInfoDo findById(String id) {
String sql = "select * from t_student_info where id=?";
Object[] params = {id};
RowMapper<StudentInfoDo> mapper = new StudentInfoMapper();
StudentInfoDo studentInfoDo = super.getJdbcTemplate().queryForObject(sql,params,mapper);
return studentInfoDo;
}
@Override
public List<StudentInfoDo> findAll() {
String sql = "select * from t_student_info";
RowMapper<StudentInfoDo> mapper = new StudentInfoMapper();
Object[] params = new Object[]{};
List<StudentInfoDo> list = super.getJdbcTemplate().query(sql,params,mapper);
return list;
}
}
1)在Spring对JDBC的支持中,由于我们需要将查询出的字段映射成实体类,这里需要使用到自定义的RowMapper
2)编写一个自定的类StudentInfoMapper继承自RowMapper,并重写mapRow(ResultSet rs,int rowIndex)方法即可
StudentInfoMapper
package com.iambest.study.mapper;
import com.iambest.study.entity.StudentInfoDo;
import org.springframework.jdbc.core.RowMapper;
import java.sql.ResultSet;
import java.sql.SQLException;
public class StudentInfoMapper implements RowMapper<StudentInfoDo> {
@Override
public StudentInfoDo mapRow(ResultSet resultSet, int i) throws SQLException {
StudentInfoDo studentInfoDo = new StudentInfoDo();
studentInfoDo.setId(resultSet.getString("ID"));
studentInfoDo.setName(resultSet.getString("NAME"));
studentInfoDo.setPhone(resultSet.getString("PHONE"));
studentInfoDo.setAge(resultSet.getInt("AGE"));
studentInfoDo.setEmail(resultSet.getString("EMAIL"));
studentInfoDo.setSex(resultSet.getString("SEX"));
studentInfoDo.setRsv1(resultSet.getString("RSV1"));
return studentInfoDo;
}
}
实体类,映射数据库的字段,这里我们手工编写对应的实体类对象
StudentInfoDo
StudentInfoDo
package com.iambest.study.entity;
import java.util.Objects;
/**
* @author Jack_David
*
*/
public class StudentInfoDo {
private String id;
private String name;
private Integer age;
private String sex;
private String phone;
private String email;
private String rsv1;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getRsv1() {
return rsv1;
}
public void setRsv1(String rsv1) {
this.rsv1 = rsv1;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
StudentInfoDo that = (StudentInfoDo) o;
return Objects.equals(id, that.id);
}
@Override
public int hashCode() {
return Objects.hash(id);
}
@Override
public String toString() {
return "StudentInfoDo{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
", phone='" + phone + '\'' +
", email='" + email + '\'' +
", rsv1='" + rsv1 + '\'' +
'}';
}
}
数据库的配置文件db.properties,我们放在resources/config目录下面,主要配置数据库的相关信息
db.properties
#mysql数据库
db.url=jdbc:mysql://127.0.0.1:3306/david?useUnicode=true&characterEncoding=utf8
db.driver=com.mysql.jdbc.Driver
db.username=root
db.password=123456
我们编写Spring的核心配置文件mybatis-01.xml
mybatis-01.xml
<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:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd">
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:config/db.properties"/>
bean>
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${db.driver}" />
<property name="url" value="${db.url}"/>
<property name="username" value="${db.username}"/>
<property name="password" value="${db.password}"/>
bean>
<bean id="jdbcStudentInfoDao" class="com.iambest.study.dao.JdbcStudentInfoDao">
<property name="dataSource" ref="myDataSource"/>
bean>
beans>
我们这里使用junit进行单元测试,编写相关的程序测试我们的程序
TestStudentDao
@Test
public void testDao() throws Exception{
String config = "config/mybatis-01.xml";
AbstractApplicationContext context = new ClassPathXmlApplicationContext(config);
StudentInfoDao studentInfoDao = context.getBean("jdbcStudentInfoDao", JdbcStudentInfoDao.class);
StudentInfoDo student = new StudentInfoDo();
student.setId("10001");
student.setName("张三");
student.setAge(20);
student.setPhone("13988887777");
student.setSex("M");
student.setEmail("[email protected]");
student.setRsv1("备注");
studentInfoDao.save(student);
}
1)通过运行单元测试,然后使用数据库连接工具查询我们的数据库表,看看是否将数据插入到数据库
2)单元测试成功
3)使用连接工具查询数据库的数据,如下图:
4)表示我们的程序验证成功
公共接口,自定义RowMapper,实体类,数据库配置我们直接使用上面的即可,不用重新写,我们这里编写实现类
JdbcStudentInfoSingleDao
package com.iambest.study.dao;
import com.iambest.study.entity.StudentInfoDo;
import com.iambest.study.mapper.StudentInfoMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import java.util.List;
/**
* 不继承JdbcDaoSupport
*
* @author Jack_David
*
*
*/
public class JdbcStudentInfoSingleDao implements StudentInfoDao {
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate){
this.jdbcTemplate = jdbcTemplate;
}
@Override
public void save(StudentInfoDo studentInfoDo) {
String sql = "insert into t_student_info (id,name,age,sex,phone,email,rsv1) values (?,?,?,?,?,?,?)";
Object[] params = {studentInfoDo.getId(), studentInfoDo.getName(), studentInfoDo.getAge(), studentInfoDo.getSex(), studentInfoDo.getPhone(), studentInfoDo.getEmail(), studentInfoDo.getRsv1()};
this.jdbcTemplate.update(sql, params);
}
@Override
public void update(StudentInfoDo studentInfoDo) {
String sql = "update t_student_info set name=?,age=?,sex=?,phone=?,email=?,rsv1=? where id=?";
Object[] params = {studentInfoDo.getName(), studentInfoDo.getAge(), studentInfoDo.getSex(), studentInfoDo.getPhone(), studentInfoDo.getEmail(), studentInfoDo.getRsv1(), studentInfoDo.getId()};
this.jdbcTemplate.update(sql, params);
}
@Override
public void deleteById(String id) {
String sql = "delete from t_student_info where id=?";
Object[] params = {id};
this.jdbcTemplate.update(sql,params);
}
@Override
public StudentInfoDo findById(String id) {
String sql = "select * from t_student_info where id=?";
Object[] params = {id};
RowMapper<StudentInfoDo> mapper = new StudentInfoMapper();
StudentInfoDo studentInfoDo = this.jdbcTemplate.queryForObject(sql,params,mapper);
return studentInfoDo;
}
@Override
public List<StudentInfoDo> findAll() {
String sql = "select * from t_student_info";
RowMapper<StudentInfoDo> mapper = new StudentInfoMapper();
Object[] params = new Object[]{};
List<StudentInfoDo> list = this.jdbcTemplate.query(sql,params,mapper);
return list;
}
}
1)不继承JdbcDaoSupport
2)在Spring的配置文件中单独声明JdbcTemplate对象
3)在编写的Dao中单独声明一个JdbcTemplate作为属性,同时在Spring中将该属性指向第2步中声明的JdbcTemplate对象引用
mybatis-01.xml
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="myDataSource"/>
bean>
<bean id="jdbcStudentInfoSingleDao" class="com.iambest.study.dao.JdbcStudentInfoSingleDao">
<property name="jdbcTemplate" ref="jdbcTemplate"/>
bean>
编写单元测试用例,测试我们的配置,在
TestStudentDao
类中增加一个测试方法testDaoSingle
如下:
TestStudentDao
@Test
public void testDaoSingle() throws Exception {
String config = "config/mybatis-01.xml";
AbstractApplicationContext context = new ClassPathXmlApplicationContext(config);
StudentInfoDao studentInfoDao = context.getBean("jdbcStudentInfoSingleDao", JdbcStudentInfoSingleDao.class);
StudentInfoDo studentInfoDo = studentInfoDao.findById("10001");
System.out.println(studentInfoDo);
}
运行单元测试用例,并查看控制台的输出,如下图表示成功:
这里的路径从src/main下开始
├── java
│ └── com
│ └── iambest
│ └── study
│ ├── dao
│ │ ├── JdbcStudentInfoDao.java
│ │ ├── JdbcStudentInfoSingleDao.java
│ │ └── StudentInfoDao.java
│ ├── entity
│ │ └── StudentInfoDo.java
│ ├── mapper
│ └── StudentInfoMapper.java
└── resources
└── config
├── db.properties
└── mybatis-01.xml
这里的路径从src/test/java下开始
└── com
└── iambest
└── study
└── test
└── TestStudentDao.java