mybatis入门案例自定义实现

一、需要实现的类和接口
  1. public static void main(String[] args) throws Exception{
  2. //1.读取配置文件
  3. InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
  4. //2.创建SqlSessionFactory工厂
  5. SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
  6. SqlSessionFactory factory = builder.build(in);
  7. //3.使用工厂生产SqlSession对象
  8. SqlSession session = factory.openSession();
  9. //4.使用SqlSession创建Dao的代理对象
  10. IUserDao userDao = session.getMapper(IUserDao.class);
  11. //5.使用代理对象执行方法
  12. List<User> users = userDao.findAll();
  13. for(User user : users) {
  14. System.out.println(user);
  15. }
  16. //6.释放资源
  17. session.close();
  18. in.close();
  19. }

根据测试类MybatisTest中的main函数,需要实现的类有:Resources、SqlSessionFactoryBuilder,需要实现的接口有:SqlSessionFactory、SqlSession。由于是自定义mybatis,我们将项目配置文件pom.xml中的mybatis的相关信息删除。

二、依据测试类创建缺少的接口和类
1.创建Resources类

在src/main/java目录下,创建mybatis包,在mybatis包下创建io包,在io包下新建类Resources,添加静态方法

  1. //使用类加载器读取配置文件的类
  2. public class Resources {
  3. /**
  4. * @description 根据传入的参数获取一个字节输入流
  5. * @param filePath
  6. * @return
  7. */
  8. public static InputStream getResourceAsStream(String filePath){
  9. return Resources.class.getClassLoader().getResourceAsStream(filePath);
  10. }
  11. }

之所以这样子添加,我们可以查看原mybatis中,getResourcesAsStream()方法的调用层级,可以发现最终调用的就是ClassLoader类下的getResourceAsStream()方法,因此我们直接调用该方法即可。

  1. //MybatisTest.class
  2. InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
  3. //Resources.class
  4. public static InputStream getResourceAsStream(String resource) throws IOException {
  5. return getResourceAsStream((ClassLoader)null, resource);
  6. }
  7. public static InputStream getResourceAsStream(ClassLoader loader, String resource) throws IOException {
  8. InputStream in = classLoaderWrapper.getResourceAsStream(resource, loader);
  9. if (in == null) {
  10. throw new IOException("Could not find resource " + resource);
  11. } else {
  12. return in;
  13. }
  14. }
  15. //ClassLoaderWrapper.class
  16. public InputStream getResourceAsStream(String resource, ClassLoader classLoader) {
  17. return this.getResourceAsStream(resource, this.getClassLoaders(classLoader));
  18. }
  19. InputStream getResourceAsStream(String resource, ClassLoader[] classLoader) {
  20. ClassLoader[] var3 = classLoader;
  21. int var4 = classLoader.length;
  22. for(int var5 = 0; var5 < var4; ++var5) {
  23. ClassLoader cl = var3[var5];
  24. if (null != cl) {
  25. InputStream returnValue = cl.getResourceAsStream(resource);
  26. if (null == returnValue) {
  27. returnValue = cl.getResourceAsStream("/" + resource);
  28. }
  29. if (null != returnValue) {
  30. return returnValue;
  31. }
  32. }
  33. }
  34. return null;
  35. }
  36. //ClassLoader.class
  37. public InputStream getResourceAsStream(String name) {
  38. Objects.requireNonNull(name);
  39. URL url = getResource(name);
  40. try {
  41. return url != null ? url.openStream() : null;
  42. } catch (IOException e) {
  43. return null;
  44. }
  45. }
2.创建SqlSessionFactorty接口

在mybatis包下新建包sqlsession,在sqlsession包下新建接口SqlSessionFactorty,依据main()方法,该接口中需要声明方法openSession()。

  1. public interface SqlSessionFactory {
  2. //用于打开一个新的SqlSession对象
  3. SqlSession openSession();
  4. }
3.创建SqlSession接口

