【Java】Java核心 77:Dom4j 解析 XML综合案例

news2024/9/20 20:06:27

文章目录

      • 1、需求
      • 2、案例效果
      • 3、案例分析
      • 4、自定义JDBC框架-代码实现
        • 4.1、Configuration
        • 4.2、注解
        • 4.3、映射类:Mapper
        • 4.4、SqlSession类
      • 5、自定义JDBC框架的使用
        • 5.1、数据表
        • 5.2、创建实体类
        • 5.3、UserMapper接口
        • 5.4、配置文件:config.xml
        • 5.5、测试类
        • 5.5、测试类


在这里插入图片描述

1、需求

需求:自定义dao层jdbc框架

  • 为了方便程序员操作数据库,让程序员更关注于sql代码层面和业务层面

2、案例效果

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

使用到的技术
- 反射
- 注解
- 动态代理
- xml解析:xpath


3、案例分析

自定义jdbc框架开发步骤:

1、通过软配置方式,和数据库连接

  • 解析xml配置文件,获得:driver、url、username、password
  • 德鲁伊连接池
    • 根据配置文件中的参数,创建连接池对象

2、创建@Select注解

  • 解析@Select注解中value值:select查询语句

3、创建映射类Mapper

  • 把从@Select注解中解析出来的select查询语句,赋值给Mapper中的sql成员变量

4、创建SqlSession类

  • 提供getMapper()方法,用来获取代理对象
    • 说明:程序员在获取到代理对象后,利用代理对象调用某个方法时,会被代理对象拦截处理

4、自定义JDBC框架-代码实现

4.1、Configuration

/*配置类
  1. 解析XML文件
  2. 创建德鲁伊连接池
*/
public class Configuration {
    /* 定义数据库连接对象相关属性 */
    private String driver;//驱动
    private String url;//连接地址
    private String username;//登录名
    private String password;//密码

    /* Mapper接口的全名称 */
    private String interName;

    /* 数据库连接池对象 */
    private DataSource dataSource;

    /* 映射类对象 */
    private Mapper mapper = new Mapper();


    //无参构造方法
    public Configuration() {
        try {
            //解析"config.xml"文件
            SAXReader reader = new SAXReader();
            InputStream is = Configuration.class.getClassLoader().getResourceAsStream("config.xml");
            Document doc = reader.read(is);
            //调用自定义方法: 将核心配置文件中的数据封装到Configuration类的属性中
            loadConfigXml(doc);

            //调用自定义方法: 初始化数据库连接池对象
            createDataSource();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    //初始化数据库连接池对象
    private void createDataSource() throws Exception {
        //创建c3p0核心类对象
        ComboPooledDataSource cpds = new ComboPooledDataSource();
        //使用对象调用方法将四大连接参数给数据库连接池
        cpds.setDriverClass(driver);
        cpds.setJdbcUrl(url);
        cpds.setUser(username);
        cpds.setPassword(password);

        //将cpds赋值给成员变量ds
        this.dataSource = cpds;//数据库连接池对象
    }


    //将核心配置文件中的数据封装到Configuration类属性中
    private void loadConfigXml(Document doc) {
        /*
        //使用document对象调用方法获取property标签:
        <property name="driver" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://127.0.0.1:3306/itheima"/>
        <property name="username" value="root"/>
        <property name="password" value="itheima"/>
        */
        List<Node> list = doc.selectNodes("//property");

        //遍历List集合
        for (Node node : list) {
            //强制转换
            Element e = (Element) node;
            //获取property标签的name属性值
            String name = e.attributeValue("name");//双引号中的name是property标签的name属性 driver
            //获取property标签的value属性值
            String value = e.attributeValue("value");//双引号中的value是property标签的value属性 com.mysql.jdbc.Driver
           
            //将value的值赋值给成员变量
            switch (name) {
                case "driver":
                    this.driver = value;//数据库驱动
                    break;
                case "url":
                    this.url = value;//连接url
                    break;
                case "username":
                    this.username = value;//登录名
                    break;
                case "password":
                    this.password = value;//密码
                    break;
            }
        }

        //<package name="xxx.xxx.UserMapper"></package>
        Node node = doc.selectSingleNode("//package");
        Element e = (Element) node;
        //Mapper接口的全名称
        this.interName = e.attributeValue("name");//"xxx.xxx.UserMapper"
    }


    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 String getInterName() {
        return interName;
    }

    public void setInterName(String interName) {
        this.interName = interName;
    }

    public DataSource getDataSource() {
        return dataSource;
    }

    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    public Mapper getMapper() {
        return mapper;
    }

    public void setMapper(Mapper mapper) {
        this.mapper = mapper;
    }
}

4.2、注解

@Select

//查询时使用的注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Select {
    String[] value();
}

@ResultType

//查询结果的封装类型
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ResultType {
    String value();
}


4.3、映射类:Mapper

package cn.itcast.config;

public class Mapper {
    private String sql;//存储sql语句
    private String resultType;//结果类型

