以查询为例
创建SqlSession接口
public interface SqlSession{ <T> List<T> queryList() throws Exception; }
创建SqlSessionImpl类,实现SqlSession接口
public class SqlSessionImpl implements SqlSession{ public <T> List<T> queryList() throws Exception{ String driver="com.mysql.cj.jdbc.Driver"; String url="jdbc:mysql://localhost:3306/testdb?characterEncoding=utf8&useSSL=false&useUnicode=true&allowPublicKeyRetrieval=false&serverTimezone=GMT"; String username="sa"; String password="admin"; //加载驱动 Class.forName(driver); //建立连接 Connection connection= DriverManager.getConnection(url,username,password); //创建Statement Statement statement=connection.createStatement(); //执行sql String sql="select * from userinfo"; ResultSet resultSet=statement.executeQuery(sql); //处理ResultSet List<T> list=new ArrayList<>(); User user; while(resultSet.next()){ user=new User(); user.setUserId(resultSet.getInt("userid")); user.setUserName(resultSet.getString("username")); user.setUserSex(resultSet.getString("usersex")); user.setUserAge(resultSet.getInt("userAge")); user.setUserAddress(resultSet.getString("useraddress")); list.add((T)user); } //释放资源 if(resultSet!=null){ resultSet.close(); } if(statement!=null){ statement.close(); } if(connection!=null){ connection.close(); } return list; } }
待处理的问题
- 数据库连接信息放置配置文件中
- Sql语句放置在配置文件中
- 结果集封装对象类型放置配置文件中
- 数据库中表对应的数据设置到对象中
处理数据库中表对应的数据设置到对象中
ResultSet resultSet=statement.executeQuery(sql); //返回list List<T> list=new ArrayList<>(); Object obj=null; String resultType="com.company.pojo.User"; Class<?> clazz=Class.forName(resultType); //获取ResultSet元数据 ResultSetMetaData metaData=resultSet.getMetaData(); //获取ResultSet列名 List<String> columnNameList=new ArrayList<>(); for(int i=1;i<=metaData.getColumnCount();i++){ String columnName=metaData.getColumnName(i); columnNameList.add(columnName); } //获取类中的方法 setXXX getXXX等方法 Method[] methods=clazz.getMethods(); while(resultSet.next()){ obj=clazz.newInstance(); //处理将结果集中数据填充到对象中的问题 for(String columnName:columnNameList){ Object columnValue=result.getObject(columnName); //遍历类中的方法 for(Method method:methods){ //获取方法名 String name=method.getName(); if(name.equalsIgnoreCase("set"+columnName)){ //利用反射执行方法赋值 method.invoke(obj,columnValue); } } } list.add(obj); } return list;
处理数据库连接信息放到Configuration对象中(Mybatis 解析XML)
SqlSessionImpl.java代码中
private Configuration configuration; public void setConfiguration(Configuration configuration){ this.configuration=configuration; } public <T> List<T> queryList(String sqlId) throws Exception{ String driver=configuration.getDriver(); String url=configuration.getUrl(); String username=configuration.getUsername(); String password=configuration.getPassword(); //...... }
在解决问题2和3,先看配置文件SqlMapConfig.xml和UserMapper.xml。
SqlMapConfig.xml
<?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> <environments default="development"> <environment id="development"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://127.0.0.1:3306/testdb?characterEncoding=utf8&useSSL=false&serverTimezone=GMT&allowPublicKeyRetrieval=false&useUnicode=true" /> <property name="username" value="sa" /> <property name="password" value="admin" /> </dataSource> </environment> </environments> <mappers> <mapper resource="UserMapper.xml" /> </mappers> </configuration>
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.company.pojo.UserMapper"> <select id="queryUserList" resultType="com.company.pojo.User"> select * from userinfo</select> </mapper>
定义Mapper.java类
public class Mapper { //sql语句 private String sql; //结果集封装的对象类型 private String resultType; public String getSql() { return sql; } public void setSql(String sql) { this.sql = sql; } public String getResultType() { return resultType; } public void setResultType(String resultType) { this.resultType = resultType; } @Override public String toString() { return "Mapper{" + "sql='" + sql + '\'' + ", resultType='" + resultType + '\'' + '}'; } }
将sql语句和结果集封装对象的类型的Mapper与sqlId一一对应,一起封装在Configuration对象中。
Configuration.java
public class Configuration { //数据库驱动 private String driver; //数据库连接url private String url; //数据库连接账户 private String username; //数据库账户对应密码 private String password; //sqlId和对应的封装对象类型及sql语句 private Map<String, Mapper> mapperMap=new HashMap<>(); @Override public String toString() { return "Configuration{" + "driver='" + driver + '\'' + ", url='" + url + '\'' + ", username='" + username + '\'' + ", password='" + password + '\'' + ", mapperMap=" + mapperMap + '}'; } public String getDriver() { return driver; } public void setDriver(String driver) { this.driver = driver; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Map<String, Mapper> getMapperMap() { return mapperMap; } public void setMapperMap(Map<String, Mapper> mapperMap) { this.mapperMap = mapperMap; } }
解析SqlMapConfig.xml和UserMapper.xml文件,并将内容封装到Configuration对象中,解决问题2和3。
XmlConfigBuilder.java
public class XmlConfigBuilder { public static Configuration loadXmlConfig(InputStream inputStream) { Configuration configuration = new Configuration(); try { //创建解析XML的SAXReader对象 SAXReader saxReader = new SAXReader(); //获取Document对象 Document document = saxReader.read(inputStream); //获取根元素 Element rootElement = document.getRootElement(); //获取子元素 List<Element> list = rootElement.selectNodes("//property"); //封装数据库连接信息 for (Element element : list) { String name = element.attributeValue("name"); String value = element.attributeValue("value"); if ("driver".equalsIgnoreCase(name)) { configuration.setDriver(value); } if ("url".equalsIgnoreCase(name)) { configuration.setUrl(value); } if ("username".equalsIgnoreCase(name)) { configuration.setUsername(value); } if ("password".equalsIgnoreCase(name)) { configuration.setPassword(value); } } //获取mapper元素,这样就可以找到resource对应的XML文件 List<Element> mapperList = rootElement.selectNodes("//mapper"); for (Element element : mapperList) { String resource = element.attributeValue("resource"); //封装有关sql信息 loadSqlConfig(configuration,resource); } } catch (DocumentException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } return configuration; } public static void loadSqlConfig(Configuration configuration,String rousource) throws Exception { Map<String, Mapper> mapperMap=configuration.getMapperMap(); InputStream inputStream = Resources.getResourceAsStream(rousource); SAXReader saxReader=new SAXReader(); Document document = saxReader.read(inputStream); Element rootElement = document.getRootElement(); String namespace = rootElement.attributeValue("namespace"); List<Element> selectElements = rootElement.selectNodes("//select"); Mapper mapper; for(Element element:selectElements){ String id =namespace+"."+ element.attributeValue("id"); String resultType = element.attributeValue("resultType"); String sql = element.getText(); mapper=new Mapper(); mapper.setSql(sql); mapper.setResultType(resultType); mapperMap.put(id,mapper); } } }
而SqlSessionImpl.java完整代码
public class SqlSessionImpl implements SqlSession { private Configuration configuration; public void setConfiguration(Configuration configuration) { this.configuration = configuration; } @Override public <T> List<T> queryList(String sqlId) throws Exception { Class.forName(configuration.getDriver()); Connection connection = DriverManager.getConnection(configuration.getUrl(), configuration.getUsername(), configuration.getPassword()); Statement statement = connection.createStatement(); //根据sqlId找到xml中对应的sql内容 String sql=configuration.getMapperMap().get(sqlId).getSql(); ResultSet resultSet = statement.executeQuery(sql); List<T> list=new ArrayList<>(); Object obj=null; //创建一个空对象,除了new的方式创建对象 还可以用反射创建对象 //根据类的全限定类名(包名+类名) //根据sqlId找到对应的结果集封装对象类型 String resultType=configuration.getMapperMap().get(sqlId).getResultType(); Class<?> clazz = Class.forName(resultType); //获取ResultSet元数据 ResultSetMetaData metaData = resultSet.getMetaData(); //获取ResultSet列名 List<String> columnNameList=new ArrayList<>(); for(int i=1;i<=metaData.getColumnCount();i++){ String columnName = metaData.getColumnName(i); columnNameList.add(columnName); } //获取类中的方法 setXXX getXXX等方法 Method[] methods = clazz.getMethods(); while(resultSet.next()){ obj = clazz.newInstance(); for(String columnName:columnNameList){ Object object = resultSet.getObject(columnName); for(Method method:methods){ String name = method.getName(); if(name.equalsIgnoreCase("set"+columnName)){ //利用反射执行方法 method.invoke(obj,object); } } } list.add((T)obj); } return list; } }
而SqlSession.java接口相应的变更
public interface SqlSession { <T> List<T> queryList(String sqlId) throws Exception; }
通过创建SqlSessionFactory,调用openSession()获取SqlSession
SqlSessionFactory.java
public class SqlSessionFactory { private Configuration configuration; public void setConfiguration(Configuration configuration) { this.configuration = configuration; } public SqlSession openSession(){ SqlSession sqlSession=new SqlSessionImpl(); ((SqlSessionImpl) sqlSession).setConfiguration(configuration); return sqlSession; } }
通过创建SqlSessionFactoryBuilder,调用build()获取SqlSessionFactory
SqlSessionFactoryBuilder.java
public class SqlSessionFactoryBuilder { public SqlSessionFactory build(InputStream inputStream){ Configuration configuration = XmlConfigBuilder.loadXmlConfig(inputStream); SqlSessionFactory sqlSessionFactory=new SqlSessionFactory(); sqlSessionFactory.setConfiguration(configuration); return sqlSessionFactory; } }
测试代码:
public class SqlSessionFacotryBuilderTest { @Test public void test() throws Exception { InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml"); SqlSessionFactoryBuilder sqlSessionFactoryBuilder=new SqlSessionFactoryBuilder(); SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream); SqlSession sqlSession = sqlSessionFactory.openSession(); List<User> list = sqlSession.queryList("com.company.pojo.UserMapper.queryUserList"); list.forEach(System.out::println); } }
项目目录如下:

posted on
浙公网安备 33010602011771号