五、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:把数据存储在内存中;(存储的数据是临时的)
索引:主键索引、普通索引、唯一索引、复合索引、全局索引