    public Mapper() {
    }

    public Mapper(String sql) {
        this.sql = sql;
    }

    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;
    }
}


4.4、SqlSession类

@SuppressWarnings("all")
public class SqlSession {
    /**
     * 动态代理
     */
    public <T> T getMapper(Class<T> clazz) {
        //类加载器: 负责加载代理类到内存中
        ClassLoader classLoader = SqlSession.class.getClassLoader();

        //父接口
        Class[] interfaces = {clazz};


        T mapperProxy = (T) Proxy.newProxyInstance(classLoader, interfaces, new InvocationHandler() {

            //在调用方法时,代理对象执行invoke方法,返回List
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //创建核心配置类对象
                Configuration config = new Configuration();


                /******** 解析 @Select、@ResultType *******/
                Class clazz = Class.forName(config.getInterName());

                Method[] methods = clazz.getMethods();
                //遍历数组
                for (Method m : methods) {
                    //判断是否有注解
                    boolean boo = m.isAnnotationPresent(Select.class);

                    boolean boo2 = m.isAnnotationPresent(ResultType.class);

                    if (boo && boo2) {
                        //获取@Select注解对象
                        Select select = m.getAnnotation(Select.class);
                        //获取属性值
                        String[] value = select.value();//{"select * from user"}
                        String sql = value[0];
                        //给Mapper对象中的sql成员变量赋值
                        config.getMapper().setSql(sql);

                        //获取@ResultType注解对象
                        ResultType resultType = m.getAnnotation(ResultType.class);
                        String type = resultType.value();//获取属性值
                        config.getMapper().setResultType(type);
                    }
                }
                /*******************************/


                //获取映射对象
                Mapper mapper = config.getMapper();
                //利用映射对象,获取sql语句
                String sql = mapper.getSql();

                //利用映射对象,获取类型
                String resultType = mapper.getResultType();
                Class cl = Class.forName(resultType);


                //获取数据库连接池对象
                DataSource ds = config.getDataSource();
                //利用连接池对象,获取Connection对象
                Connection conn = ds.getConnection();

                //调用自定义方法: 执行sql查询语句
                List list = queryForList(conn, sql, cl);

                return list;
            }
        });

