1.0 使用 Dao 的实现类,操作数据库
1.0.1 Dao 开发
(0)定义接口StudentDao 及创建接口的映射文件StudentDao .xm
package com.zep.dao;import com.zep.domain.Student;import java.util.List;public interface StudentDao {List<Student> selectStudents();int insertStudent(Student student);int updateStudent(Student student);int deleteStudent(int id);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zep.dao.StudentDao"><select id="selectStudents" resultType="com.zep.domain.Student">select * from student order by id;</select><insert id="insertStudent">insert into student values(#{id},#{name},#{email},#{age})</insert><update id="updateStudent">update student set age = #{age} where id=#{id}</update><delete id="deleteStudent">delete from student where id=#{studentId}</delete>
</mapper>
(1) 创建 Dao 接口实现类
public class StudentDaoImpl implements StudentDao
(2) 实现接口中 select 方法
@Overridepublic List<Student> selectStudents() {// 1.获取SqlSession对象SqlSession sqlSession = MybatisUtils.getSqlSession();String sqlId = "com.zep.dao.StudentDao.selectStudents";// 2.执行sql语句,使用SqlSession类的方法List<Student> students = sqlSession.selectList(sqlId);/*for (Student student : students) {System.out.println(student);}*/// 3.关闭sqlSession.close();return students;}
测试查询操作:
MyBatisTest 类中创建 StudentDaoImpl 对象
public class TestMybatis {@Testpublic void testSelectStudents() {StudentDaoImpl dao = new StudentDaoImpl();List<Student> students = dao.selectStudents();for (Student student : students) {System.out.println(student);}}
}
(3) 实现接口中 insert 方法
@Overridepublic int insertStudent(Student student) {// 1.获取SqlSession对象SqlSession sqlSession = MybatisUtils.getSqlSession();String sqlId = "com.zep.dao.StudentDao.insertStudent";// 2.执行sql语句,使用SqlSession类的方法int nums = sqlSession.insert(sqlId,student);// 3.提交事务sqlSession.commit();// 4.关闭sqlSession.close();return nums;}
测试 insert
@Testpublic void testInsertStudent() {StudentDaoImpl dao = new StudentDaoImpl();Student student = new Student();student.setId(1003);student.setName("zep");student.setEmail("zep@qq.com");student.setAge(22);int nums = dao.insertStudent(student);System.out.println("添加对象的数量:" + nums);}
(4) 实现接口中 update 方法
@Override
public int updateStudent(Student student) {SqlSession session = MybatisUtils.getSqlSession();int nums = session.update("com.zep.dao.StudentDao.updateStudent",student);session.commit();session.close();return nums;}
测试 update
@Test
public void testUpdateStudent() {StudentDaoImpl dao = new StudentDaoImpl();Student student = new Student();student.setId(1004);student.setAge(222);int nums = dao.updateStudent(student);System.out.println("使用Dao修改数据:" + nums);}
(5) 实现接口中 delete 方法
@Override
public int deleteStudent(int id) {SqlSession session = MybatisUtils.getSqlSession();int nums = session.delete("com.zep.dao.StudentDao.deleteStudent",id);session.commit();session.close();return nums;}
测试 delete
@Testpublic void testDeleteStudent() {StudentDaoImpl dao = new StudentDaoImpl();int nums = dao.deleteStudent(1005);System.out.println("使用Dao删除的数据:" + nums);}
项目完整代码如下:
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.zep</groupId><artifactId>ch02-mybatis-dao</artifactId><version>1.0-SNAPSHOT</version><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target></properties><dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.11</version><scope>test</scope></dependency><!--mybatis依赖--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.1</version></dependency><!--mysql驱动--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.9</version></dependency></dependencies><build><resources><resource><directory>src/main/java</directory><!--所在的目录--><includes><!--包括目录下的.properties,.xml 文件都会扫描到--><include>**/*.properties</include><include>**/*.xml</include></includes><filtering>false</filtering></resource></resources><plugins><plugin><artifactId>maven-compiler-plugin</artifactId><version>3.1</version><configuration><source>1.8</source><target>1.8</target></configuration></plugin></plugins></build></project>
Student .java:
package com.zep.domain;
// 推荐和表名一样,容易记忆
public class Student {// 定义属性,目前要求是 属性名和列名保持一致private Integer id;private String name;private String email;private Integer age;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getEmail() {return email;}public void setEmail(String email) {this.email = email;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}@Overridepublic String toString() {return "Student{" +"id=" + id +", name='" + name + '\'' +", email='" + email + '\'' +", age=" + age +'}';}
}
mybatis.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><!--mybatis.xml 文件加入日志配置,可以在控制台输出执行的 sql 语句和参数--><settings><setting name="logImpl" value="STDOUT_LOGGING"/></settings><environments default="mysql"><environment id="mysql"><transactionManager type="JDBC"/><dataSource type="POOLED"><!--数据库的驱动类名--><property name="driver" value="com.mysql.jdbc.Driver"/><!--连接数据库的url字符串--><property name="url" value="jdbc:mysql://localhost:3306/ssm"/><!--访问数据库的用户名--><property name="username" value="root"/><!--密码--><property name="password" value="root"/></dataSource></environment></environments><mappers><mapper resource="com/zep/dao/StudentDao.xml"/></mappers>
</configuration>
MybatisUtils .java:
package com.zep.utils;import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;import java.io.IOException;
import java.io.InputStream;public class MybatisUtils {private static SqlSessionFactory factory = null;/*静态代码块:执行优先级高于非静态的初始化块,它会在类初始化的时候执行一次,执行完成便销毁*///使用 静态块 创建一次 SqlSessionFactorystatic {String config = "mybatis.xml"; //需要和你的项目中的文件名一样try {//读取配置文件InputStream in = Resources.getResourceAsStream(config);//创建SqlSessionFactory对象,使用SqlSessionFactoryBuilderfactory = new SqlSessionFactoryBuilder().build(in);} catch (IOException e) {e.printStackTrace();}}// 获取SqlSession对象的方法public static SqlSession getSqlSession() {SqlSession sqlSession = null;if (factory != null) {sqlSession = factory.openSession(); // 非自动提交事务}return sqlSession;}
}
StudentDao .java:
package com.zep.dao;import com.zep.domain.Student;import java.util.List;public interface StudentDao {List<Student> selectStudents();int insertStudent(Student student);int updateStudent(Student student);int deleteStudent(int id);
}
StudentDao.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zep.dao.StudentDao"><select id="selectStudents" resultType="com.zep.domain.Student">select * from student order by id;</select><insert id="insertStudent">insert into student values(#{id},#{name},#{email},#{age})</insert><update id="updateStudent">update student set age = #{age} where id=#{id}</update><delete id="deleteStudent">delete from student where id=#{studentId}</delete>
</mapper>
StudentDaoImpl .java:
package com.zep.dao.Impl;import com.zep.dao.StudentDao;
import com.zep.domain.Student;
import com.zep.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;import java.util.List;public class StudentDaoImpl implements StudentDao {@Overridepublic List<Student> selectStudents() {// 1.获取SqlSession对象SqlSession sqlSession = MybatisUtils.getSqlSession();String sqlId = "com.zep.dao.StudentDao.selectStudents";// 2.执行sql语句,使用SqlSession类的方法List<Student> students = sqlSession.selectList(sqlId);/*for (Student student : students) {System.out.println(student);}*/// 3.关闭sqlSession.close();return students;}@Overridepublic int insertStudent(Student student) {// 1.获取SqlSession对象SqlSession sqlSession = MybatisUtils.getSqlSession();String sqlId = "com.zep.dao.StudentDao.insertStudent";// 2.执行sql语句,使用SqlSession类的方法int nums = sqlSession.insert(sqlId,student);// 3.提交事务sqlSession.commit();// 4.关闭sqlSession.close();return nums;}public int updateStudent(Student student) {SqlSession session = MybatisUtils.getSqlSession();int nums = session.update("com.zep.dao.StudentDao.updateStudent",student);session.commit();session.close();return nums;}@Overridepublic int deleteStudent(int id) {SqlSession session = MybatisUtils.getSqlSession();int nums = session.delete("com.zep.dao.StudentDao.deleteStudent",id);session.commit();session.close();return nums;}
}
TestMybatis .java:
package com.zep;import com.zep.dao.Impl.StudentDaoImpl;
import com.zep.domain.Student;
import org.junit.Test;import java.util.List;public class TestMybatis {@Testpublic void testSelectStudents() {//com.zep.dao.StudentDaoStudentDaoImpl dao = new StudentDaoImpl();/*** 调用List<Student> students = dao.selectStudents();* 1.dao对象,类型是StudentDao,可以获取到它的全限定类名为:com.zep.dao.StudentDao* 这个全限定名称和StudentDao.xml文件中mapper的namespace的值是一样的** 2.方法名称,selectStudents,这个方法就是StudentDao.xml文件中mapper标签下的子标签中id的值selectStudents** 3.通过dao中方法的返回值也可以确定Mybatis要调用的SqlSession的方法* 如果返回值是List,调用的是SqlSession.selectList()方法。* 如果返回值是int,或者是非List的,看mapper文件中的标签是<insert>,<update>* 就会调用SqlSession的insert(),update()等方法** mybatis的动态代理:mybatis根据dao的方法调用,获取执行sql语句的信息。* mybatis根据你的dao接口,创建出一个dao接口的实现类,并创建这个类的对象来完成* SqlSession调用方法,访问数据库。*/List<Student> students = dao.selectStudents();for (Student student : students) {System.out.println(student);}}@Testpublic void testInsertStudent() {StudentDaoImpl dao = new StudentDaoImpl();Student student = new Student();student.setId(1005);student.setName("zep");student.setEmail("zep@qq.com");student.setAge(22);int nums = dao.insertStudent(student);System.out.println("添加对象的数量:" + nums);}@Testpublic void testUpdateStudent() {StudentDaoImpl dao = new StudentDaoImpl();Student student = new Student();student.setId(1004);student.setAge(222);int nums = dao.updateStudent(student);System.out.println("使用Dao修改数据:" + nums);}@Testpublic void testDeleteStudent() {StudentDaoImpl dao = new StudentDaoImpl();int nums = dao.deleteStudent(1005);System.out.println("使用Dao删除的数据:" + nums);}}
1.0.2 传统 Dao 开发方式的分析
在前面例子中自定义 Dao 接口实现类时发现一个问题:Dao 的实现类其实并没有干什么实质性的工作,它仅仅就是通过 SqlSession 的相关 API 定位到映射文件 mapper (StudentDao.xml)中相应 id 的 SQL 语句,真正对 DB 进行操作的工作其实是由框架通过 mapper 中的 SQL 完成的。
所以,MyBatis 框架就抛开了 Dao 的实现类,直接定位到映射文件 mapper 中的相应 SQL 语句,对DB 进行操作。这种对 Dao 的实现方式称为 Mapper 的动态代理方式。
Mapper 动态代理
方式无需程序员实现 Dao 接口,不需要我们自己编写Dao接口的实现类。接口是由 MyBatis 结合映射文件自动生成的动态代理实现的