在sqlsession包下新建接口SqlSessionFactorty,依据main()方法,该接口中需要声明方法getMapper()和close()。

  1. //自定义mybatis中和数据库交互的核心类,可以创建dao接口的代理对象
  2. public interface SqlSession {
  3. /**
  4. * @description 根据参数创建一个代理对象
  5. * @param daoInterfaceClass dao的接口字节码
  6. * @param <T>
  7. * @return
  8. */
  9. <T> T getMapper(Class<T> daoInterfaceClass);
  10. //释放资源
  11. void close();
  12. }

至于getMapper的声明为什么是这样子,可以查看我的上一篇博客:mybatis入门案例分析

4.创建SqlSessionFactoryBuilder类

在sqlsession包下创建SqlSessionFactoryBuilder类,添加一个build()方法,先返回空值,之后我们再来补全。

  1. /* 用于创建一个SqlSessionFactory对象 */
  2. public class SqlSessionFactoryBuilder {
  3. /**
  4. * @Description: 根据字节输入流来构建一个SqlSessionFactory工厂
  5. * @param config
  6. * @return
  7. */
  8. public SqlSessionFactory build(InputStream config){
  9. return null;
  10. }
  11. }

在原mybatis中,build()方法调用层级为:

  1. //MybatisTest.class
  2. SqlSessionFactory factory = builder.build(in);
  3. //SqlSessionFactoryBuilder.class
  4. public SqlSessionFactory build(InputStream inputStream) {
  5. return this.build((InputStream)inputStream, (String)null, (Properties)null);
  6. }
  7. public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
  8. SqlSessionFactory var5;
  9. try {
  10. XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
  11. var5 = this.build(parser.parse());
  12. } catch (Exception var14) {
  13. throw ExceptionFactory.wrapException("Error building SqlSession.", var14);
  14. } finally {
  15. ErrorContext.instance().reset();
  16. try {
  17. inputStream.close();
  18. } catch (IOException var13) {
  19. }
  20. }
  21. return var5;
  22. }
  23. public SqlSessionFactory build(Configuration config) {
  24. return new DefaultSqlSessionFactory(config);
  25. }

可以看到最后返回的是一个DefualtSqlSessionFactory对象,所以在自定义mybatis时,我们也需要返回一个DefuaultSqlSessionFactory对象。而且还用到了xml文件解析类XMLConfigBuilder,因此接下来我们需要定义xml解析类和DefuaultSqlSessionFactory类。

5.创建xml解析类XMLConfigBuilder

解析xml文件,我们采用的是dom4j技术,在查找信息时,用到了XPath。所以我们需要在项目文件pom.xml中添加上相关内容,导入jaxen是为了能够使用XPath:

  1. <dependency>
  2. <groupId>dom4j</groupId>
  3. <artifactId>dom4j</artifactId>
  4. <version>1.1</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>jaxen</groupId>
  8. <artifactId>jaxen</artifactId>
  9. <version>1.1.6</version>
  10. </dependency>

