MySql数据库二

五、JDBC

jdbc就是操作关系型数据库的规则(接口),数据库厂商需要实现这套接口,并且提供数据库驱动jar包。我们去使用这套接口,真正执行的是对应的驱动包里的实现类。

com.mysql.jdbc.Driver类是mysql提供的实现类,它实现了java.sql.Driver;

1、关于增删改操作调用executeupdate方法:

        // 1.注册驱动(可以省略)
        Class.forName("com.mysql.jdbc.Driver");

        // 2.获取连接,Connection连接对象
        String url = "jdbc:mysql://localhost:3306/db4?characterEncoding=UTF-8";
        Connection conn = DriverManager.getConnection(url,"root","123456");

        // 3.获取执行平台Statement
        Statement statement = conn.createStatement();

        // 3.1通过statement的executeUpdate来创建一张表
        String sql = "create table test(id int, name varchar(20), age int);";
        int i = statement.executeUpdate(sql); // 返回int值表示瘦影响的行数

        System.out.println("i = " + i);

        // 4.关闭流
        statement.close();
        conn.close();

2、执行查询语句调用executeQuery方法:

        // 1.注册驱动
        Class.forName("com.mysql.jdbc.Driver");

        // 2.获取连接Connection
        String url = "jdbc:mysql://localhost:3306/db4";
        Connection conn = DriverManager.getConnection(url,"root","123456");

        // 3.获取执行平台Statement
        Statement statement = conn.createStatement();

        // 4.执行查询语句 executeQuery()
        String sql = "select * from jdbc_user";
        ResultSet resultSet = statement.executeQuery(sql);

        while (resultSet.next()){
            int id = resultSet.getInt("id");
            String username = resultSet.getString("username");
            String password = resultSet.getString("password");
            Date date = resultSet.getDate("birthday");

            System.out.println(id + " : " + username + " : " + password + " : " + date);
        }

        // 5.关闭流
        resultSet.close();
        statement.close();
        conn.close();

需要释放资源的对象:
Connection连接、Statement语句、ResultSet结果集(查询的时候会使用到)。
释放原则:先开后关  ResultSet=>Statement=>Connection。
关闭操作可以放到finally块中执行。

JDBC操作的步骤总结:
1.获取驱动(可以省略);
2.获取连接;
3.获取Statement;
4.处理结果集(只在查询时处理);
5.释放资源;

3、JDBC工具类:

/**
 * JDBC工具类
 */
public class JDBCUtil {

    // 定义常量
    public static final String DRIVERNAME = "com.mysql.jdbc.Driver";
    public static final String URL = "jdbc:mysql://localhost:3306/db4?characterEncoding=UTF-8";
    public static final String USER = "root";
    public static final String PASSWORD = "123456";

