zoukankan      html  css  js  c++  java
  • Java数据库编程、XML解析技术

    数据库编程

    JDBC概述

      是Java Database Connecive,即数据库连接技术的简称,它提供了连接各种常用数据库的能力。

      是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。

    JDBC组成

      通常JDBC有两部分组成:JDBC API和JDBC Driver。

      1)主要使用JDBC API完成三件事情:与数据库建立连接、执行SQL语句、处理结果。

      2)JDBC Driver常见的有以下几类:

                      JDBC-ODBC桥加ODB(驱动程序):缺点却是执行效率低、功能不够强大

                      JDBC+本地驱动:安全性比较差。

                      JDBC网络纯Java驱动程序:将JDBC转换为与DBMS无关的网络协议,又被某服务器转换为一种DBMS协议,以操作各种数据库

                      本地协议纯Java驱动程序:缺点是访问不同的数据库需要下载专用的JDBC驱动。

    JDBC应用步骤

    1. 加载JDBC Driver
    2. 创建数据库连接(Connection)
    3. 创建一个Statement
    4. 执行sql语句(CRUD操作语句)
    5. 处理sql结果
    6. 关闭Statement
    7. 关闭连接Connection

    1)加载JDBC Driver

      

    1 try {
    2     //加载MySQL JDBC驱动
    3     Class.forName("com.mysql.jdbc.Driver");
    4 } catch (ClassNotFoundException e) {
    5     e.printStackTrace();
    6 }

    2)创建数据库连接

     1 Connection connection = null;
     2 String url = "jdbc:mysql://localhost:3306/jdbc"; // 连接字符串
     3 String user = "root"; // 用户名
     4 String pass = "123456"; // 密码
     5 try {
     6     // 创建Connection对象
     7     connection = DriverManager.getConnection(url, user, pass);
     8 } catch (SQLException e) {
     9     e.printStackTrace();
    10 }

    3)创建Statement对象,执行SQL语句

    // 创建Statement对象
    Statement stmt = connection.createStatement();
    // 发送Insert语句
    int count = stmt.executeUpdate("INSERT INTO users(username, password) VALUES ('lily', 'lily123')");
    // 发送查询SQL语句
    ResultSet rs = stmt.executeQuery("SELECT id, username, password FROM users");

    4)处理结果

    // 循环处理查询结果集
    while (rs.next()){
        System.out.println("编号:" + rs.getInt(1) + ", 用户名:" + rs.getString("username") + ", 密码:" + rs.getString("password"));
    }

    5)释放资源

    try {
        if (rs != null)
            rs.close();
        if (stmt != null)
            stmt.close();
        if (connection != null)
            connection.close();
    } catch (SQLException e) {
        e.printStackTrace();
    }

    关于PreparedStatement  

      从代码易读性上来说,因为PreparedStatement使用“?”来代替参数,所以SQL语句较使用Statement更容易阅读。

      从安全性上来说,PreparedStatement是通过“?”来传递参数的,避免了拼sql而出现sql注入的问题,所以安全性较好。在开发中,推荐使用PreparedStatement。

    String username = "admin";
    String password = "admin";
    // 创建Statement对象
    Statement stmt = connection.createStatement();
    // 发送SQL语句并执行
    ResultSet rs = stmt.executeQuery("SELECT id, username, password FROM users WHERE username='" + username + "' AND password='" + password + "'");
    
    // 创建PreparedStatement对象
    PreparedStatement pstmt = connection.prepareStatement("SELECT id, username, password FROM users WHERE username=? AND password=?");
    // 设置pstmt参数
    pstmt.setString(1, username);
    pstmt.setString(2, password);
    // 执行SQL语句
    ResultSet rs2 = pstmt.executeQuery();

    连接到数据库

      1)使用DriverManager类的静态方法getConnection();

      2)使用DataSource类的getConnection();

    /**
     * 加载配置文件中JDBC连接所需要数据
     */
    private static void loadProperties() {
        InputStream in = Thread.currentThread().getClass()
                .getResourceAsStream("/jdbc.properties");
        Properties prop = new Properties();
        try {
            prop.load(in);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        driver = prop.getProperty("driver");
        url = prop.getProperty("url");
        user = prop.getProperty("user");
        password = prop.getProperty("password");
    }
    /* 通过静态代码块加载数据库驱动 */
    static {
        loadProperties(); // 读取配置文件
        try {
            Class.forName(driver); // 加载驱动
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }
    /**
     * 获取连接对象
     * 
     * @return 连接对象
     * @throws SQLException
     *             无法建立连接,则抛出异常
     */
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(url, user, password);
    }

    数据库会话

    /**
     * 开启会话
     */
    public void open() {
        if (null == conn)
            try {
                conn = JdbcResourceManager.getConnection();
            } catch (SQLException e) {
                throw new JdbcSessionException("数据库会话创建失败", e);
            }
    }
    
    /**
     * 关闭数据库会话,释放资源
     */
    public void close() {
        try {
            JdbcResourceManager.close(rs);
            rs = null;
        } catch (SQLException e) {
            throw new JdbcSessionException("数据库会话ResultSet关闭失败", e);
        } finally {
            try {
                JdbcResourceManager.close(pstmt);
                pstmt = null;
            } catch (SQLException e) {
                throw new JdbcSessionException("数据库会话Statement关闭失败", e);
            } finally {
                try {
                    JdbcResourceManager.close(conn);
                    conn = null;
                } catch (SQLException e) {
                    throw new JdbcSessionException("数据库会话Connection关闭失败", e);
                }
            }
        }
    }

    执行INSERT、UPDATE、DELETE语句的方法:

    /**
     * 执行更新SQL语句
     * 
     * @param sql
     *            更新的SQL语句,如INSERT、UPDATE、DELETE语句
     * @param params
     *            用于替换更新语句中"?"占位符的参数列表
     * @return 受影响行数
     */
    public int executeUpdate(String sql, Object... params) {
        try {
            pstmt = conn.prepareStatement(sql);
            if (null != params) {
                for (int i = 0; i < params.length; i++) { // 为每个?占位符设置参数
                    pstmt.setObject(i + 1, params[i]);
                }
            }
            return pstmt.executeUpdate();
        } catch (SQLException e) {
            throw new JdbcSessionException("执行更新操作失败", e);
        }
    }

      用于执行SELECT语句的方法:

    /**
     * 执行查询SQL语句
     * 
     * @param sql
     *            待执行查询的SQL语句,如 SELECT 语句
     * @param params
     *            用于替换查询语句中"?"占位符的参数列表
     * @return 查询结果集ResultSet对象
     */
    public ResultSet executeQuery(String sql, Object... params) {
        try {
            pstmt = conn.prepareStatement(sql);
            if (null != params) {
                for (int i = 0; i < params.length; i++) { // 为每个?占位符设置参数
                    pstmt.setObject(i + 1, params[i]);
                }
            }
            return rs = pstmt.executeQuery();
        } catch (SQLException e) {
            throw new JdbcSessionException("执行查询操作失败", e);
        }
    }

    JDBC之DAO模式

    主要功能:是实现对持久化数据的访问。 

    DAO的组成部分包括以下四个内容:

    • 数据库操作辅助类:实现数据库操作辅助功能,如获取连接,关闭连接等
    • 实体类:用于数据传递
    • DAO接口:约定DAO功能
    • DAO接口的实现类:具体实现DAO功能

    使用JDBC处理MySQL大文本和大数据

    向MySQL中存储大文本,可调用JDBC API中PreparedStatement的如下方法:

    // 将指定参数设置为给定 Reader 对象
    void setCharacterStream(int parameterIndex, Reader reader) throws SQLException 
    // 将给定参数设置为给定 Reader 对象,该对象具有给定字符数长度(int型)
    void setCharacterStream(int parameterIndex, Reader reader, int length) throws SQLException 
    // 将指定参数设置为给定 Reader 对象,该对象具有给定字符数长度(long型)
    void setCharacterStream(int parameterIndex, Reader reader, long length) throws SQLException 

    从MySQL数据库中获取大文本列字段值,则可以使用ResultSet的如下方法:

    // 以 java.io.Reader 对象的形式获取此 ResultSet 对象的当前行中指定列的值
    Reader getCharacterStream(int columnIndex) throws SQLException
    Reader getCharacterStream(String columnLabel) throws SQLException
    
    // 以 String 的形式获取此 ResultSet 对象的当前行中指定列的值
    String getString(int columnIndex) throws SQLException
    String getString(String columnLabel) throws SQLException

    向MySQL中存储二进制数据,可调用JDBC API中PreparedStatement的如下方法:

    // 将指定参数设置为给定输入流。 
    void setBinaryStream(int parameterIndex, InputStream x) 
    // 将指定参数设置为给定输入流,该输入流将具有给定字节数(int型)。 
    void setBinaryStream(int parameterIndex, InputStream x, int length) 
    // 将指定参数设置为给定输入流,该输入流将具有指定字节数(long型)。 
    void setBinaryStream(int parameterIndex, InputStream x, long length) 

    需要从MySQL数据库中获取二进制列字段值,则可以使用ResultSet的如下方法:

    // 以未解释字节的流的形式获取此 ResultSet 对象的当前行中指定列的值。
    InputStream getBinaryStream(int columnIndex) 
    // 以未解释的 byte 流的形式获取此 ResultSet 对象的当前行中指定列的值。
    InputStream getBinaryStream(String columnLabel) 
    
    // 以 Java 编程语言中 Blob 对象的形式获取此 ResultSet 对象的当前行中指定列的值。 
    Blob getBlob(int columnIndex)
    // 以 Java 编程语言中 Blob 对象的形式获取此 ResultSet 对象的当前行中指定列的值。
    Blob getBlob(String columnLabel)

    XML解析技术

    XML概述:

      被设计用来传输和存储数据的可扩展标记语言。

      通过XML我们可以自定义自己的标签:

    <mail>
        <from>tom</from>
        <to>lily</to>
        <detail>I will go home this weekend!</detail>
    </mail>

      XML是一种树结构。树是一种重要的非线性数据结构,直观地看,它是数据元素(在树中称为结点)按分支关系组织起来的结构

      XML文档必须包含根元素,该元素是所有其他元素的父元素

    XML语法规则

      XML声明,如:

        <?xml version="1.0" encoding="utf-8"?>
    

      它定义XML的版本(1.0)和所使用的编码(utf-8)字符集。

      所有的XML元素都是成对出现的,有一个开始标签,就必须有一个关闭标签。

      XML标签对大小写敏感,标签<Letter>与标签<letter>是不同的。

      XML文档必须有根元素,标签如果需要嵌套,必须正确嵌套,在内层打开的标签就必须在内层关闭。

      XML标签如果需要添加属性,属性值必须加引号。

      在XML中编写注释的语法与HTML的语法很相似,都是 <!– This is a comment –>。

      在XML中,空格会被保留,不像HTML中,加再多的空格最终都只合并为一个。

    XML命名规则

    XML元素必须遵循以下命名规则:

    • 名称可以包含字母、数字以及其他的字符
    • 名称不能以数字或者标点符号开始
    • 名称不能以字母 xml(或者 XML、Xml 等等)开始
    • 名称不能包含空格
    • 可使用任何名称,没有保留的字词。

    DTD 

      作用:是定义XML文档的合法构建模块

    声明一个元素:

      <!ELEMENT 元素名称 (元素内容)>

    空元素:

      <!ELEMENT 元素名称 EMPTY>

    PCDATA 的元素通过圆括号中的#PCDATA进行声明:

      <!ELEMENT 元素名称 (#PCDATA)>

    带任何元素的内容:

      <!ELEMENT 元素名称 ANY>

    带有子元素(序列)的元素: 

     <!ELEMENT 元素名称 (子元素名称 1,子元素名称 2,.....)>

    注意:

    当子元素按照由逗号分隔开的序列进行声明时,这些子元素必须按照相同的顺序出现在文档中。在一个完整的声明中,子元素也必须被声明,同时子元素也可拥有子元素。“mail”元素的完整声明是:

    <!ELEMENT mail (from,to,detail)>

    <!ELEMENT mail (from,to,detail)> <!ELEMENT from (#PCDATA)> <!ELEMENT to (#PCDATA)> <!ELEMENT detail (#PCDATA)>

    声明只出现一次的元素:  
      <!ELEMENT 元素名称 (子元素名称)>
    声明最少出现一次的元素:  
      <!ELEMENT 元素名称 (子元素名称+)>
    声明出现0次或多次的元素: 
      <!ELEMENT 元素名称 (子元素名称*)>
    声明出现0次或1次的元素:   
      <!ELEMENT 元素名称 (子元素名称?)>
    声明属性
      
    <!ATTLIST 元素名称 属性名称 属性类型 默认值>

    CDATA - (未解析)字符数据 

      CDATA部分不能包含字符串“]]>”,也不允许嵌套的CDATA部分。

      标记CDATA部分结尾的“]]>”不能包含空格或换行。

    <script>
        <![CDATA[
            function matchwo(a,b)
            {
                if (a < b && a < 0)
                    return 1;
                else
                    return 0;
            }
        ]]>
    </script>

    内部的DOCTYPE声明

    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE mail[
    <!ELEMENT mail (from,to,detail)>
    <!ELEMENT from (#PCDATA)>
    <!ELEMENT to (#PCDATA)>
    <!ELEMENT detail (#PCDATA)>
    ]>  
    <mail>
        <from>tom</from>
        <to>lily</to>
        <detail>I will go home this weekend!</detail>
    </mail>

    外部文档声明

    <!ELEMENT mail (from,to,detail)>
    <!ELEMENT from (#PCDATA)>
    <!ELEMENT to (#PCDATA)>
    <!ELEMENT detail (#PCDATA)>

    XML文件:

    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE mail SYSTEM "mail.dtd">   
    <mail>
        <from>tom</from>
        <to>lily</to>
        <detail>I will go home this weekend!</detail>
    </mail>

     

    使用dom4j操作xml   

    1. 创建Document对象

      Document document = DocumentHelper.createDocument();

      Element root = document.addElement(“students”); // 根元素节点

    2. 读取XML文件时,获取Document对象

      SAXReader reader = new SAXReader();

      Document document = reader.read(new File(“student.xml”));

    3. 字符串解析为XML时,获取Document对象

      String text = “tom“;

      Document document = DocumentHelper.parseText(text);

    /**
     * 创建XML文件
     * 
     * @throws IOException
     */
    public void createXml() throws IOException {
        // 创建Document对象
        Document document = DocumentHelper.createDocument();
        // 根元素节点
        Element root = document.addElement("students");
        root.addComment("all students info"); // 添加注释
        Element student = root.addElement("student"); // 根元素节点添加子节点
        student.addAttribute("id", "001"); // 添加节点属性
        Element name = student.addElement("name");
        name.addText("tommy"); // 设置节点文本
        Element age = student.addElement("age");
        age.addText("18");
        // 设置XML美化格式
        OutputFormat format = OutputFormat.createPrettyPrint();
        format.setEncoding("utf-8"); // 编码字符集设置
        // xml写入器
        XMLWriter writer = new XMLWriter(new FileWriter("students.xml"), format);
        // 写操作
        writer.write(document);
        writer.flush();
        writer.close();
    }
    /**
     * 修改xml文件
     * 
     * @throws Exception
     */
    public void modifyXml() throws Exception {
        // 创建SAXReader对象
        SAXReader reader = new SAXReader();
        Document document = reader.read(new File("students.xml"));
        /** 修改内容之一: 如果student节点中id属性的内容为001,则修改成1001。因为查找节点使用到了Xpath,所以还需要将 jaxen-1.1-beta-6.jar 包添加到项目中 */
        List list = document.selectNodes("/students/student/@id");
        Iterator it = list.iterator();
        while (it.hasNext()) {
            Attribute attr = (Attribute) it.next();
            if ("001".equals(attr.getValue()))
                attr.setValue("1001");
        }
        /**
         * 修改内容之二: name项内容若为"tommy",则改为"tom"
         */
        list = document.selectNodes("/students/student/name");
        it = list.iterator();
        while (it.hasNext()) {
            Element name = (Element) it.next();
            if ("tommy".equals(name.getText())) {
                name.setText("tom");
            }
        }
        /** 修改内容之三: 将id="1001"的学生age节点删除,再添加birth节点 */
        list = document.selectNodes("/students/student/@id");
        it = list.iterator();
        while (it.hasNext()) {
            Attribute attr = (Attribute) it.next();
            if ("1001".equals(attr.getValue())) {
                Element parent = attr.getParent();
                Iterator iterator = parent.elementIterator("age");
                if (iterator.hasNext()) {
                    Element elem = (Element) iterator.next();
                    parent.remove(elem);
                }
                Element birth = parent.addElement("birth");
                birth.setText("1995-01-01");
                break;
            }
        }
        /* 将document中的内容写入文件中 */
        // 设置XML美化格式
        OutputFormat format = OutputFormat.createPrettyPrint();
        format.setEncoding("utf-8"); // 编码字符集设置
        // xml写入器
        XMLWriter writer = new XMLWriter(new FileWriter("students.xml"), format);
        writer.write(document);
        writer.close();
    }
    /**
     * 遍历节点
     * 
     * @throws Exception
     */
    public void readXml() throws Exception {
        // 创建SAXReader对象
        SAXReader reader = new SAXReader();
        // 加载xml文件
        Document document = reader.read(new File("students.xml"));
        // 获取根元素节点
        Element root = document.getRootElement();
        // 递归遍历所有节点内容
        read(root);
    }
    
    /**
     * 读节点信息
     * 
     * @param element
     *            student节点
     */
    private void read(Element element) {
        for (int i = 0, size = element.nodeCount(); i < size; i++) {
            Node node = element.node(i); // 获取元素的子节点
            if (node instanceof Comment) // 注释节点
                continue;
            if (node instanceof Element) { // 元素节点
                Element elem = (Element) node;
                System.out.print(elem.getName() + " : ");
                if ("student".equals(node.getName())) { // 是student节点
                    System.out.println();
                    Iterator attr = elem.attributes().iterator(); // student节点属性
                    while (attr.hasNext()) {
                        Attribute at = (Attribute) attr.next();
                        System.out
                                .println(at.getName() + " : " + at.getValue());
                    }
                }
                read((Element) node);
            } else if (node instanceof Text) { // 文本节点
                if (!"".equals(node.getText().trim()))
                    System.out.println(node.getText());
            }
        }
    }

     

    XPath 简介

      在XPath中,有七种类型的节点:元素、属性、文本、命名空间、处理指令、注释以及文档(根)节点。
      
    节点关系:父、子、同胞、先辈、后代

     

      

  • 相关阅读:
    通过vue-cli命令行安装uni-app
    微信小程序中父子通信
    react启动问题
    react 父子通信
    windows下MongoDB的安装和启动服务--转载
    vue中使用骨架 vue-skeleton-webpack-plugin
    像企业一样思考
    Promise原理详解
    如何封装一个Cookie库
    你应该知道的浏览器缓存知识
  • 原文地址:https://www.cnblogs.com/wwg1426802735/p/4491613.html
Copyright © 2011-2022 走看看