在mybatis包下新建包utils,在utils包下新建类XMLConfigBuilder。解析xml不是本文重点,所以解析类的代码在这里直接给出:

  1. /**
  2. * 用于解析配置文件
  3. */
  4. public class XMLConfigBuilder {
  5. /**
  6. * 解析主配置文件,把里面的内容填充到DefaultSqlSession所需要的地方
  7. * 使用的技术:dom4j+xpath
  8. */
  9. public static Configuration loadConfiguration(InputStream config){
  10. try{
  11. //定义封装连接信息的配置对象(mybatis的配置对象)
  12. Configuration cfg = new Configuration();
  13. //1.获取SAXReader对象
  14. SAXReader reader = new SAXReader();
  15. //2.根据字节输入流获取Document对象
  16. Document document = reader.read(config);
  17. //3.获取根节点
  18. Element root = document.getRootElement();
  19. //4.使用xpath中选择指定节点的方式,获取所有property节点
  20. List<Element> propertyElements = root.selectNodes("//property");
  21. //5.遍历节点
  22. for(Element propertyElement : propertyElements){
  23. //判断节点是连接数据库的哪部分信息
  24. //取出name属性的值
  25. String name = propertyElement.attributeValue("name");
  26. if("driver".equals(name)){
  27. //表示驱动
  28. //获取property标签value属性的值
  29. String driver = propertyElement.attributeValue("value");
  30. cfg.setDriver(driver);
  31. }
  32. if("url".equals(name)){
  33. //表示连接字符串
  34. //获取property标签value属性的值
  35. String url = propertyElement.attributeValue("value");
  36. cfg.setUrl(url);
  37. }
  38. if("username".equals(name)){
  39. //表示用户名
  40. //获取property标签value属性的值
  41. String username = propertyElement.attributeValue("value");
  42. cfg.setUsername(username);
  43. }
  44. if("password".equals(name)){
  45. //表示密码
  46. //获取property标签value属性的值
  47. String password = propertyElement.attributeValue("value");
  48. cfg.setPassword(password);
  49. }
  50. }
  51. //取出mappers中的所有mapper标签,判断他们使用了resource还是class属性
  52. List<Element> mapperElements = root.selectNodes("//mappers/mapper");
  53. //遍历集合
  54. for(Element mapperElement : mapperElements){
  55. //判断mapperElement使用的是哪个属性
  56. Attribute attribute = mapperElement.attribute("resource");
  57. if(attribute != null){
  58. System.out.println("使用的是XML");
  59. //表示有resource属性,用的是XML
  60. //取出属性的值
  61. String mapperPath = attribute.getValue();//获取属性的值"dao/IUserDao.xml"
  62. //把映射配置文件的内容获取出来,封装成一个map
  63. Map<String,Mapper> mappers = loadMapperConfiguration(mapperPath);
  64. //给configuration中的mappers赋值
  65. cfg.setMappers(mappers);
  66. }
  67. }
  68. //返回Configuration
  69. return cfg;
  70. }catch(Exception e){
  71. throw new RuntimeException(e);
  72. }finally{
  73. try {
  74. config.close();
  75. }catch(Exception e){
  76. e.printStackTrace();
  77. }
  78. }
  79. }
  80. /**
  81. * 根据传入的参数,解析XML,并且封装到Map中
  82. * @param mapperPath 映射配置文件的位置
  83. * @return map中包含了获取的唯一标识(key是由dao的全限定类名和方法名组成)
  84. * 以及执行所需的必要信息(value是一个Mapper对象,里面存放的是执行的SQL语句和要封装的实体类全限定类名)
  85. */
  86. private static Map<String,Mapper> loadMapperConfiguration(String mapperPath)throws IOException {
  87. InputStream in = null;
  88. try{
  89. //定义返回值对象
  90. Map<String,Mapper> mappers = new HashMap<String,Mapper>();
  91. //1.根据路径获取字节输入流
  92. in = Resources.getResourceAsStream(mapperPath);
  93. //2.根据字节输入流获取Document对象
  94. SAXReader reader = new SAXReader();
  95. Document document = reader.read(in);
  96. //3.获取根节点
  97. Element root = document.getRootElement();
  98. //4.获取根节点的namespace属性取值
  99. String namespace = root.attributeValue("namespace");//是组成map中key的部分
  100. //5.获取所有的select节点
  101. List<Element> selectElements = root.selectNodes("//select");
  102. //6.遍历select节点集合
  103. for(Element selectElement : selectElements){
  104. //取出id属性的值 组成map中key的部分
  105. String id = selectElement.attributeValue("id");
  106. //取出resultType属性的值 组成map中value的部分
  107. String resultType = selectElement.attributeValue("resultType");
  108. //取出文本内容 组成map中value的部分
  109. String queryString = selectElement.getText();
  110. //创建Key
  111. String key = namespace+"."+id;
  112. //创建Value
  113. Mapper mapper = new Mapper();
  114. mapper.setQueryString(queryString);
  115. mapper.setResultType(resultType);
  116. //把key和value存入mappers中
  117. mappers.put(key,mapper);
  118. }
  119. return mappers;
  120. }catch(Exception e){
  121. throw new RuntimeException(e);
  122. }finally{
  123. in.close();
  124. }
  125. }
  126. }