        //代理对象返回给getMapper的调用者     UserMapper mapper = sqlSession.getMapper(UserMapper.class);//mapperProxy
        return mapperProxy;
    }
   public List queryForList(Connection conn, String sql, Class clazz) throws SQLException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        List userList = new ArrayList();

        //通过连接对象得到预编译的语句对象
        PreparedStatement ps = conn.prepareStatement(sql);

        //执行SQL语句,得到结果集
        ResultSet rs = ps.executeQuery();

        while (rs.next()) {
            //获取构造方法对象,并实例化
            Object user = clazz.getConstructor().newInstance();

            //获取所有的成员变量(包含私有成员变量)
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) { //field可以是:id name passwd age gender adddate
                //得到成员变量的名字
                String name = field.getName();

                //暴力破解: 取消权限检查
                field.setAccessible(true);

                //rs.getObject(name) 表示根据数据表的列名取出数据表中的列值 因为User类中的成员变量名必须和数据表列名一致
                //例如: name 的值是birthday 那么这里 rs.getObject(name)---》rs.getObject("age")获取数据表的年龄20
                Object table_value = rs.getObject(name);

                //void set(Object obj, Object value)给成员变量赋值,参数1:对象名 参数2:要赋的值
                field.set(user, table_value);

            }
            //user对象添加到集合中
            userList.add(user);
        }

        //释放资源
        rs.close();
        ps.close();
        conn.close();

        //返回集合
        return userList;
    }
}   

5、自定义JDBC框架的使用


5.1、数据表

CREATE TABLE user (
  id int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
  name varchar(30) DEFAULT NULL,
  passwd varchar(20) DEFAULT NULL,
  age int(3) DEFAULT NULL,
  gender varchar(2) DEFAULT NULL,
  adddate date DEFAULT NULL
);

# 测试数据
INSERT INTO user VALUES (null, 'itcast', '123123', '10', '男', '2020-12-11');

5.2、创建实体类

public class User {
    private int id;
    private String name;
    private String passwd;
    private int age;
    private String gender;
    private Date adddate;

    public User() {
    }

    public User(int id, String name, String passwd, int age, String gender, Date adddate) {
        this.id = id;
        this.name = name;
        this.passwd = passwd;
        this.age = age;
        this.gender = gender;
        this.adddate = adddate;
    }

    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 getPasswd() {
        return passwd;
    }

    public void setPasswd(String passwd) {
        this.passwd = passwd;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public Date getAdddate() {
        return adddate;
    }

    public void setAdddate(Date adddate) {
        this.adddate = adddate;
    }


    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", passwd='" + passwd + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                ", adddate=" + adddate +
                '}';
    }
}


5.3、UserMapper接口

public interface UserMapper {

    //查询所有用户
    @Select("select * from user")
    @ResultType("com.itcast.pojo.User")
    public abstract List queryAllUser();

}

5.4、配置文件:config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<configuration>

    <!--数据源-->
    <dataSource>
        <!--驱动-->
        <property name="driver" value="com.mysql.jdbc.Driver"/>
        <!--地址-->
        <property name="url" value="jdbc:mysql://127.0.0.1:3306/itheima"/>
        <!--用户名-->
        <property name="username" value="root"/>
        <!--密码-->
        <property name="password" value="itheima"/>
    </dataSource>

    <!--加载映射接口-->
    <mappers>
        <package name="com.itcast.mapper.UserMapper"></package>
    </mappers>

</configuration>

5.5、测试类

public class Test1 {
    @Test
    public void testSelect() {
        //实例化
        SqlSession sqlSession = new SqlSession();

        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        List<User> users = mapper.queryAllUser();

        for (User u : users) {
            System.out.println(u);
        }
    }
}

assword" value=“itheima”/>

<!--加载映射接口-->
<mappers>
    <package name="com.itcast.mapper.UserMapper"></package>
</mappers>
~~~

5.5、测试类

public class Test1 {
    @Test
    public void testSelect() {
        //实例化
        SqlSession sqlSession = new SqlSession();

        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        List<User> users = mapper.queryAllUser();

        for (User u : users) {
            System.out.println(u);
        }
    }
}


在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/698080.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

当金融风控遇上人工智能,众安金融的实时特征平台实践

导读&#xff1a;随着企业数字化转型升级&#xff0c;线上业务呈现多场景、多渠道、多元化的特征。数据要素价值的挖掘可谓分秒必争&#xff0c;业务也对数据的时效性和灵活性提出了更高的要求。在庞大分散、高并发的数据来源背景下&#xff0c;数据的实时处理能力成为企业提升…

