在前面章节,我们在自定义持久层框架当中,实现了查询方法,本章节对增、删、改方法进行实现,首先先来说说实现增、删、改方法的基本思路
1、在Excutor接口中增加update方法,因为之前写的都是查询方法,有针对结果集的封装,而增删改的操作,没有前面繁琐的结果集封装,只需要返回一个简单的执行操作影响的行数常量就行,所以单独提取一个update方法进行处理
2、在SqlSession接口中增加delete方法和update两个方法,因为其实不论是添加、删除或是更新,其实底层执行的都是update方法
3、对SqlSession中getMapper方法的改造,之前实现查询方法的时候,只是针对返回结果集是否进行了泛型参数化进行了判断,如果是则说明当前返回对象是一个集合,则调用selectList方法,否则就调用selectOne方法,但是在返回的结果集当中如果返回的是一个未进行泛型参数化的时候还存在是insert、update、delete的情况,所以还要在否则条件中进行更进一步的判断,具体的判断方法就是通过statementId在MappedStatement中获取到对应执行的SQL语句,并对SQL语句进行一个toLowerCase转换(避免SQL语句因为大小写差异,因为有时候我们编写的习惯不同,可能存在SQL语句编写大小写不统一的情况),然后再通过SQL语句是以delete、select或都其它开头,调用对应的delete、selectOne或update方法,以delete方法开头就调用delete方法,以select开关就调用selectOne方法,否则就调用update方法
4、对XMLMapperBuilder解析类的改造,因为之前编写查询方法的时候,只对select标签进行了解析,后面需要添加对insert、update、delete标签的解析
思路分析完成,接下来我们看具体的实现
1、在Excutor接口增加update方法,并在SimpleExecutor实现类中进行具体的实现
Excutor接口代码
package study.lagou.com.sqlSession;
import study.lagou.com.pojo.Configuration;
import study.lagou.com.pojo.MappedStatement;
import java.util.List;
public interface Executor {
/**
* 查询方法
* @param configuration
* @param mappedStatement
* @param params
* @param
* @return
* @throws Exception
*/
List query(Configuration configuration, MappedStatement mappedStatement, Object... params) throws Exception;
/**
* 更新方法,主要用于实现统一更新、删除和添加方法
* @param configuration
* @param mappedStatement
* @param params
*/
Integer update(Configuration configuration,MappedStatement mappedStatement,Object... params) throws Exception;
}
SimpleExecutor实现类代码,因为获取数据库连接、转换SQL、获取PreparedStatement和设置参数的步骤查询和修改方法都是一致的,所以我们对这些步骤进行了一个简单的提取,提到到getPreparedStatement方法当中
package study.lagou.com.sqlSession;
import study.lagou.com.config.BoundSql;
import study.lagou.com.pojo.Configuration;
import study.lagou.com.pojo.MappedStatement;
import study.lagou.com.utils.GenericTokenParser;
import study.lagou.com.utils.ParameterMapping;
import study.lagou.com.utils.ParameterMappingTokenHandler;
import study.lagou.com.utils.SelefJavaClass;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
/**
* @Description: 功能描述
* @Author houjh
* @Email: [email protected]
* @Date: 2021-2-22 22:10
*/
public class SimpleExecutor implements Executor {
@Override
public List query(Configuration configuration, MappedStatement mappedStatement, Object... params) throws Exception {
//5、执行SQL
ResultSet resultSet = getPreparedStatement(configuration,mappedStatement,params).executeQuery();
//6、封装返回结果集
String resultType = mappedStatement.getResultType();
Class> resultTypeClass = getClassType(resultType);
ArrayList
2、在SqlSession接口中增加delete方法和update两个方法,并对getMapper方法进行改造,判断当前操作是要执行查询、新增、修改还是删除分别调用不同的方法
SqlSession接口类代码如下
package study.lagou.com.sqlSession;
import java.util.List;
public interface SqlSession {
/**
* 查询列表信息
* @param statementId
* @param params
* @param
* @return
*/
List selectList(String statementId, Object... params) throws Exception;
/**
* 查询单个数据信息
* @param statementId
* @param params
* @param
* @return
*/
T selectOne(String statementId,Object... params) throws Exception;
/**
* 删除信息
* @param statementId
* @param params
*/
Integer delete(String statementId,Object... params) throws Exception;
/**
* 更新数据信息
* @param statementId
* @param params
*/
Integer update(String statementId,Object... params) throws Exception;
/**
* 通过接口
* @param mapperInterfaceClass
* @param
* @return
*/
T getMapper(Class> mapperInterfaceClass);
}
DefaultSqlSession实现类具体代码,注意此处的代码包含对getMapper方法的改造
package study.lagou.com.sqlSession;
import study.lagou.com.pojo.Configuration;
import study.lagou.com.pojo.MappedStatement;
import java.lang.reflect.*;
import java.util.List;
/**
* @Description: 功能描述
* @Author houjh
* @Email: [email protected]
* @Date: 2021-2-22 21:24
*/
public class DefaultSqlSession implements SqlSession {
private Configuration configuration;
private Executor simpleExecutor = new SimpleExecutor();
public DefaultSqlSession(Configuration configuration) {
this.configuration = configuration;
}
@Override
public List selectList(String statementId, Object... params) throws Exception {
List
3、对XMLMapperBuilder解析类的改造,因为之前编写查询方法的时候,只对select标签进行了解析,后面需要添加对insert、、update、delete标签的解析,此处只需要在rootElement.selectNodes获取节点的时候添加//insert|//update|//delete标签就行
具体实现代码如下
package study.lagou.com.config;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import study.lagou.com.pojo.Configuration;
import study.lagou.com.pojo.MappedStatement;
import java.io.InputStream;
import java.util.List;
/**
* @Description: 功能描述
* @Author houjh
* @Email: [email protected]
* @Date: 2021-1-28 23:32
*/
public class XMLMapperBuilder {
private Configuration configuration;
public XMLMapperBuilder(Configuration configuration) {
this.configuration = configuration;
}
public void parse(InputStream inputStream) throws DocumentException {
Document document = new SAXReader().read(inputStream);
Element rootElement = document.getRootElement();
String namespace = rootElement.attributeValue("namespace");
List list = rootElement.selectNodes("//select|//insert|//update|//delete");
for (Element element : list) {
String id = element.attributeValue("id");
String resultType = element.attributeValue("resultType");
String paramterType = element.attributeValue("paramterType");
String sqlText = element.getTextTrim();
MappedStatement mappedStatement = new MappedStatement();
mappedStatement.setId(id);
mappedStatement.setResultType(resultType);
mappedStatement.setParamterType(paramterType);
mappedStatement.setSql(sqlText);
String statementId = namespace+"."+id;
configuration.getMappedStatementMap().put(statementId,mappedStatement);
}
}
}
最后编写测试类对方法进行测试,注意测试方法中需要注意数据库中是否在对应的数据,此处将源代码贴出来,大家注意根据自己数据库中的数据进行相应的调整
package study.lagou.com.test;
import org.dom4j.DocumentException;
import org.junit.Test;
import study.lagou.com.io.Resources;
import study.lagou.com.persistence.test.dao.IUserDao;
import study.lagou.com.persistence.test.pojo.User;
import study.lagou.com.sqlSession.SqlSession;
import study.lagou.com.sqlSession.SqlSessionFactory;
import study.lagou.com.sqlSession.SqlSessionFactoryBuilder;
import java.beans.PropertyVetoException;
import java.io.InputStream;
import java.util.List;
/**
* @Description: 功能描述
* @Author houjh
* @Email: [email protected]
* @Date: 2021-1-28 21:19
*/
public class PersistenceMapperTest {
public IUserDao getUserDao() throws PropertyVetoException, DocumentException {
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = build.openSession();
IUserDao userDao = sqlSession.getMapper(IUserDao.class);
return userDao;
}
@Test
public void testOne() throws Exception {
User user = new User();
user.setId(1);
user.setUsername("xiaozhangsan");
User resultUser = getUserDao().findByCondition(user);
System.out.println(resultUser);
}
@Test
public void testList() throws Exception {
List userList = getUserDao().findAll();
for (User user : userList) {
System.out.println(user);
}
}
@Test
public void testUpdate() throws Exception {
User user = new User();
user.setId(1);
user.setUsername("zhangsan");
user.setPassword("777");
user.setNickname("张三");
Integer update = getUserDao().updateById(user);
System.out.println(update);
}
@Test
public void testDelete() throws Exception {
Integer delete = getUserDao().deleteById(3);
System.out.println(delete);
}
@Test
public void testInsert() throws Exception {
User user = new User();
user.setId(5);
user.setUsername("zhaoliu");
user.setPassword("888");
user.setNickname("赵六");
getUserDao().insert(user);
}
}
具体代码对应下载地址:https://gitee.com/happymima/mybatis.git