6.创建配置类Configuration

解析xml文件啊返回的包含有数据库的连接信息、SQL语句和查询结果的封装信息。在mybatis包下创建包config,在config包下新建类Configuration。结合我们之前的入门案例分析,这个类中的属性应该包括:driver,url,username,password,映射信息mappers。

  1. /* 自定义mybatis的配置类 */
  2. public class Configuration {
  3. private String driver;
  4. private String url;
  5. private String username;
  6. private String password;
  7. private Map<String,Mapper> mappers = new HashMap<>();
  8. public Map<String, Mapper> getMappers() {
  9. return mappers;
  10. }
  11. public void setMappers(Map<String, Mapper> mappers) {
  12. this.mappers.putAll(mappers);
  13. }
  14. public String getDriver() {
  15. return driver;
  16. }
  17. public void setDriver(String driver) {
  18. this.driver = driver;
  19. }
  20. public String getUrl() {
  21. return url;
  22. }
  23. public void setUrl(String url) {
  24. this.url = url;
  25. }
  26. public String getUsername() {
  27. return username;
  28. }
  29. public void setUsername(String username) {
  30. this.username = username;
  31. }
  32. public String getPassword() {
  33. return password;
  34. }
  35. public void setPassword(String password) {
  36. this.password = password;
  37. }
  38. }

注意:映射信息我们是存放在一个HashMap中,这样可以更加方便地通过完整的id找到SQL语句和查询结果的封装信息。因此接下来我们要定义一个Mapper类,并且setMapper()方法实际上是一个添加新元素并且去重的方法,所以我们不是直接赋值,而是调用putAll()方法。

7.创建Mapper类

结合我们对入门案例的分析,我们知道Mapper类中应该有两大属性,一个是queryString,即我们要执行的SQL语句;另一个是resultType,即封装查询信息的类。在config包下新建类Mapper,如下:

  1. /*用于封装执行的SQL语句和结果类型的全限定类名*/
  2. public class Mapper {
  3. private String queryString;
  4. private String resultType;
  5. public String getQueryString() {
  6. return queryString;
  7. }
  8. public void setQueryString(String queryString) {
  9. this.queryString = queryString;
  10. }
  11. public String getResultType() {
  12. return resultType;
  13. }
  14. public void setResultType(String resultType) {
  15. this.resultType = resultType;
  16. }
  17. }
8.创建SqlSessionFactory接口的实现类DefualtSqlSessionFactory

在mybatis包下新建包defualts,在defualts包下创建类DefualtSqlSessionFactory,openSession()方法返回的是一个操作数据库的对象,要想操作数据库,我们需要提供数据库的连接信息,因此需要添加Configuration类型的字段。

  1. public class DefualtSqlSessionFactory implements SqlSessionFactory {
  2. private Configuration cfg;
  3. public DefualtSqlSessionFactory(Configuration cfg){
  4. this.cfg = cfg;
  5. }
  6. /* 用于创建一个新的操作数据库对象*/
  7. @Override
  8. public SqlSession openSession() {
  9. return new DefualtSqlSession(cfg);
  10. }
  11. }
9.创建SqlSession接口的实现类DefualtSqlSession