vCenter崩了之后重新搭建处理办法

一、需要重新搭的情况下&#xff0c;vCenter虚拟机是无法使用分布式端口组的&#xff0c;而此时所有的物理网卡都在分布式交换机上&#xff0c;这样vCenter虚拟机的网络是无法访问的&#xff0c;所以需要先找到需要一台esxi。 二、此时可以看到两个分布式交换机 正常情况下分布…

高性能商品秒杀抢购系统

完整资料进入【数字空间】查看——baidu搜索"writebug" Goirisrabbbitmqmysql构建高性能商品秒杀抢购系统 一、项目介绍 1. 课程目标 应用GoWeb快速构建秒杀系统全流程应用开发及架构化设计思维梳理逐级优化&#xff0c;轻松应对“秒杀”及类似高并发场景 2. 知…

layui框架学习(30:树形模块)

Layui中的树形组件模块tree用于以树形形式显示上下级结构的数据&#xff0c;类似于winform中的tree控件。tree模块的基本用法及显示效果如下所示&#xff1a; <div id"test"></div><br /><script>layui.use([tree,layer], function(){var tr…

python安装pyelliptic-.5.7报错ImportError: No module named setuptools

1.背景&#xff1a; python安装pyelliptic-.5.7模块报错 2.环境及版本&#xff1a; linux&#xff1a;centos-7.7 python&#xff1a; 2.7.5 pyelliptic&#xff1a;5.7 注意&#xff1a;这里是纯内网环境所以pip不能使用&#xff0c;我这里配置了一个内部yum源 3.解决思路&…

Spring Boot 中的事务注解

在应用程序中&#xff0c;事务管理是一个非常重要的概念。事务是指一系列的操作&#xff0c;这些操作要么全部成功&#xff0c;要么全部失败。在Spring Boot中&#xff0c;可以使用事务注解来管理事务。在使用事务注解的时候&#xff0c;一个非常重要的概念就是事务传播行为。 …

js内存泄漏及排查详解

js内存泄漏及排查详解 常见内存泄漏及解决方案 内存泄漏&#xff08;Memory Leak&#xff09;是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放&#xff0c;造成系统内存的浪费&#xff0c;导致程序运行速度减慢甚至系统崩溃等严重后果。 隐式全局变量 在局部…

音频小说项目介绍

看小说、听音频&#xff0c;App,H5网站&#xff0c;小程序多端开发 一、主页 主页tabBar四个分类&#xff1a; 首页&#xff0c;分类&#xff0c;收藏&#xff0c;我的 最上方是搜索框 下方是轮播图&#xff0c;不但自动滚动&#xff0c;还有动画效果 下面分类有&#xf…

IDEA 或者SVN修改老项目的svn地址

公司svn地址修改了&#xff0c;ip修改了。本地还有代码没提交。这里介绍一下怎么在IDEA或svn修改为新地址&#xff0c;然后代码就可以直接提交了。网上也有文章介绍&#xff0c;但其中没注明一个关键点&#xff0c;导致很多人修改不成功。所以有了这篇文章。 IDEA下修改svn地址…

【Python】模块导入 ⑤ ( 主程序判断语句 | 模块中执行函数问题 | 制作自定义模块并执行函数 | 导入自定义模块会执行模块中的代码 )

文章目录 一、模块中执行函数问题1、制作自定义模块并执行函数2、导入自定义模块会执行模块中的代码3、主程序判断语句4、代码示例 - 主程序判断语句 一、模块中执行函数问题 1、制作自定义模块并执行函数 如果在自定义模块中 , 定义了函数 , 并且调用了该函数 ; 如下代码所示…

【TCP/IP】多播 - 定义、原理及编程实现 (TTL、多播组、多播消息)

目录 多播 多播的原理 多播的数据传输时的特点 TTL 的概念 TTL 和 多播组的配置方法 多播的编程与实现 发送者 接收者 多播 多播是一种介于单播和广播通信之间的技术方式&#xff0c;可以将发送者所需要发送的数据包分别发送给分散在不同子网中的一组接收者。 多播的原…

