zoukankan      html  css  js  c++  java
  • 【mybatis学习笔记】

    2017年6月份接触JAVA,但是时隔快三年了,突然发现自己都没怎么在项目中用过,实在是有点难受...有些基础的东西都已经忘记了,在此,我就将之前学过的知识全部列在CSDN上面,供自己复习使用,但愿对您也有一定的帮助.

    学习链接:https://www.bilibili.com/video/BV1tf4y1U7pi?from=search&seid=5159934471689180192

    一、mybatis入门程序

    1.1导入依赖

        <dependencies>
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.4.5</version>
            </dependency>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.10</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.6</version>
                <scope>runtime</scope>
            </dependency>
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>1.2.12</version>
            </dependency>
        </dependencies>
    

    1.2 执行SQL文件

    DROP TABLE IF EXISTS `user`;
    
    CREATE TABLE `user` (
      `id` int(11) NOT NULL auto_increment,
      `username` varchar(32) NOT NULL COMMENT '用户名称',
      `birthday` datetime default NULL COMMENT '生日',
      `sex` char(1) default NULL COMMENT '性别',
      `address` varchar(256) default NULL COMMENT '地址',
      PRIMARY KEY  (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    
    insert  into `user`(`id`,`username`,`birthday`,`sex`,`address`) values (41,'老王','2018-02-27 17:47:08','男','北京'),(42,'小二王','2018-03-02 15:09:37','女','北京金燕龙'),(43,'小二王','2018-03-04 11:34:34','女','北京金燕龙'),(45,'传智播客','2018-03-04 12:04:06','男','北京金燕龙'),(46,'老王','2018-03-07 17:37:26','男','北京'),(48,'小马宝莉','2018-03-08 11:44:00','女','北京修正');
    
    
    DROP TABLE IF EXISTS `account`;
    
    CREATE TABLE `account` (
      `ID` int(11) NOT NULL COMMENT '编号',
      `UID` int(11) default NULL COMMENT '用户编号',
      `MONEY` double default NULL COMMENT '金额',
      PRIMARY KEY  (`ID`),
      KEY `FK_Reference_8` (`UID`),
      CONSTRAINT `FK_Reference_8` FOREIGN KEY (`UID`) REFERENCES `user` (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    
    insert  into `account`(`ID`,`UID`,`MONEY`) values (1,41,1000),(2,45,1000),(3,41,2000);
    
    DROP TABLE IF EXISTS `role`;
    
    CREATE TABLE `role` (
      `ID` int(11) NOT NULL COMMENT '编号',
      `ROLE_NAME` varchar(30) default NULL COMMENT '角色名称',
      `ROLE_DESC` varchar(60) default NULL COMMENT '角色描述',
      PRIMARY KEY  (`ID`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    insert  into `role`(`ID`,`ROLE_NAME`,`ROLE_DESC`) values (1,'院长','管理整个学院'),(2,'总裁','管理整个公司'),(3,'校长','管理整个学校');
    
    DROP TABLE IF EXISTS `user_role`;
    
    CREATE TABLE `user_role` (
      `UID` int(11) NOT NULL COMMENT '用户编号',
      `RID` int(11) NOT NULL COMMENT '角色编号',
      PRIMARY KEY  (`UID`,`RID`),
      KEY `FK_Reference_10` (`RID`),
      CONSTRAINT `FK_Reference_10` FOREIGN KEY (`RID`) REFERENCES `role` (`ID`),
      CONSTRAINT `FK_Reference_9` FOREIGN KEY (`UID`) REFERENCES `user` (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    insert  into `user_role`(`UID`,`RID`) values (41,1),(45,1),(41,2);
    
    

    1.3 创建实体类

    get、set、toString方法自己添加.

    public class User implements Serializable {
        private Integer id;
        private String username;
        private Date birthday;
        private String sex;
        private String address;
    }
    

    1.4日志配置

    log4j.properties:

    # Set root category priority to INFO and its only appender to CONSOLE.
    #log4j.rootCategory=INFO, CONSOLE            debug   info   warn error fatal
    log4j.rootCategory=debug, CONSOLE, LOGFILE
    
    # Set the enterprise logger category to FATAL and its only appender to CONSOLE.
    log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE
    
    # CONSOLE is set to be a ConsoleAppender using a PatternLayout.
    log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
    log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
    log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m
    
    
    # LOGFILE is set to be a File appender using a PatternLayout.
    log4j.appender.LOGFILE=org.apache.log4j.FileAppender
    log4j.appender.LOGFILE.File=d:axis.log
    log4j.appender.LOGFILE.Append=true
    log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
    log4j.appender.LOGFILE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m
    
    
    

    1.5mybatis主配置文件

    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>
        <!-- 配置 mybatis 的环境 -->
        <environments default="mysql">
            <!-- 配置 mysql 的环境 -->
            <environment id="mysql">
                <!-- 配置事务的类型 -->
                <transactionManager type="JDBC"></transactionManager>
                <!-- 配置连接数据库的信息:用的是数据源(连接池) -->
                <dataSource type="POOLED">
                    <property name="driver" value="com.mysql.jdbc.Driver"/>
                    <property name="url" value="jdbc:mysql://xxxx:3306/test"/>
                    <property name="username" value="root"/>
                    <property name="password" value="123456"/>
                </dataSource>
            </environment>
        </environments>
        <!-- 告知 mybatis 映射配置的位置 -->
        <mappers>
            <mapper resource="IUserDao.xml"/>
        </mappers>
    </configuration>
    

    1.6 IUserDao.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.learning.mybatis.dao.IUserDao">
        <!-- 配置查询所有操作 -->
        <select id="findAll" resultType="com.learning.mybatis.domain.User">
            select * from user
        </select>
    </mapper>
    

    1.7 IUserDao接口

    public interface IUserDao {
        /**
         * 查询所有用户
         * @return
         */
        List<User> findAll();
    }
    

    1.8 入门程序测试

    public class MybatisTest {
        public static void main(String[] args) throws IOException {
            //1.读取配置文件
            InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
            //2.创建 SqlSessionFactory 的构建者对象
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            //3.使用构建者创建工厂对象 SqlSessionFactory
            SqlSessionFactory factory = builder.build(in);
            //4.使用 SqlSessionFactory 生产 SqlSession 对象
            SqlSession session = factory.openSession();
            //5.使用 SqlSession 创建 dao 接口的代理对象
            IUserDao userDao = session.getMapper(IUserDao.class);
            //6.使用代理对象执行查询所有方法
            List<User> users = userDao.findAll();
            for (User user : users) {
                System.out.println(user);
            }
            //7.释放资源
            session.close();
            in.close();
        }
    }
    

    框架中运用了构建者模式、工厂模式、动态代理

    • 构建者模式:我们不需要管对象具体构建的繁琐、复杂的具体细节.
    • 工厂模式:如果类A,现在new A1实现类,如果想用new A2实现类,那么就要修改代码,变成A2实现类,需要重新部署、编译代码,所以使用工厂模式,避免了new关键字,解耦,降低类之间的依赖关系.
    • 代理模式:不修改源码的基础上,对代码进行增强.

    构建者模式体现的代码:SqlSessionFactory factory = builder.build(in)
    工厂模式体现的代码:SqlSession session = factory.openSession()
    动态代理体现的代码:IUserDao userDao = session.getMapper(IUserDao.class)

    读取配置文件:

    • 使用绝对路径---->路径是固定的,不可取
    • 使用相对路径---->src/java/main/xxx.xml 项目部署后没有src路径,也不可取
    • 使用类加载器---->它只能读取类加载路径的文件(mybatis使用的是这种方式)
    • 使用ServletContext对象文档getRealPath()

    1.9代码结构截图

    在这里插入图片描述

    1.10 教训

    我先创建了一个空工程,然后创建了一个mybatis模块,但是....后来我觉得模块名字取得不好,我修改了模块名称...结果完了,直接报下面这个错误:
    在这里插入图片描述

    下次模块命名的时候一定要准确仔细,避免修改模块名称,造成不必要的麻烦!!!

    二、自定义mybatis

    2.1 流程分析

    在这里插入图片描述

    2.2 依赖

    在mybatis入门案例的基础上,删除mybatis依赖(最好是重新创建一个模块),添加dom4j依赖

        <dependencies>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.10</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.6</version>
                <scope>runtime</scope>
            </dependency>
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>1.2.12</version>
            </dependency>
            <dependency>
                <groupId>dom4j</groupId>
                <artifactId>dom4j</artifactId>
                <version>1.6.1</version>
            </dependency>
            <dependency>
                <groupId>jaxen</groupId>
                <artifactId>jaxen</artifactId>
                <version>1.1.6</version>
            </dependency>
    

    2.3 创建Resources类

    在测试类中,却什么类,我们就补什么类

    public class Resources {
        /**
         * 根据传入的参数,获取一个字节输入流
         * @param filePath
         * @return
         */
        public static InputStream getResourceAsStream(String filePath){
            return Resources.class.getClassLoader().getResourceAsStream(filePath);
        }
    }
    

    2.3 创建SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession 类

        /**
         * 根据参数的字节输入流来构建一个SqlSessionFactory工厂
         * @param config
         * @return
         */
        public SqlSessionFactory build(InputStream config){
            return null;
        }
    

    我们暂时先让上面的方法返回null,发现此时报错,因为缺少SqlSessionFactory 类
    那么现在我们先创建SqlSessionFactory接口,保证上面的类不报错:

    public interface SqlSessionFactory {
        /**
         * 用于打开一个新的SqlSession对象
         * @return
         */
        SqlSession openSession();
    }
    

    目前缺少SqlSession 类,所以上面的接口报错了,现在去创建:

    public interface SqlSession {
        /**
         * 根据参数创建一个代理对象
         * @param daoInterfaceClass dao的接口字节码
         * @param <T>
         * @return
         */
        <T> T getMapper(Class<T> daoInterfaceClass);
    
        /**
         * 释放资源
         */
        void close();
    }
    

    好了,现在所有的类都不报错了.

    2.4 XMLConfigBuilder工具类

    public class XMLConfigBuilder {
    
    
    
        /**
         * 解析主配置文件,把里面的内容填充到DefaultSqlSession所需要的地方
         * 使用的技术:
         *      dom4j+xpath
         */
        public static Configuration loadConfiguration(InputStream config){
            try{
                //定义封装连接信息的配置对象(mybatis的配置对象)
                Configuration cfg = new Configuration();
    
                //1.获取SAXReader对象
                SAXReader reader = new SAXReader();
                //2.根据字节输入流获取Document对象
                Document document = reader.read(config);
                //3.获取根节点
                Element root = document.getRootElement();
                //4.使用xpath中选择指定节点的方式,获取所有property节点
                List<Element> propertyElements = root.selectNodes("//property");
                //5.遍历节点
                for(Element propertyElement : propertyElements){
                    //判断节点是连接数据库的哪部分信息
                    //取出name属性的值
                    String name = propertyElement.attributeValue("name");
                    if("driver".equals(name)){
                        //表示驱动
                        //获取property标签value属性的值
                        String driver = propertyElement.attributeValue("value");
                        cfg.setDriver(driver);
                    }
                    if("url".equals(name)){
                        //表示连接字符串
                        //获取property标签value属性的值
                        String url = propertyElement.attributeValue("value");
                        cfg.setUrl(url);
                    }
                    if("username".equals(name)){
                        //表示用户名
                        //获取property标签value属性的值
                        String username = propertyElement.attributeValue("value");
                        cfg.setUsername(username);
                    }
                    if("password".equals(name)){
                        //表示密码
                        //获取property标签value属性的值
                        String password = propertyElement.attributeValue("value");
                        cfg.setPassword(password);
                    }
                }
                //取出mappers中的所有mapper标签,判断他们使用了resource还是class属性
                List<Element> mapperElements = root.selectNodes("//mappers/mapper");
                //遍历集合
                for(Element mapperElement : mapperElements){
                    //判断mapperElement使用的是哪个属性
                    Attribute attribute = mapperElement.attribute("resource");
                    if(attribute != null){
                        System.out.println("使用的是XML");
                        //表示有resource属性,用的是XML
                        //取出属性的值
                        String mapperPath = attribute.getValue();//获取属性的值"com/itheima/dao/IUserDao.xml"
                        //把映射配置文件的内容获取出来,封装成一个map
                        Map<String,Mapper> mappers = loadMapperConfiguration(mapperPath);
                        //给configuration中的mappers赋值
                        cfg.setMappers(mappers);
                    }/*else{
                        System.out.println("使用的是注解");
                        //表示没有resource属性,用的是注解
                        //获取class属性的值
                        String daoClassPath = mapperElement.attributeValue("class");
                        //根据daoClassPath获取封装的必要信息
                        Map<String, Mapper> mappers = loadMapperAnnotation(daoClassPath);
                        //给configuration中的mappers赋值
                        cfg.setMappers(mappers);
                    }*/
                }
                //返回Configuration
                return cfg;
            }catch(Exception e){
                throw new RuntimeException(e);
            }finally{
                try {
                    config.close();
                }catch(Exception e){
                    e.printStackTrace();
                }
            }
    
        }
    
        /**
         * 根据传入的参数,解析XML,并且封装到Map中
         * @param mapperPath    映射配置文件的位置
         * @return  map中包含了获取的唯一标识(key是由dao的全限定类名和方法名组成)
         *          以及执行所需的必要信息(value是一个Mapper对象,里面存放的是执行的SQL语句和要封装的实体类全限定类名)
         */
        private static Map<String,Mapper> loadMapperConfiguration(String mapperPath)throws IOException {
            InputStream in = null;
            try{
                //定义返回值对象
                Map<String,Mapper> mappers = new HashMap<String,Mapper>();
                //1.根据路径获取字节输入流
                in = Resources.getResourceAsStream(mapperPath);
                //2.根据字节输入流获取Document对象
                SAXReader reader = new SAXReader();
                Document document = reader.read(in);
                //3.获取根节点
                Element root = document.getRootElement();
                //4.获取根节点的namespace属性取值
                String namespace = root.attributeValue("namespace");//是组成map中key的部分
                //5.获取所有的select节点
                List<Element> selectElements = root.selectNodes("//select");
                //6.遍历select节点集合
                for(Element selectElement : selectElements){
                    //取出id属性的值      组成map中key的部分
                    String id = selectElement.attributeValue("id");
                    //取出resultType属性的值  组成map中value的部分
                    String resultType = selectElement.attributeValue("resultType");
                    //取出文本内容            组成map中value的部分
                    String queryString = selectElement.getText();
                    //创建Key
                    String key = namespace+"."+id;
                    //创建Value
                    Mapper mapper = new Mapper();
                    mapper.setQueryString(queryString);
                    mapper.setResultType(resultType);
                    //把key和value存入mappers中
                    mappers.put(key,mapper);
                }
                return mappers;
            }catch(Exception e){
                throw new RuntimeException(e);
            }finally{
                in.close();
            }
        }
    
        /**
         * 根据传入的参数,得到dao中所有被select注解标注的方法。
         * 根据方法名称和类名,以及方法上注解value属性的值,组成Mapper的必要信息
         * @param daoClassPath
         * @return
         */
        /*private static Map<String,Mapper> loadMapperAnnotation(String daoClassPath)throws Exception{
            //定义返回值对象
            Map<String,Mapper> mappers = new HashMap<String, Mapper>();
    
            //1.得到dao接口的字节码对象
            Class daoClass = Class.forName(daoClassPath);
            //2.得到dao接口中的方法数组
            Method[] methods = daoClass.getMethods();
            //3.遍历Method数组
            for(Method method : methods){
                //取出每一个方法,判断是否有select注解
                boolean isAnnotated = method.isAnnotationPresent(Select.class);
                if(isAnnotated){
                    //创建Mapper对象
                    Mapper mapper = new Mapper();
                    //取出注解的value属性值
                    Select selectAnno = method.getAnnotation(Select.class);
                    String queryString = selectAnno.value();
                    mapper.setQueryString(queryString);
                    //获取当前方法的返回值,还要求必须带有泛型信息
                    Type type = method.getGenericReturnType();//List<User>
                    //判断type是不是参数化的类型
                    if(type instanceof ParameterizedType){
                        //强转
                        ParameterizedType ptype = (ParameterizedType)type;
                        //得到参数化类型中的实际类型参数
                        Type[] types = ptype.getActualTypeArguments();
                        //取出第一个
                        Class domainClass = (Class)types[0];
                        //获取domainClass的类名
                        String resultType = domainClass.getName();
                        //给Mapper赋值
                        mapper.setResultType(resultType);
                    }
                    //组装key的信息
                    //获取方法的名称
                    String methodName = method.getName();
                    String className = method.getDeclaringClass().getName();
                    String key = className+"."+methodName;
                    //给map赋值
                    mappers.put(key,mapper);
                }
            }
            return mappers;
        }*/
    
        
    }
    

    先注释掉注解有关的。上面的类发现还是报错,需要创建下面的类.

    2.5 创建Configuration类

    public class Configuration {
    
        private String driver;
        private String url;
        private String username;
        private String password;
    
        private Map<String,Mapper> mappers = new HashMap<String,Mapper>();
    
        public Map<String, Mapper> getMappers() {
            return mappers;
        }
    
        public void setMappers(Map<String, Mapper> mappers) {
            this.mappers.putAll(mappers);//此处需要使用追加的方式
        }
    
        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;
        }
    }
    

    2.6 创建Mapper类

    public class Mapper {
    
        private String queryString;//SQL
        private String resultType;//实体类的全限定类名
    
        public String getQueryString() {
            return queryString;
        }
    
        public void setQueryString(String queryString) {
            this.queryString = queryString;
        }
    
        public String getResultType() {
            return resultType;
        }
    
        public void setResultType(String resultType) {
            this.resultType = resultType;
        }
    }
    

    2.7 创建DefaultSqlSessionFactory

    创建DefaultSqlSessionFactory类

    public class DefaultSqlSessionFactory implements SqlSessionFactory{
    
        private Configuration cfg;
    
        public DefaultSqlSessionFactory(Configuration cfg){
            this.cfg = cfg;
        }
    
        /**
         * 用于创建一个新的操作数据库对象
         * @return
         */
        @Override
        public SqlSession openSession() {
            return new DefaultSqlSession(cfg);
        }
    }
    

    改造SqlSessionFactoryBuilder类

    public class SqlSessionFactoryBuilder {
        /**
         * 根据参数的字节输入流来构建一个SqlSessionFactory工厂
         * @param config
         * @return
         */
        public SqlSessionFactory build(InputStream config){
            Configuration cfg = XMLConfigBuilder.loadConfiguration(config);
            return  new DefaultSqlSessionFactory(cfg);
        }
    }
    

    2.8 创建DefaultSqlSession

    public class DefaultSqlSession implements SqlSession {
    
        private Configuration cfg;
        private Connection connection;
    
        public DefaultSqlSession(Configuration cfg){
            this.cfg = cfg;
            connection = DataSourceUtil.getConnection(cfg);
        }
    
        /**
         * 用于创建代理对象
         * @param daoInterfaceClass dao的接口字节码
         * @param <T>
         * @return
         */
        @Override
        public <T> T getMapper(Class<T> daoInterfaceClass) {
            return (T) Proxy.newProxyInstance(daoInterfaceClass.getClassLoader(),
                    new Class[]{daoInterfaceClass},new MapperProxy(cfg.getMappers(),connection));
        }
    
        /**
         * 用于释放资源
         */
        @Override
        public void close() {
            if(connection != null) {
                try {
                    connection.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
    

    2.9 数据库工具类

    public class DataSourceUtil {
    
        /**
         * 用于获取一个连接
         * @param cfg
         * @return
         */
        public static Connection getConnection(Configuration cfg){
            try {
                Class.forName(cfg.getDriver());
                return DriverManager.getConnection(cfg.getUrl(), cfg.getUsername(), cfg.getPassword());
            }catch(Exception e){
                throw new RuntimeException(e);
            }
        }
    }
    

    2.10 创建MapperProxy类

    public class MapperProxy implements InvocationHandler {
    
        //map的key是全限定类名+方法名
        private Map<String, Mapper> mappers;
        private Connection conn;
    
        public MapperProxy(Map<String,Mapper> mappers,Connection conn){
            this.mappers = mappers;
            this.conn = conn;
        }
    
        /**
         * 用于对方法进行增强的,我们的增强其实就是调用selectList方法
         * @param proxy
         * @param method
         * @param args
         * @return
         * @throws Throwable
         */
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            //1.获取方法名
            String methodName = method.getName();
            //2.获取方法所在类的名称
            String className = method.getDeclaringClass().getName();
            //3.组合key
            String key = className+"."+methodName;
            //4.获取mappers中的Mapper对象
            Mapper mapper = mappers.get(key);
            //5.判断是否有mapper
            if(mapper == null){
                throw new IllegalArgumentException("传入的参数有误");
            }
            //6.调用工具类执行查询所有
            return new Executor().selectList(mapper,conn);
        }
    }
    

    2.11 创建Executor 类

    public class Executor {
    
        public <E> List<E> selectList(Mapper mapper, Connection conn) {
            PreparedStatement pstm = null;
            ResultSet rs = null;
            try {
                //1.取出mapper中的数据
                String queryString = mapper.getQueryString();//select * from user
                String resultType = mapper.getResultType();//com.itheima.domain.User
                Class domainClass = Class.forName(resultType);
                //2.获取PreparedStatement对象
                pstm = conn.prepareStatement(queryString);
                //3.执行SQL语句,获取结果集
                rs = pstm.executeQuery();
                //4.封装结果集
                List<E> list = new ArrayList<E>();//定义返回值
                while(rs.next()) {
                    //实例化要封装的实体类对象
                    E obj = (E)domainClass.newInstance();
    
                    //取出结果集的元信息:ResultSetMetaData
                    ResultSetMetaData rsmd = rs.getMetaData();
                    //取出总列数
                    int columnCount = rsmd.getColumnCount();
                    //遍历总列数
                    for (int i = 1; i <= columnCount; i++) {
                        //获取每列的名称,列名的序号是从1开始的
                        String columnName = rsmd.getColumnName(i);
                        //根据得到列名,获取每列的值
                        Object columnValue = rs.getObject(columnName);
                        //给obj赋值:使用Java内省机制(借助PropertyDescriptor实现属性的封装)
                        PropertyDescriptor pd = new PropertyDescriptor(columnName,domainClass);//要求:实体类的属性和数据库表的列名保持一种
                        //获取它的写入方法
                        Method writeMethod = pd.getWriteMethod();
                        //把获取的列的值,给对象赋值
                        writeMethod.invoke(obj,columnValue);
                    }
                    //把赋好值的对象加入到集合中
                    list.add(obj);
                }
                return list;
            } catch (Exception e) {
                throw new RuntimeException(e);
            } finally {
                release(pstm,rs);
            }
        }
    
    
        private void release(PreparedStatement pstm,ResultSet rs){
            if(rs != null){
                try {
                    rs.close();
                }catch(Exception e){
                    e.printStackTrace();
                }
            }
    
            if(pstm != null){
                try {
                    pstm.close();
                }catch(Exception e){
                    e.printStackTrace();
                }
            }
        }
    }
    

    2.12 使用注解

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public @interface Select {
    
        /**
         * 配置SQL语句的
         * @return
         */
        String value();
    }
    
    
    1. 将xml解析的工具类中与注解相关的代码注释放开
    2. 在IuserDao.java中,添加注解@(select * from user)
    3. 将mybatis主配置文件的resource改成class="com.learning.mybatis.dao.IUserDao"
      到此为止,注解的支持就已经完毕!

    这个如果不看代码,自己实现感觉还难度挺大的哦.
    声明:此笔记是在学习黑马的JAVA视频做的.

  • 相关阅读:
    739. Daily Temperatures
    556. Next Greater Element III
    1078. Occurrences After Bigram
    1053. Previous Permutation With One Swap
    565. Array Nesting
    1052. Grumpy Bookstore Owner
    1051. Height Checker
    数据库入门及SQL基本语法
    ISCSI的概念
    配置一个IP SAN 存储服务器
  • 原文地址:https://www.cnblogs.com/tangliping/p/14630455.html
Copyright © 2011-2022 走看看