在defualts包下创建类DefualtSqlSession。在该类中,我们同样需要配置信息,因此需要添加Configuration类型的字段。为了连接数据库,我们需要添加Connection类型的字段。结合上篇文章的分析,在创建代理对象时,我们需要指定代理方式。接下来我们要实现的就是连接数据库的类DataSourceUtil和调用selectList()方法的InvocationHandler接口的实现类。

  1. public class DefualtSqlSession implements SqlSession {
  2. private Configuration cfg;
  3. private Connection connection;
  4. public DefualtSqlSession(Configuration cfg){
  5. this.cfg = cfg;
  6. connection = DataSourceUtil.getConnection(cfg);
  7. }
  8. /* 用于创建代理对象*/
  9. @Override
  10. public <T> T getMapper(Class<T> daoInterfaceClass) {
  11. return (T) Proxy.newProxyInstance(daoInterfaceClass.getClassLoader(),
  12. new Class[]{daoInterfaceClass}, new MapperProxy(cfg.getMappers(), connection));
  13. }
  14. /*Description: 用于释放资源*/
  15. @Override
  16. public void close(){
  17. if(connection != null){
  18. try {
  19. connection.close();
  20. }catch (Exception e){
  21. e.printStackTrace();
  22. }
  23. }
  24. }
  25. }
10.创建连接数据库的类DataSourceUtil

在utils包下新建类DataSourceUtil:

  1. /* 创建数据源的工具类 */
  2. public class DataSourceUtil {
  3. /* 用于获取一个连接 */
  4. public static Connection getConnection(Configuration cfg){
  5. try {
  6. Class.forName(cfg.getDriver());
  7. return DriverManager.getConnection(cfg.getUrl(),cfg.getUsername(),cfg.getPassword());
  8. }catch (Exception e){
  9. throw new RuntimeException(e);
  10. }
  11. }
  12. }
11.创建InvocationHandler接口的实现类MapperProxy

在mybatis包下新建包proxy,在proxy包下新建类MapperProxy,该类中要对数据库进行查询,所以需要映射信息和数据库连接。在执行查询操作时,我们调用了Executor().selectList(mapper,conn)静态方法,所以接下来我们要定义工具类Executor。

  1. public class MapperProxy implements InvocationHandler {
  2. private Map<String, Mapper> mappers;
  3. private Connection conn;
  4. public MapperProxy(Map<String,Mapper> mappers, Connection conn){
  5. this.mappers = mappers;
  6. this.conn = conn;
  7. }
  8. /* 用于对方法进行增强的,其实就是调用selectList方法 */
  9. @Override
  10. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  11. //1.获取方法名
  12. String methodName = method.getName();
  13. //2.获取方法所在类的名称
  14. String className = method.getDeclaringClass().getName();
  15. //3.组合key
  16. String key = className+"."+methodName;
  17. //4.获取mappers中的Mapper对象
  18. Mapper mapper = mappers.get(key);
  19. //5.判断是否有mapper
  20. if(mapper == null){
  21. throw new IllegalArgumentException("传入的参数有误");
  22. }
  23. //6.调用工具类执行查询所有
  24. return new Executor().selectList(mapper,conn);
  25. }
  26. }
12.创建查询工具类Executor