MySQL - 第11节 - MySQL事务管理

1.事务的概念 事务的概念&#xff1a; • 上层看起来比较简单的需求&#xff0c;可能对应的后端要做很多工作&#xff0c;后端这些工作组合起来才是一个完整的需求解决的方案。 • 事务由一条或多条SQL语句组成&#xff0c;这些语句在逻辑上存在相关性&#xff0c;共同完成一个…

聊聊transformers库; 微软推出ZeRO++技术:优化大型AI模型训练时间和成本

&#x1f989; AI新闻 &#x1f680; 微软推出ZeRO技术&#xff1a;优化大型AI模型训练时间和成本 摘要&#xff1a;据报道&#xff0c;微软研究人员最近发布了一项名为ZeRO的新技术&#xff0c;旨在优化训练大型AI模型时常遇到的数据传输成本和带宽限制问题&#xff0c;可大…

【0212】tcpdump抓包分析pg_hba.conf以password作为认证证方式下frontend与Backend之间身份验证过程(13 - 2)

文章目录 1. 回顾2. 密码校验通过3. 密码校验失败上一文:【0211】tcpdump抓包分析pg_hba.conf以password作为认证证方式下frontend与Backend之间身份验证过程(13 - 1) 1. 回顾 在上一节内容中,讲解了Backend对于接收到来自frontend的字符串明文密码,和来自于来自pg_auth…

荷兰宽带数据泄露 1

又要引入一个新工具RouterPassView 大多数现代路由器都可以备份一个路由器的配置文件&#xff0c;然后在需要的时候从文件中恢复配置。路由器的备份文件通常包含了像您的ISP的用户名重要数据/密码&#xff0c;路由器的登录密码&#xff0c;无线网络的KEY。 如果你忘记了这些密码…

第八十九天学习记录:C++核心:引用

引用的基本使用 作用&#xff1a;给变量起别名 语法&#xff1a;数据类型 &别名原名 #include<iostream> using namespace std;int main() {//引用基本语法//数据类型 &别名 原名int num1 3;int &num2 num1;cout << "num1" << n…

输入路由器IP地址进入IIS问题解决

0x01 问题描述 Windows10系统&#xff0c;路由器IP为192.168.1.1&#xff0c;本机获取的IP为192.168.1.110&#xff0c;但在浏览器URL输入路由器IP时却没有进入路由登录页&#xff0c;而是进了IIS欢迎页面。 0x02 问题分析 由于我本机IP不是192.168.1.1&#xff0c;所以排除与…

第八十七天学习记录:Linux基础:基础指令Ⅱ

touch创建文件 可以通过touch命令创建文件 语法&#xff1a;touch Linux路径 1、touch命令无选项&#xff0c;参数必填&#xff0c;表示要创建的文件路径&#xff0c;相对、绝对、特殊路径符均可以使用 cat命令 查看文件内容 首先用Vim编辑器在刚刚新建的tanktest.txt中编辑…

MyBatis学习笔记--中篇

MyBatis学习 文章目录 MyBatis学习1、MyBatis 配置解析1.1、核心配置文件1.2、事务管理器&#xff08;transactionManager&#xff09;1.3、数据源&#xff08;DataSource&#xff09;1.4、属性&#xff08;properties&#xff09;1.5、类型别名&#xff08;typeAliases&#x…

1. AGPC-SLAM: Absolute Ground Plane Constrained 3D Lidar SLAM

AGPC-SLAM: Absolute Ground Plane Constrained 3D Lidar SLAM overview 关键思路 odom约束 回环检测约束 地面约束 总体约束 问题 地面约束似乎倾向于全部对齐到第一个平面&#xff0c;也就是说该方案假设了所有地面方程是同一个平面。后面的实验也验证了上述假设有问题&…