    // 静态代码块 注册驱动
    static {
        try {
            Class.forName(DRIVERNAME);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    // 静态方法获取连接
    public static Connection getConnection(){
        try {
            Connection conn = DriverManager.getConnection(URL, USER, PASSWORD);
            return conn;
        } catch (SQLException e) {
            e.printStackTrace();
            return null;
        }
    }

    // 静态方法关闭流
    public static void close(Connection conn, Statement statement){

        if(conn != null && statement != null){
            try {
                statement.close();
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    // 静态方法关闭流
    public static void close(Connection conn, Statement statement, ResultSet resultSet){

        if(conn != null && statement != null && resultSet != null){
            try {
                resultSet.close();
                statement.close();
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

调用JDCB工具类,插入数据为例

    /**
     * 插入数据
     * @throws SQLException
     */
    @Test
    public void testInsert() throws SQLException {

        // 1.获取连接
        Connection conn = JDBCUtil.getConnection();

        // 2.创建Statement
        Statement statement = conn.createStatement();
        // 2.1 创建 插入 ql语句
        String sql = "insert into jdbc_user values(null, 'test3', '123', '2021/2/4')";
        // 2.2 执行sql语句
        int i = statement.executeUpdate(sql);

        // 3.关闭流
        JDBCUtil.close(conn, statement);
    }

SQL注入问题
例如登录问题,用户输入用户名和密码与我们的sql语句进行了拼接,用户输入的内容成为了sql语句的一部分,用户会利用这个漏洞输入一些其他字符串,从而改变sql语句原有的意思。
select * from jdbc_user where username = 'admin' and password = '123456' or 1=1;  -- 这条sql语句不论用户名和密码是否正确都能登录成功。
如何解决:要解决sql注入,就不能让用户输入的数据和我们的SQL语句进行拼接。
预处理对象PreparedStatement,他是Statement的子接口。
        使用预处理对象,他有预编译的功能,提高SQL的执行效率。
        使用预处理对象,通过占位符的方式设置参数,可以有效的防止SQL注入问题

        String sql = "select * from jdbc_user where username = ? and password = ?";
        // 4.获取预处理对象 PreparedStatement
        PreparedStatement ps = conn.prepareStatement(sql);
        // 4.1设置参数
        ps.setString(1, username);
        ps.setString(2, password);

        // 5.执行sql语句
        ResultSet resultSet = ps.executeQuery();

细节:
Statement对象每执行一条SQL,就会发送给数据库,数据库要先编译再执行。也就是每次执行都需要编译。
PreparedStatment会将SQL发给数据库进行一个预编译,然后将预编译的SQL保存起来,这样就只需要编译一次了。当我们执行多次插入操作的时候,只需要设置参数就可以了。也就是只需要编译一次。

Statement和PreparedStatement区别:
1.Statement用于执行静态的SQL,在执行时必须是一个准备好的SQL。
2.PreparedStatement是预编译的SQL语句对象,语句中可以包含动态参数“?”,在执行时可以为“?”动态参数设置值。
3.PreparedStatement可以减少编译次数提高数据库性能。

4、JDBC操作事务

     /**
     * JDBC操作事务
     * @param args
     */
    public static void main(String[] args) {

        Connection conn = null;
        PreparedStatement ps = null;
        try {
            // 1.获取连接
            conn = JDBCUtil.getConnection();
            // 2.开启事务
            conn.setAutoCommit(false); // 手动提交事务
            // 3.获取预处理对象(执行两个插入操作)
            // 3.1 tom账户-500
            ps = conn.prepareStatement("update account set money = money - ? where name = ?");
            ps.setDouble(1,500.0);
            ps.setString(2,"tom");
            ps.executeUpdate();

            // 模拟出现异常
            System.out.println(1 / 0);

            // 3.2 jack账户+500
            ps = conn.prepareStatement("update account set money = money + ? where name = ?");
            ps.setDouble(1, 500.0);
            ps.setString(2, "jack");
            ps.executeUpdate();
            // 4.提及搜事务
            conn.commit();

        } catch (SQLException e) {
            try {
                // 5.出现异常回滚事务
                conn.rollback();
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
            e.printStackTrace();
        } finally {
            // 6.关闭资源
            JDBCUtil.close(conn, ps);
        }

六、数据库连接池和DBUtils

6.1 数据库连接池

数据池技术,管理数据库链接,可以重复使用链接。关闭链接不代表销毁connection,只是将链接进行了归还。

java为数据库连接池提供了公共的接口:javax.sql.DataSource,各数据库厂商需实现这个接口。

6.1.1 DBCP连接池

tomcat内置的连接池。

package com.lagou.utils;

import org.apache.commons.dbcp.BasicDataSource;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

/**
 * DBCP连接池工具类
 */
public class DBCPUtils {

    // 1.定义常量保存数据库链接的相关信息
    public static final String DRIVERNAME = "com.mysql.jdbc.Driver";
    public static final String URL = "jdbc:mysql://localhost:3306/db5?characterEncoding=UTF-8";
    public static final String USERNAME = "root";
    public static final String PASSWORD = "123456";

    // 2.创建连接池对象(由DBCP提供的实现类)
    public static BasicDataSource dataSource = new BasicDataSource();

    // 3.使用静态代码块进行配置
    static {
        dataSource.setDriverClassName(DRIVERNAME);
        dataSource.setUrl(URL);
        dataSource.setUsername(USERNAME);
        dataSource.setPassword(PASSWORD);
        dataSource.setMaxActive(20);
    }

    // 4.获取连接
    public static Connection getConnection() throws SQLException {
        Connection conn = dataSource.getConnection();
        return conn;
    }

    // 5.释放资源
    public static void close(Connection conn, Statement statement){
        try {
            if(conn != null && statement != null){
                conn.close();
                statement.close();
            }

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

    public static void close(Connection conn, Statement statement, ResultSet resultSet){
        try {
            if(conn != null && statement != null && resultSet != null){
                resultSet.close();
                statement.close();
                conn.close();
            }

        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}
package com.lagou.testpool;

import com.lagou.utils.DBCPUtils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

/**
 * 测试DBCP工具类
 */
public class TestDBCP {

    public static void main(String[] args) throws SQLException {

        // 1.获取连接
        Connection conn = DBCPUtils.getConnection();
        // 2.创建Statement
        Statement statement = conn.createStatement();
        // 3.执行SQL语句
        String sql = "select * from employee";
        ResultSet resultSet = statement.executeQuery(sql);
        // 4.处理结果集
        while (resultSet.next()){
            String ename = resultSet.getString("ename");
            System.out.println(ename);
        }
        // 5.关闭资源
        DBCPUtils.close(conn, statement, resultSet);
    }
}

6.1.2 C3P0 连接池

需要的jar: c3p0-0.9.5.2.jar和mchange-commons-0.2-12.jar

使用配置文件的方式:c3p0-config.xml

    // c3p0对dataSource接口的实现类
    // 使用配置文件中默认的配置
//    public static ComboPooledDataSource dataSource = new ComboPooledDataSource();

    // 使用指定的配置
    public static ComboPooledDataSource dataSource = new ComboPooledDataSource("mysql");

6.1.3 Druid连接池(德鲁伊连接池)

需要jar:druid-1.0.9.jar

    // 创建成员变量
    public static DataSource dataSource;

    // 静态代码块 加载配置文件 为成员变量赋值
    static {
        try {
            // 创建属性集对象
            Properties properties = new Properties();
            // 加载配置文件,Druid不能主动加载配置文件,需要指定文件
            InputStream is = DruidUtils.class.getClassLoader().getResourceAsStream("druid.properties");
            // 使用Properties对象的 load方法 从字节流中读取配置信息
            properties.load(is);
            // 通过工厂类获取连接池对象
            dataSource = DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

DBUtils工具类 
需要comons-dbutils-1.6.jar 

表和类之间的关系:
1、可以将一张表肯做一个类。表中的列与类中的成员变量对应。一个对象对应表中的一条数据。

javaBean类要求:
1、实现Serializable接口;
2、成员变量私有化;
3、提供get、set方法;
4、提供无参构造方法;

QueryRunner核心类:
两种创建方式:
// 方式1 手动模式 QueryRunner qr1 = new QueryRunner();
// 方式2 自动模式,需要提供数据库连接池对象 QueryRunner qr2 = new QueryRunner(DruidUtils.getDataSource());

    /**
     * 插入一条数据
     * @throws SQLException
     */
    @Test
    public void testInsert() throws SQLException {

        // 1.创建QueryRunner 手动模式
        QueryRunner qr = new QueryRunner();

        // 2.创建SQL语句 占位符方式
        String sql = "insert into employee values(?, ?, ?, ?, ?, ?)";

        // 3.设置占位符参数
        Object[] params = {null, "张百万", 20, "男",8000.0, "2021-2-7"};

        // 4.执行update方法
        Connection conn = DruidUtils.getConnection();
        qr.update(conn, sql, params);

        // 5.关闭资源
        DbUtils.closeQuietly(conn);
    }

    /**
     * 更新数据
     */
    @Test
    public void testUpdate() throws SQLException {

        // 1.自动方式创建QueryRunner对象
        QueryRunner qr = new QueryRunner(DruidUtils.getDataSource());

        String sql = "update employee set salary = ? where ename = ?";

        Object[] params = {12000.0, "张百万"};

        // 执行SQL语句 自动模式,不需要传入connection', 不需要手动去关闭资源
        qr.update(sql, params);
    }

ResultSetHandler 查询
实现类:
ArrayHandler

    /**
     * 查询id为5的记录,封装到数组中 ArrayHandler
     */
    @Test
    public void testFindById() throws SQLException {

        QueryRunner qr = new QueryRunner(DruidUtils.getDataSource());
        String sql = "select * from employee where eid = ?";
        Object[] query = qr.query(sql, new ArrayHandler(), 5);

        System.out.println(Arrays.toString(query));
    }

ArrayListHandler

    /**
     * 查询所有数据,封装到List集合中  ArrayListHandler
     */
    @Test
    public void testFindAll() throws SQLException {

        QueryRunner qr = new QueryRunner(DruidUtils.getDataSource());
        String sql = "select * from employee";
        List<Object[]> query = qr.query(sql, new ArrayListHandler());
        for (Object[] obj : query){
            System.out.println(Arrays.toString(obj));
        }
    }

BeanHandler

    /**
     * 查询id为5的记录,封装到指定JavaBean中
     * BeanHandler 查询结果封装到javaBean中
     */
    @Test
    public void testFindByIdJavaBean() throws SQLException {
        QueryRunner qr = new QueryRunner(DruidUtils.getDataSource());
        String sql = "select * from employee where eid = ?";

        Employee employee = qr.query(sql, new BeanHandler<Employee>(Employee.class), 5);

        System.out.println(employee.toString());
    }

BeanListHandler

    /**
     * 查询薪资大于 3000 的所员工信息,封装到JavaBean中再封装到List集合中
     * BeanListHandler 查询结果每条封装到javabean中,再封装到list集合中
     */
    @Test
    public void testFindBySalary() throws SQLException {
        QueryRunner qr = new QueryRunner(DruidUtils.getDataSource());
        String sql = "select * from employee where salary > ?";

        List<Employee> query = qr.query(sql, new BeanListHandler<Employee>(Employee.class), 1);

        for(Employee e : query){
            System.out.println(e.toString());
        }
    }

MapHandler

    /**
     * 查询姓名是 张百万的员工信息,将结果封装到Map集合中
     * MapHandler 查询结果的第一条封装到map集合中
     */
    @Test
    public void testFindByName() throws SQLException {

        QueryRunner qr = new QueryRunner(DruidUtils.getDataSource());
        String sql = "select * from employee where ename = ?";
        Map<String, Object> res = qr.query(sql, new MapHandler(), "张百万");

        Set<Map.Entry<String, Object>> entries = res.entrySet();
        for (Map.Entry<String, Object> en : entries){
            System.out.println(en.getKey() + " = " + en.getValue());
        }
    }

ScalarHandler

    /**
     * 查询所有员工的薪资总额
     * ScalarHanler 用于封装单个数据
     */
    @Test
    public void testFindSumSalary() throws SQLException {

        QueryRunner qr = new QueryRunner(DruidUtils.getDataSource());
        String sql = "select sum(salary) from employee";
        Double sum = (Double)qr.query(sql, new ScalarHandler<>());
        System.out.println("员工总薪资:" + sum);
    }

6.2 批处理

rewriteBatchedStatements=true

    public static void main(String[] args) throws SQLException {

        Connection conn = DruidUtils.getConnection();

        String sql = "insert into testBatch (uname) values(?)";
        PreparedStatement ps = conn.prepareStatement(sql);

        for(int i=0; i<10000; i++){
            ps.setString(1, "admin" + i);
            // 将SQL添加到批处理列表
            ps.addBatch();
        }
        // 统一执行批量执行操作
        ps.executeBatch();

        DruidUtils.close(conn, ps);
    }

6.3 元数据

元数据:
查询结果信息:UPDATE或DELETE语句,受影响的记录数。
数据库和数据表的信息:包含了数据库和数据表的结构信息。
MYSQL服务器信息:包含了数据库服务器的当前状态,版本号。


-- 元数据相关命令介绍

-- 1.查看服务器当前状态
SHOW STATUS;

-- 2.查看MYSQL的版本信息
SELECT VERSION();

-- 3.查询表中的详细信息
SHOW COLUMNS FROM employee;

-- 4.显示表的详细索引信息
SHOW INDEX FROM employee;

-- 5.列出所有数据库
SHOW DATABASES;

-- 6.显示当前数据库的所有表
SHOW TABLES;

-- 7.获取当前的数据库名
SELECT DATABASE();

JDBC获取数据源信息:

    /**
     * 数据库元数据对象 DataBaseMetaData
     */
    @Test
    public void testDataBaseMetaData() throws SQLException {
        // 1.获取连接
        Connection conn = DruidUtils.getConnection();
        // 2.获取代表数据库的元数据对象 DataBaseMetaData
        DatabaseMetaData databaseMetaData = conn.getMetaData();
        // 3.获取数据库相关的元数据信息
        String url = databaseMetaData.getURL();
        System.out.println("url = " + url);
        String username = databaseMetaData.getUserName();
        System.out.println("username = " + username);
        String databaseProductName = databaseMetaData.getDatabaseProductName();
        System.out.println("数据库产品名:" + databaseProductName);
        String databaseProductVersion = databaseMetaData.getDatabaseProductVersion();
        System.out.println("数据库产品版本:" + databaseProductVersion);
        String driverName = databaseMetaData.getDriverName();
        System.out.println("驱动名:" + driverName);
    }
    /**
     * 结果集元数据信息 ResultSetMetaDate
     */
    @Test
    public void testResultSetMetaData() throws SQLException {
        Connection conn = DruidUtils.getConnection();
        PreparedStatement ps = conn.prepareStatement("select * from employee");

        ResultSetMetaData metaData = ps.getMetaData();
        int columnCount = metaData.getColumnCount();
        System.out.println("总共有"+columnCount+"列");

        for (int i=1; i<=columnCount; i++){
            String columnName = metaData.getColumnName(i);
            System.out.println(columnName);
            String columnTypeName = metaData.getColumnTypeName(i);
            System.out.println(columnTypeName);
        }
    }

七、XML

7.1 XML

XML能做什么:1.存储数据。2.作为配置文件使用。3.使用XML在网络中传递数据。

<!--XML注释

1.XML中必须进行文档声明
           version 版本信息
           encoding 编码
2.XML的文档声明必须写在第一行
3.XML中的元素标签 命名规则
           标签定义不能使用空格或者冒号
           XML标签名区分大小写
4.XML中只能有一个根元素
5.元素体可以是文本或者还是一个标签
6.属性是元素的一部分,必须出现在开始标签中
           属性值必须使用单引号或者双引号包裹。
           一个元素标签可以定义多个属性值

-->

用XML描述employee信息
 

<?xml version="1.0" encoding="UTF-8" ?>
<employees>
    <employee eid="5">
        <ename>李清照</ename>
        <age>22</age>
        <sex>女</sex>
        <salary>4000</salary>
        <empdate>2018-11-12</empdate>
    </employee>

    <employee eid="5">
        <ename>林黛玉</ename>
        <age>20</age>
        <sex>女</sex>
        <salary>5000</salary>
        <empdate>2019-03-14</empdate>
    </employee>
</employees>

7.2 XML约束

XML约束:规定了XML中标签的书写规则,由框架提供(XML由框架解析)

7.2.1 DTD约束:

DTD文件

    <!ELEMENT students (student+) >
        <!ELEMENT student (name,age,sex)>
        <!ELEMENT name (#PCDATA)>
        <!ELEMENT age (#PCDATA)>
        <!ELEMENT sex (#PCDATA)>
        <!ATTLIST student number ID #REQUIRED>

        <!--
        ELEMENT: 用来定义元素
        students (student+) : 代表根元素 必须是 <students>
        student+ : 根标签中至少有一个 student子元素, + 代表至少一个
        student (name,age,sex): student 标签中包含的子元素,按顺序出现
        #PCDATA: 是普通文本内容
        ATTLIST: 用来定义属性
        student number ID #REQUIRED
        student子元素中 有一个ID属性叫做 number,是必须填写的
        ID: 唯一 值只能是字母或者下划线开头
        -->

引入DTD文件:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE students SYSTEM "student.dtd">
<students>
    <student number="s1">
        <name>杜甫</name>
        <age>20</age>
        <sex>男</sex>
    </student>
</students>

7.2.2 Schema约束

扩展名是xsd,内容是xml格式。

<?xml version="1.0" encoding="UTF-8" ?>
<students
        xmlns="http://www.lagou.com/xml"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.lagou.com/xml student.xsd"
>
    <student number="hehe_1234">
        <name>李白</name>
        <age>200</age>
        <sex>male</sex>
    </student>
    <student number="hehe_0000">
        <name>李白</name>
        <age>200</age>
        <sex>male</sex>
    </student>
</students>

7.3 XML解析

DOM方式:将整个XML读取到内存中,形成一个Document对象。
                   优点:元素与元素之间有结构关系,可以进行CRUD; 缺点:占用内存太多,容易内存溢出;
SAX方式:一遍扫描一遍解析,速度更快。
                 优点:占用内存少,速度快。  缺点:只能进行解析操作(读)。

常见的解析器:JAXP、DOM4J、Jsoup、PULL

DOM4j进行解析:

    // 获取XML中所有元素的名称
    @Test
    public void test1() throws DocumentException {

        // 1. 获取XML解析对象
        SAXReader saxReader = new SAXReader();
        // 2.解析XML,获取文档对象Document
        Document document = saxReader.read(new File("D:\\大数据课程\\jdbc_work\\xml_task03\\src\\com\\lagou\\xml03\\user.xml"));
        // 3.获取根元素
        Element rootElement = document.getRootElement();
        // 获取根元素的名称
        System.out.println("根标签:" + rootElement.getName());
        // 4.获取根元素下的标签
        List<Element> elements = rootElement.elements();
        for (Element element : elements){
            System.out.println("跟标签下的子标签:" + element.getName());
            List<Element> elements1 = element.elements();
            for (Element element1 : elements1){
                System.out.println(element1.getName());
            }
            break;
        }
    }
    // 获取标签中的文本信息 和 属性
    @Test
    public void test2() throws DocumentException {
        // 1.获取XML解析对象
        SAXReader saxReader = new SAXReader();
        // 2.解析XML,获取Document对象
        Document document = saxReader.read(new File("D:\\大数据课程\\jdbc_work\\xml_task03\\src\\com\\lagou\\xml03\\user.xml"));
        // 3.获取根节点
        Element rootElement = document.getRootElement();
        List<Element> elements = rootElement.elements();
        // 4.获取第一个子节点
        Element user = elements.get(0);

        String id = user.attributeValue("id");
        String name = user.elementText("name");
        String age = user.elementText("age");
        String hobby = user.element("hobby").getText();
        System.out.println(id + ", " + name + ", " + age + ", " + hobby);
    }

XPath解析:
需要导入jar包jaxen-1.1-beta-6.jar,主要是两个方法:document.selectSingleNode()和document.selectNodes()

    /**
     * 使用selectSingleNode 获取单个节点 标签
     */
    @Test
    public void test1() throws DocumentException {
        SAXReader saxReader = new SAXReader();
        Document document = saxReader.read(new File("D:\\大数据课程\\jdbc_work\\xml_task03\\src\\com\\lagou\\xml04\\book.xml"));

        Node node = document.selectSingleNode("/bookstore/book/name");
        String name = node.getName();
        System.out.println("节点名称:" + name);
        String text = node.getText();
        System.out.println("书名:" + text);

        Node node1 = document.selectSingleNode("bookstore/book[3]/name");
        System.out.println("节点名称:" + node1.getName());
        System.out.println("书名:" + node1.getText());
    }

    /**
     * 通过XML获取属性值,通过属性值获取节点信息
     */
    @Test
    public void test2() throws DocumentException {
        SAXReader saxReader = new SAXReader();
        Document document = saxReader.read(new File("D:\\大数据课程\\jdbc_work\\xml_task03\\src\\com\\lagou\\xml04\\book.xml"));

        // 1.获取第一个book节点中的  id属性的值
        Node node = document.selectSingleNode("/bookstore/book/attribute::id");
        System.out.println("第一个节点id属性值:" + node.getText());

        // 2.获取最后一个book节点的 id属性值
        Node node1 = document.selectSingleNode("/bookstore/book[last()]/attribute::id");
        System.out.println("最后一个节点id属性值:" + node1.getText());

        // 3.通过id的值 获取book2节点 中的书名
        Node node2 = document.selectSingleNode("/bookstore/book[@id='book2']/name");
//        String name = node2.selectSingleNode("name").getText();
        System.out.println("book2节点的书名:" + node2.getText());
    }
    /**
     * 使用selectNodes() 获取所有指定名称的 节点
     */
    @Test
    public void test3() throws DocumentException {
        SAXReader saxReader = new SAXReader();
        Document document = saxReader.read(new File("D:\\大数据课程\\jdbc_work\\xml_task03\\src\\com\\lagou\\xml04\\book.xml"));

        // 1. 获取所有的节点
        List<Node> list = document.selectNodes("//*");
        for (Node node : list){
            System.out.println(node.getName());
        }

        // 2.获取所有的书名
        List<Node> list1 = document.selectNodes("//name");
        for (Node node1 : list1){
            System.out.println("书名:" + node1.getText());
        }

        // 3.获取 id值为 book1 的节点中的所有内容
        List<Node> list2 = document.selectNodes("/bookstore/book[@id='book1']//*");
        for (Node node : list2){
            System.out.println(node.getName() + " = " + node.getText());
        }
    }

JDBCUtils配置文件的编写:
 

<?xml version="1.0" encoding="UTF-8" ?>
<jdbc>
    <property name="driverClass">com.mysql.jdbc.Driver</property>
    <property name="jdbcUrl">jdbc:mysql://localhost:3306/db5?characterEncoding=UTF-8</property>
    <property name="user">root</property>
    <property name="password">123456</property>
</jdbc>
package com.lagou.xml05;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class JDBCUtils {

    private static String DRIVERCLASS;
    private static String URL;
    private static String USERNAME;
    private static String PASSWORD;

    static {
        // 使用XPath方式 对xml中的数据进行读取
        SAXReader saxReader = new SAXReader();
        try {
            Document document = saxReader.read(new File("D:\\大数据课程\\jdbc_work\\xml_task03\\src\\com\\lagou\\xml05\\jdbc-config.xml"));
            Node driver = document.selectSingleNode("/jdbc/property[@name='driverClass']");
            DRIVERCLASS = driver.getText();
            Node url = document.selectSingleNode("/jdbc/property[@name='jdbcUrl']");
            URL = url.getText();
            Node userName = document.selectSingleNode("/jdbc/property[@name='user']");
            USERNAME = userName.getText();
            Node password = document.selectSingleNode("/jdbc/property[@name='password']");
            PASSWORD = password.getText();
//            System.out.println();
            // 注册驱动
            Class.forName(DRIVERCLASS);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //  获取连接
    public static Connection getConnection(){
        try {
            Connection connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
            return connection;
        } catch (SQLException e) {
            e.printStackTrace();
            return null;
        }
    }


}

八、MYSQL高级

MySql逻辑架构——>Mysql分层:连接层、服务层、引擎层、文件系统层

备份按照业务进行划分:完全备份、差异备份、增量备份。

备份按照运行状态:冷备份和热备份。

导致SQL性能下降的原因:
1、等待时间长:锁表导致查询一直处于等待状态;
2、执行时间长:查询语句写的烂、索引失效、关联查询太多join、服务器调优及各个参数的设置;

编写出更高效的SQL:
1、只返回需要的结果:where过滤掉不需要的数据、避免使用select * from;
2、确保查询使用了正确的索引:经常出现在where、order by、多表链接查询关联字、group by 后面加索引;
3、避免索引失效:

存储引擎:就是如何存储数据、如何为存储的数据建立索引和如何更新、查询数据等技术的实现方法。 (主要是用来操作物理文件的)
存储引擎作用:并发性、事务支持、引用的完成性、索引的支持
默认是 支持事务的存储引擎InnoDB。
InnoDB:有点:支持事务、支持并发控制的行级锁、支持自增、支持外键、适用于大容量数据库,支持自动灾难备份。
MYisAM:有点:速度快;缺点:不支持事务和行级锁和外键;(适用于读操作比较多的)
Memory:把数据存储在内存中;(存储的数据是临时的)

索引:主键索引、普通索引、唯一索引、复合索引、全局索引

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值