在utils包下,新建类Executor:

  1. /* 执行查询封装的工具类 */
  2. public class Executor {
  3. public <E> List<E> selectList(Mapper mapper, Connection conn) {
  4. PreparedStatement pstm = null;
  5. ResultSet rs = null;
  6. try {
  7. //1.取出mapper中的数据
  8. String queryString = mapper.getQueryString();//select * from user
  9. String resultType = mapper.getResultType();//domain.User
  10. Class domainClass = Class.forName(resultType);
  11. //2.获取PreparedStatement对象
  12. pstm = conn.prepareStatement(queryString);
  13. //3.执行SQL语句,获取结果集
  14. rs = pstm.executeQuery();
  15. //4.封装结果集
  16. List<E> list = new ArrayList<E>();//定义返回值
  17. while(rs.next()) {
  18. //实例化要封装的实体类对象
  19. E obj = (E)domainClass.getDeclaredConstructor().newInstance();
  20. //取出结果集的元信息:ResultSetMetaData
  21. ResultSetMetaData rsmd = rs.getMetaData();
  22. //取出总列数
  23. int columnCount = rsmd.getColumnCount();
  24. //遍历总列数
  25. for (int i = 1; i <= columnCount; i++) {
  26. //获取每列的名称,列名的序号是从1开始的
  27. String columnName = rsmd.getColumnName(i);
  28. //根据得到列名,获取每列的值
  29. Object columnValue = rs.getObject(columnName);
  30. //给obj赋值:使用Java内省机制(借助PropertyDescriptor实现属性的封装)
  31. PropertyDescriptor pd = new PropertyDescriptor(columnName,domainClass);//要求:实体类的属性和数据库表的列名保持一种
  32. //获取它的写入方法
  33. Method writeMethod = pd.getWriteMethod();
  34. //把获取的列的值,给对象赋值
  35. writeMethod.invoke(obj,columnValue);
  36. }
  37. //把赋好值的对象加入到集合中
  38. list.add(obj);
  39. }
  40. return list;
  41. } catch (Exception e) {
  42. throw new RuntimeException(e);
  43. } finally {
  44. release(pstm,rs);
  45. }
  46. }
  47. private void release(PreparedStatement pstm,ResultSet rs){
  48. if(rs != null){
  49. try {
  50. rs.close();
  51. }catch(Exception e){
  52. e.printStackTrace();
  53. }
  54. }
  55. if(pstm != null){
  56. try {
  57. pstm.close();
  58. }catch(Exception e){
  59. e.printStackTrace();
  60. }
  61. }
  62. }
  63. }
13.补全SqlSessionFactoryBuilder类的build方法

build()方法是根据字节输入流来构建一个SqlSessionFactory工厂,因此首先要对xml文件进行解析,读取配置文件,然后返回一个DefualtSqlSessionFactory类的实例。

  1. public SqlSessionFactory build(InputStream config){
  2. Configuration cfg = XMLConfigBuilder.loadConfiguration(config);
  3. return new DefualtSqlSessionFactory(cfg);
  4. }
三、项目结果和执行结果

到这里,我们就完成了自定义mybatis的通过xml文件进行配置的实现,之后我们还可以添加提供注解进行配置的实现,项目结构如下;

最后运行测试类的结果为:

四、添加注解的实现
1.修改主配置文件SqlMapConfig

将mapper标签修改为;

  1. <mappers>
  2. <mapper class="dao.IUserDao" />
  3. </mappers>
2.添加注解类

在mybatis包下新建包annocations,在annocations包下新建注解Select,如下:

  1. /* 查询的注解 */
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Target(ElementType.METHOD)
  4. public @interface Select {
  5. //配置SQL语句
  6. String value();
  7. }
3.在dao接口中添加注解
  1. public interface IUserDao {
  2. @Select("select * from user")
  3. List<User> findAll();
  4. }
4.在xml解析类中添加对注解的解析

1.添加通过注解创建映射的函数loadMapperAnnotation()

