1.示例项目目录:
2.相关接口和映射文件之间的规则
(1) 在mapper.xml中将namespace设置为对应的mapper.java(Dao接口)的全限定名 。如:
(2) 将mapper.java接口的方法名和mapper.xml中statement的id保持一致。
(3) 将mapper.java接口的方法输入参数类型和mapper.xml中statement的parameterType保持一致
(4) 将mapper.java接口的方法输出 结果类型和mapper.xml中statement的resultType保持一致
3.Dao 接口不需要实现类
MyBatis在采用面向接口编程时,采用实体+接口+映射文件的方式。其中接口是不需要实现类的。
因为Mybatis 提供了 Mapper接口的代理对象(mybatis通过JDK的动态代理方式,在启动加载配置文件时,根据配置mapper的xml去生成Dao的实现,session.getMapper()使用了代理,当调用一次此方法,都会产生一个代理class的instance。),在执行 Mapper接口方法时,实际执行的是Mybatis的代理对象,代理对象在 invoke 方法内获取 Mapper接口类全名+方法全名 作为statement的ID,然后通过ID去Statement匹配注册的SQL,然后使用 SqlSession 执行这个 SQL。所以,这也解释了为什么Mybatis映射文件需要 namespace 和 id , 前者是类全名,后者是方法名。
4.具体示例
User类
package com.mybatisstudy.model;
public class User {
private int id;
private String name;
private String sex;
private int age;
public User() {
super();
}
public User(String name, String sex, int age) {
super();
this.name = name;
this.sex = sex;
this.age = age;
}
public User(int id, String name, String sex, int age) {
super();
this.id = id;
this.name = name;
this.sex = sex;
this.age = age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "[id:" + id + ",name:" + name + ",sex:" + sex + ",age:" + age + "]";
}
}
userMapper.xml(实体映射文件)
<?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="com.mybatisstudy.dao.IUserDao">
<select id="selectAllUser"
resultType="com.mybatisstudy.model.User">
SELECT * FROM user ;
</select>
<select id="selectUserById" parameterType="int"
resultType="com.mybatisstudy.model.User">
SELECT * FROM user where id = #{id} ;
</select>
<insert id="addUser" parameterType="com.mybatisstudy.model.User">
INSERT INTO user(id,name,sex,age) VALUES(#{id},#{name},#{sex},#{age});
</insert>
<delete id="deleteUserById" parameterType="com.mybatisstudy.model.User">
DELETE FROM user WHERE id=#{id};
</delete>
<update id="updateUser" parameterType="com.mybatisstudy.model.User">
UPDATE user SET age=#{age} ,name=#{name} WHERE id=#{id}
</update>
</mapper>
IUserDao.java(Dao 接口)
package com.mybatisstudy.dao;
import java.util.List;
import com.mybatisstudy.model.User;
public interface IUserDao {
public List<User> selectAllUser();
public User selectUserById(int id);
public int addUser(User user);
public int deleteUserById(int id);
public int updateUser(User user);
}
TestUser.java(单元测试类)
package com.mybatisstudy.test;
import static org.junit.jupiter.api.Assertions.*;
import java.util.List;
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 org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.Assert;
import com.mybatisstudy.dao.IUserDao;
import com.mybatisstudy.model.User;
class TestUser {
static SqlSessionFactory factory;
static SqlSession session;
IUserDao userDao;
@BeforeAll
static void setUpBeforeClass() throws Exception {
String resource = "mybatisconf.xml";
factory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream(resource));
session = factory.openSession();
}
@AfterAll
static void tearDownAfterClass() throws Exception {
if (session != null) {
session.close();
}
session = null;
factory = null;
}
@BeforeEach
void setUp() throws Exception {
}
@AfterEach
void tearDown() throws Exception {
}
@Test
void testSelectAllUser() {
// 采用了实体+接口+映射文件的方式,在IUserDao中并没有实现selectAllUser方法,而在映射文件中进行了实现
IUserDao userDao = session.getMapper(IUserDao.class);
List<User> users = userDao.selectAllUser();
System.out.println(users);
}
@Test
void testSelectUserById() {
IUserDao userDao = session.getMapper(IUserDao.class);
int userId = 1001;
User user = userDao.selectUserById(userId);
System.out.println(user);
}
@Test
void testAddUser() {
IUserDao userDao = session.getMapper(IUserDao.class);
User user = new User(1003, "小杰", "男", 20);
int line = userDao.addUser(user);
// 使用断言
// assertEquals 如果预期值与真实值相等,则运行success,反之Failure
Assert.assertEquals(1, line);
}
@Test
void testUpdateUser() {
IUserDao userDao = session.getMapper(IUserDao.class);
User user = new User(1003, "小明", "男", 21);
int line = userDao.updateUser(user);
Assert.assertEquals(1, line);
}
@Test
void testDeleteUserById() {
IUserDao userDao = session.getMapper(IUserDao.class);
int line = userDao.deleteUserById(1003);
Assert.assertEquals(1, line);
}
}
mybatisconf.xml(MyBatis配置文件)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 引用并使用db.properties -->
<properties resource="db.properties" />
<!-- environments:信息配置的是连接数据库的(数据源的)一些参数,如用户名,密码等,MyBatis数据库操作的session就是根据这些信息初始化的-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<!-- 数据源配置 -->
<dataSource type="POOLED">
<!-- 数据库驱动 -->
<property name="driver" value="${driver}" />
<!-- 数据库连接URL -->
<property name="url" value="${url}"/>
<!-- 数据库用户名和密码 -->
<property name="username" value="${username}" />
<property name="password" value="${password}" />
</dataSource>
</environment>
</environments>
<!-- mappers:配置的是一个个Mapper文件,这些文件来约束数据库的信息(Relationship) 和 对象(Object)的信息映射(Mapper);它负责完成对象和数据库表的映射,是ORM最具体的配置-->
<mappers>
<!-- 配置实体映射文件 -->
<mapper resource="com/mybatisstudy/dao/userMapper.xml" />
</mappers>
</configuration>
db.properties(数据库配置信息)
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatisstudy?useUnicode=true&characterEncoding=utf8
username=root
password=