注意在dao接口中添加注解时,我们并没有添加resultType,因此这里我们获取resultType时运用了反射技术,findAll()方法的返回值是一个List,我们只需找到这个List当中元素的类型即为resultType。

  1. /**
  2. * 根据传入的参数,得到dao中所有被select注解标注的方法。
  3. * 根据方法名称和类名,以及方法上注解value属性的值,组成Mapper的必要信息
  4. * @param daoClassPath
  5. * @return
  6. */
  7. private static Map<String,Mapper> loadMapperAnnotation(String daoClassPath)throws Exception{
  8. //定义返回值对象
  9. Map<String,Mapper> mappers = new HashMap<String, Mapper>();
  10. //1.得到dao接口的字节码对象
  11. Class daoClass = Class.forName(daoClassPath);
  12. //2.得到dao接口中的方法数组
  13. Method[] methods = daoClass.getMethods();
  14. //3.遍历Method数组
  15. for(Method method : methods){
  16. //取出每一个方法,判断是否有select注解
  17. boolean isAnnotated = method.isAnnotationPresent(Select.class);
  18. if(isAnnotated){
  19. //创建Mapper对象
  20. Mapper mapper = new Mapper();
  21. //取出注解的value属性值
  22. Select selectAnno = method.getAnnotation(Select.class);
  23. String queryString = selectAnno.value();
  24. mapper.setQueryString(queryString);
  25. //获取当前方法的返回值,还要求必须带有泛型信息
  26. Type type = method.getGenericReturnType();//List<User>
  27. //判断type是不是参数化的类型
  28. if(type instanceof ParameterizedType){
  29. //强转
  30. ParameterizedType ptype = (ParameterizedType)type;
  31. //得到参数化类型中的实际类型参数
  32. Type[] types = ptype.getActualTypeArguments();
  33. //取出第一个
  34. Class domainClass = (Class)types[0];
  35. //获取domainClass的类名
  36. String resultType = domainClass.getName();
  37. //给Mapper赋值
  38. mapper.setResultType(resultType);
  39. }
  40. //组装key的信息
  41. //获取方法的名称
  42. String methodName = method.getName();
  43. String className = method.getDeclaringClass().getName();
  44. String key = className+"."+methodName;
  45. //给map赋值
  46. mappers.put(key,mapper);
  47. }
  48. }
  49. return mappers;
  50. }

2.修改loadConfiguration()方法

注解和xml文件进行配置调用的方法是不一样的,这里我们取出mapper标签,判断mapperElement使用的是哪个属性。将第二个循环体修改为:

  1. //取出mappers中的所有mapper标签,判断他们使用了resource还是class属性
  2. List<Element> mapperElements = root.selectNodes("//mappers/mapper");
  3. //遍历集合
  4. for(Element mapperElement : mapperElements){
  5. //判断mapperElement使用的是哪个属性
  6. Attribute attribute = mapperElement.attribute("resource");
  7. if(attribute != null){
  8. System.out.println("使用的是XML");
  9. //表示有resource属性,用的是XML
  10. //取出属性的值
  11. String mapperPath = attribute.getValue();//获取属性的值"dao/IUserDao.xml"
  12. //把映射配置文件的内容获取出来,封装成一个map
  13. Map<String,Mapper> mappers = loadMapperConfiguration(mapperPath);
  14. //给configuration中的mappers赋值
  15. cfg.setMappers(mappers);
  16. }else{
  17. System.out.println("使用的是注解");
  18. //表示没有resource属性,用的是注解
  19. //获取class属性的值
  20. String daoClassPath = mapperElement.attributeValue("class");
  21. //根据daoClassPath获取封装的必要信息
  22. Map<String,Mapper> mappers = loadMapperAnnotation(daoClassPath);
  23. //给configuration中的mappers赋值
  24. cfg.setMappers(mappers);
  25. }
  26. }
5.运行结果

博客链接:

mybatis入门案例

mybatis入门案例分析

mybatis入门案例自定义实现的更多相关文章

  1. MyBatis入门案例、增删改查

    一.MyBatis入门案例: ①:引入jar包 ②:创建实体类 Dept,并进行封装 ③ 在Src下创建大配置mybatis-config.xml <?xml version="1.0 ...

  2. MyBatis入门案例 增删改查

    一.MyBatis入门案例: ①:引入jar包 ②:创建实体类 Dept,并进行封装 ③ 在Src下创建大配置mybatis-config.xml <?xml version="1.0 ...

  3. Mybatis入门案例中设计模式的简单分析

    Talk is cheap, show me the code! public class TestMybatis { public static void main(String[] args) t ...

  4. mybatis入门案例分析

    mybatis入门案例分析 一.设计模式分析 public class MybatisTest { public static void main(String[] args) throws Exce ...

  5. 03 Mybatis:01.Mybatis课程介绍及环境搭建&&02.Mybatis入门案例

    mybatis框架共四天第一天:mybatis入门 mybatis的概述 mybatis的环境搭建 mybatis入门案例 -------------------------------------- ...

  6. intellij IDEA Mybatis入门案例

    最近打算学习ssm框架  Mybatis 作为入门的第一个持久层框架,学习起来实在费劲.故写此文章作为入门案例. 先打开 IDEA建立一个Maven项目,目录结构如下: 源代码已经上传至GitHub ...

  7. 一、mybatis入门案例

    今天学习了mybatis框架,简单记录一下mybatis第一个入门案例,目标是使用Mybatis作为持久层框架,执行查询数据的SQL语句并且获取结果集 基本步骤: 物理建模 逻辑建模 引入依赖 创建持 ...

  8. MyBatis入门案例

    1.案例架构 2.引入jar 包 3.书写配置文件mybatis-config.xml <?xml version="1.0" encoding="UTF-8&qu ...

  9. 阶段3 1.Mybatis_02.Mybatis入门案例_1.mybatis的入门

    H:\BaiDu\黑马传智JavaEE57期 2019最新基础+就业+在职加薪\讲义+笔记+资料\主流框架\31.会员版(2.0)-就业课(2.0)-Mybatis\mybatis\mybatis_d ...

随机推荐

  1. Visual Studio 2017 安装心得

    既然VS2017已经发布了,就想安装一下试试,先卸载VS2015, 网上有个完全卸载的东东,https://github.com/Microsoft/VisualStudioUninstaller/r ...

  2. Windows Live Writer 语法高亮

    1.WindowsLiveWriter.CNBlogs.CodeHighlighter.rar 这个插件生成的高亮代码与网页上的一模一样,插入后即可立即显示效果,不过貌似它必须联网才能实时显示效果,因 ...

  3. .net core3.1项目在centos7.6上部署经验

    0x00环境搭建 1)使用PuTTY远程登录你的centos 2)yum -y update 更新系统 3)安装宝塔面板: yum install -y wget && wget -O ...

  4. 虚拟机安装LEDE旁路由实现软路由功能

    如何在虚拟上安装LEDE软路由,接下来我们一步一步操作. 1.首先到https://firmware.koolshare.cn/ 下载虚拟机下专用盘如图标记均可 2.虚拟机创建 选择下载好的文件 保持 ...

  5. 27.python中excel处理库openpyxl使用详解

    openpyxl是一个第三方库,可以处理xlsx格式的Excel文件.pip install openpyxl安装. 读取Excel文件 需要导入相关函数 ? 1 2 3 from openpyxl ...

  6. solr学习(一)安装与部署

    经过测试,同步MongoDB数据到Solr的时候,Solr版本为8.4.0会出现连接不上的错误,8.3.0未经测试不知,博主测试好用的一版为8.2.0,但是官网已经下不到了,所以我会把下载链接放在文末 ...

  7. Linux下扫描服务器IP地址是否冲突(arp-scan)

    部署服务突然发现,连接的服务器断开了,因为服务器用户名密码是一样的,所以重新连接后,发现文件变了,跟之前不一样. 猜想是不是ip地址冲突了,两次连接的服务器不同. 网上查找资料说可以用工具扫描.工具: ...

  8. Winform在控件内实现简单画笔功能

    using System.Drawing; using System.Windows.Forms; namespace ZhuoHuiSchoolroom.ZhuoHuiClass { /// < ...

  9. Win7计划任务命令

    计划任务命令 schtasks C:\Users\Administrator>schtasks /? SCHTASKS /parameter [arguments] 描述: 允许管理员创建.删除 ...

  10. Spring Boot2 系列教程(二十一) | 自动配置原理

    微信公众号:一个优秀的废人.如有问题,请后台留言,反正我也不会听. 前言 这个月过去两天了,这篇文章才跟大家见面,最近比较累,大家见谅下.下班后闲着无聊看了下 SpringBoot 中的自动配置,把我 ...