JDBC和XML
JDBC是一套操作关系型数据库的规则(接口),数据库厂商需要实现这套接口,并提供数据库驱动jar包。
开发人员使用这套接口,真正执行的是对应的驱动包中的实现类。
1 JDBC环境配置
1.1 MySQL驱动包
mysql-connector-java-5.1.37.zip下载 _
将其中的
mysql-connector-java.5.1.37-bin.jar
复制到自定义的jar仓库,
1.2 新建Java项目并添加驱动包
在IDEA中新建空项目后,CTRLALTSHIFTL打开ProjectStructure对话框,在Project选项卡中添加Java的SDK,在Libraries选项卡中添加jar仓库。
1.3 注册驱动
在main方法中添加
Class.forName("com.mysql.jdbc.Driver");
2 JDBC基本操作
2.1 JDBC操作流程
2.1.1 获取连接对象
DriverManager.getConnection(url,user,password);//其中url的格式如下:
jdbc:mysql://主机地址:端口号/数据库名?参数名=参数
jdbc:mysql://localhost:3306?characterEncoding=UTF-8
2.1.2 获取语句执行平台对象Statement
Statement类常用方法功能说明int executeUpdate(String sql);执行insert、update、delete语句,返回int类型,表示受影响的行数ResuoltSet executeQuery(String sql);执行select语句,返回ResultSet结果集对象
- 获取语句执行平台对象
Statement statement = connection.createStatement();
- 创建一张表
String sql_CreateTable ="create table test(id int,name varchar(20),age int)";int i = statement.executeUpdate(sql_CreateTable);
- 执行查询操作,获得ResultSet结果集合
String sql_Select ="select * from jdbc_user";ResultSet resultSet = statement.executeQuery(sql_Select);//打印获得的数据while(resultSet.next()){int id = resultSet.getInt("id");String username = resultSet.getString("username");String password = resultSet.getString("password");Date birthday = resultSet.getDate("birthday");System.out.println("id:"+ id +"username:"+ username +"password:"+ password +"birthday:"+ birthday);}
2.1.3 释放资源
- 需要释放的对象:ResultSet结果集,Statement语句,Connection连接。
- 释放原则:类似出入栈规则
- 以下代码可以放到try/catch/finally中的finally里
//顺序不能变
resultSet.close();
statement.close();
connection.close();
2.3 JDBC实现增删改查
2.3.1 工具类的创建
可以新建JDBCUtils工具类,存放数据库连接关闭、增删改查语句的静态方法,方便项目中操作数据库。
工具类中包含的内容:
- 可以把几个字符串定义成常量:用户名,密码,URL,驱动类
- 得到数据库连接的方法:
getConnection()
- 关闭所有打开的资源方法:
close()
//1.定义常量publicstaticfinalString DRIVERNAME ="com.mysql.jdbc.Driver";//2.静态代码块→随类的加载而加载一次static{Class.forName(DRIVERNAME);}//3.获取连接的静态方法publicstaticConnectiongetConnection(){}//4.关闭资源(重载)publicstaticvoidclose(Connection ct,Statement sm){}publicstaticvoidclose(Connection ct,Statement sm,ResultSet rs){}
2.3.2 DML(增删改)操作
- 解决插入中文乱码的问题
//指定字符的编码、解码格式jdbc:mysql://localhost:3306/db?characterEncoding=UTF-8
- 添加注解在自定义成员方法前添加注解后,就可以单独运行该方法。
- 增删改
//1.获取连接Connection con =JDBCUtils.getConnection();//2.获取Statement对象Statement statement = con.createStatement();//3.sql语句操作statement.executeUpdate("插入数据的语句");
注意最后关闭流
2.3.3 DQL(查询)操作
//1.获取连接Connection con =JDBCUtils.getConnection();//2.获取Statement对象Statement statement = con.createStatement();//3.sql语句操作ResultSet rs = statement.executeQuery("查询数据的语句");//4.处理结果集while(rs.next()){int i = rs.getInt(字段名);String str = rs.getString(字段名);...}//5.关闭资源
2.4 预处理
在程序中如果用户输入可以直接于编写的SQL进行拼接,则会产生SQL注入漏洞。
在此使用预处理对象PrepareStatement
作为Statement接口的子接口,有预编译的功能,通过占位符的方式设置参数,可以有效防止SQL注入。
2.4.1 预处理对象执行原理
只编译一次SQL语句,并将SQL缓存,用户输入的只是用作参数来被调用。
2.4.2 预处理对象使用(重要)
//1.获取连接Connection con =JDBCUtils.getConnection();//2.获取预处理对象,通过占位符?设置参数String sql ="select * from table_user where username = ? and password = ?";PreparedStatement ps = con.prepareStatement(sql);//3.获取用户输入Scanner sc =newScanner.(System.in);String name = sc.nextLine();String password = sc.nextLine();//4.设置参数使用setXXX方法
ps.setString(1,name);
ps.setString(2,password);//5.执行查询ResultSet rs = ps.executeQuery();//6.处理结果集//7.关闭流
2.4.3 Statement与PreparedStatement的区别
- Statement用于执行静态SQL语句,在执行时,必须指定一个实现准备好的SQL语句。
- PrepareStatement是预编译的SQL语句对象,语句中可以包含动态参数“?”,在执行时可以动态设置参数值。
- PrepareStatement可以减少编译次数提高数据库的性能。
2.5 JDBC控制事务
//1.获取连接Connection con =JDBCUtils.getConnection();//2.开启事务
con.setAutoCommit(false);//手动提交事务//3.获取预处理对象并执行String sql ="";PreparedStatement ps = con.prepareStatement(sql);
ps.executeUpdate();//4.提交事务
con.commit();//--------------------------------------------------////5.如果提交失败,则回滚操作
con.rollback();//6.释放资源
3 数据库连接池
用于管理数据库连接,可以重复使用连接。
关闭连接不代表销毁connection,只是将连接进行了归还。
3.1 数据库连接池介绍
Java中提供了公共接口:
javax.sql.DataSource接口
,与JDBC类似,数据库厂商需要实现该接口。
常见的数据库连接池有DBCP连接池,C3P0连接池,Druid连接池。
3.2 DBCP连接池
DBCP是一个开源的连接池,是Apache成员之一,Tomcat中内置。
3.2.1 配置
将commons-dbcp-1.4.jar和commons-pool-1.5.6.jar两个包 _复制到上文中提到的
myjar
路径下,在IDEA中新建项目后,CTRLALTSHIFTL打开ProjectStructure对话框,在Modules选项卡按照下图所示操作,添加myjar。
3.2.2 自定义工具类DBCPUtils
//1.自定义常量,保存数据库连接的驱动、地址等信息publicstaticfinalString DRIVERNAME ="com.mysql.jdbc.Driver";//2.创建连接池对象publicstaticBasicDataSource dataSource =newBasicDataSource();//3.使用静态代码块设置参数static{
dataSource.setDriverClassName(DRIVERNAME);
dataSource.setUrl();
dataSource.setUsername(USERNAME);
dataSource.setPassword(PASSWORD);}//4。获取连接对象publicstaticConnectiongetConnection(){Connection con = dataSource.getConnection();return connection;}//5.释放资源(归还连接)(重载)publicstaticvoidclose(Connection con,Statement sm){/*先判断非空*/}publicstaticvoidclose(Connetion con,Statement sm,ResultSet rs){/*先判断非空*/}
3.2.3 常见的配置项
在DBCPUtils中可以定义以下参数
属性含义driverClassName数据库驱动名称url数据库地址username用户名password密码maxActive最大连接数量(默认为8)maxIdle最大空闲连接(默认为8)minIdle最小空闲连接(默认为0)initialSize初始化连接
3.2.4 连接池测试
//1.获取连接Connection con =DBCPUtils.getConnection();//2.获取预处理对象String sql ="select * from table where name = ?";PreparedStatement ps = con.prepareStatement(sql);//3.设置占位符的值
ps.setString(1,"...");ResultSet rs = ps.executeQuery();//4.处理结果集while(rs.next()){int id = rs.getInt("id");System.out.println(id);}//5.释放资源DBCPUtils.close(rs,ps,con);
3.3 C3P0连接池
C3P0是一个开源的JDBC连接池,支持JDBC3规范和JDBC2的标准扩展,目前使用它的开源项目有Hibernate,Spring等。
3.3.1 导入配置文件
将c3p0-0.9.5.2.jar和mchange-commons-java-0.2.12.jar _导入上文提到的
myjar
路径下。
导入配置文件
c3p0-config.xml
,将该文件直接放到src或资源文件夹中。资源文件夹是指在项目下新建目录,然后右击→Mark Directory as→Surces Root。
3.3.2 修改配置参数
在
c3p0-config.xml
文件中添加以下内容:
<!--配置连接池mysql--><named-configname="mysql"><propertyname="driverClass">com.mysql.jdbc.Driver</property><propertyname="jdbcUrl">jdbc:mysql://IP地址/数据库名?characterEncoding=UTF-8</property><propertyname="user">用户名</property><propertyname="password">连接密码</property><propertyname="initialPoolSize">初始化连接数量10</property><propertyname="maxIdleTime">最大空闲时间30</property><propertyname="maxPoolSize">最大线程池大小100</property><propertyname="minPoolSize">最小连接池大小10</property></named-config><!--配置连接池2,可以配置多个-->
分类属性描述必须项user用户名password密码driverClass驱动jdbcUrl路径基本配置initialPoolSize连接池初始化时创建的连接数,默认3maxPoolSize连接池中拥有的最大连接数,默认15minPoolSize连接池保持的最小连接数,默认10maxIdleTime连接的最大空闲时间,如果超过此时间某个数据库还没有被使用,则会断开这个连接;如果为0,则永远不断开连接。默认0
3.3.3 自定义C3P0Utils工具类
//1.创建连接池对象C3P0对DATa Source接口的实现类//使用的是默认文件中的配置publicstaticComboPooledDataSource dataSource =newComboPooledDataSource();//如果要使用指定的配置,比如上文中自定义的连接池mysqlpublicstaticComboPooledDataSource dataSource =newComboPooledDataSource("mysql");//获取连接的方法publicstaticConnectiongetConnection(){return dataSource.getConnection();}//释放资源(方法重载)publicstaticvoidclose(Connection con,Statement sm,ResultSet rs){/*先判断非空*/}
3.3.4 测试
(同上,此处不赘述)
3.4 Druid连接池
由阿里巴巴开发,加入了日志监控。
3.4.1 导入jar包及配置文件
将druid-1.0.9.jar _复制到上文提到的
myjar
路径下。
将druid.properties _复制到src或自定义资源文件夹下。
3.4.2 修改配置参数(注意编码UTF-8)
3.4.3 自定义DruidUtils类
此处需要通过工厂类DruidDataSourceFactory类的CreateDataSource()方法来获取对象,并使用Properties对象的load方法来读取配置信息。
publicstaticDataSource dataSource;static{//1.创建属性集对象Properties p =newProperties();//2.指定加载的配置文件InputStream ins =DruidUtils.class.getClassloader().getResourceAsStream("druid.properties");//3.调用Properties对象的load方法从字节流中读取配置信息
p.load(ins);//4.通过工厂类获取连接池对象
dataSource =DruidDataSourceFactory.createDataSource(p);}//5.获取连接的方法publicstaticConnectiongetConnection(){};//6.释放资源的方法publicstaticvoidclose(Connection con,Statement st,ResultSet rs){/*先判断非空*/}
4 DBUtils工具类
Commons DBUils是Apache组织提供的一个对JDBC进行简单封装的开源工具类库,能够在保证性能的同时简化程序开发。
4.1 配置
导入配置文件,将commons-dbutils-1.6.jar _复制到上文提到的
myjar
路径下。
4.2 QueryRunner类
4.2.1 增删改操作
//1.创建QueryRunner对象QueryRunner qr1 =newQueryRunner();//手动模式QueryRunner qr2 =newQueryRunner(DruidUtils.getDataSource());//自动模式,传入的是连接池//2.编写占位符方式的SQL语句String sql ="insert into table_name values(?,?,?)";//3.设置占位符的参数Object[] param ={null,"张san",20};//4.执行update方法Connetion con1 =DruidUtils.getConnection();int i = qr.update(con,sql,param);//手动模式int ii = qr.update(sql,param);//自动模式不需要传入Connection对象//5.释放资源DBUtils.closeQuery(con);
4.2.2 查询操作
需要用到ResultSetHandler实现类
查询方法为
query(String sql,handler,Object[] param)
或
query(Connection con,String sql,hadler,Object[] param)
ResultSetHandler实现类说明ArrayHandler将结果集中的第一条记录封装到一个Object[]数组中,数组中的每一个元素就是这条记录中的每一个字段的值ArrayListHandler将结果集中的每一条记录都封装到一个Object[]数组中,将这些数组再封装到List集合中BeanHandler将结果集中第一条记录封装到指定的javaBean中BeanListHandler将结果集中每一条记录封装到指定的javaBean中,再将这些javaBean封装到List集合中ColumnListHandler将结果集中指定的列的字段值,封装到一个List集合中KeyedHandler将结果集中每一条记录封装到Map<String,Object>,再将这个Map集合作为另一个Map的value,另一个Map集合的key是指定的字段的值MapHandler将结果集中第一条记录封装到了Map<String,Object>集合中,key是字段名称,value是字段值MapListHandler将结果集中每一条记录封装到了Map<String,Object>集合中,key是字段名,value是字段值,再将这些Map封装到List集合中ScalarHandler用于封装单个数据,例如
select count(*) from table_name
操作
//举例说明//1.创建QueryRunnerQueryRunner qr =newQueryRunner(DruidUtils.getDataSource());//2.编写SQLString sql ="select * from table_name";//3.执行查询,封装到ArrayList集合中,封装到其他集合亦类似List<Object[]> query = qr.query(sql,newArrayListHandler());//4.打印for(Object[] objects:query){System.out.println(Arrays.toString(objects));}
4.3 封装到javaBean
QueryRunner qr =newQueryRunner(DruidUtils.getDataSource());String sql ="select * from table_name where id=?";Employee employee = qr.query(sql,newBeanHandler<Employee>(Employee.class),3);
5 批处理
5.1 方法简介
方法说明void addBatch()将给定的SQL命令添加到此Statement对象的当前命令列表中,通过调用方法executeBatch可以批量执行此列表中的命令int executeBatch()每次提交一批命令到数据库中执行,如果所有的命令都成功执行了,那么返回一个数组,这个数组是说明每条命令所影响的行数
5.2 开启批处理
MySQL默认是关闭批处理的,开启需要在Druid的properties文件中的url后添加如下语句:
url=jdbc:mysql://IP地址:3306/数据库名?characterEncoding=UTF-8&rewriteBatchedStatements=true
5.3 操作介绍
//1.获取连接Connection con =DruidUtils.getConnection();//2.获取预处理对象PreparedStatement ps = connection.prepareStatement(sql语句);//3.执行批量插入操作for(int i=0;i<1000;i++){
ps.setString(1,"张三");//将SQL添加到批处理列表
ps.addBatch();}//4.统一执行
ps.executeBatch();//5.关闭连接DruidUtils.close(connection,ps);
6 元数据
包含查询结果信息:UPDATE或DELETE语句受影响的记录数。
数据库和数据表的信息:结构信息。
MySql服务器信息:当前状态、版本号等。
6.1 JDBC获取
获取元数据对象的方法为getMetaData()
- 如果是Connection对象调用该方法,则获取的是DatabaseMetaData数据库元数据对象。
- 如果是PrepareStatement预处理对象调用该方法,则获取的是ResultSetMetaData结果集元数据对象。
6.2 方法介绍
获取元数据方法
元数据对象具体方法方法说明DatabaseMetaDatagetURL()获取数据库的URLgetUser()获取当前数据库的用户名getDatabaseProductName()获取数据库的产品名称(数据库类型)getDatabaseProductVersion()获取数据库的版本号getDriverName()返回驱动程序名称isReadOnly()判断数据库是否只允许读,true表示只读
6.3 方法运用
1.获取数据库相关的元数据信息,使用DatabaseMetaData
//1.获取数据库连接对象Connection con =DruidUtils.getConnection();//2.获取代表数据库的元数据对象DatabaseMetaData metaData = con.getMetaData();//3.获取数据库相关的元数据信息String url = metaData.getURL();String userName = metaData.getUserName();//4.释放资源
con.close();
2.获取结果集中的元数据信息
//1.获取数据库连接Connection con =DruidUtils.getConnection();//2.获取预处理对象PreparedStatement ps = con.prepareStatement(SQL语句);ResultSet rusultSet = ps.executeQuery();//3.获取结果集元数据对象ResultSetMetData metaData = ps.getMetaData();//4.获取结果集信息int count = metaData.getColumnCount();System.out.println(count);//5.释放资源DruidUtils.close(con,ps,resultSet);
7 XML
XML即可扩展性标记语言,与HTML相比标签为自定义、语法严格。可用于:
- 存储数据,与properties文件类似。
- 作为配置文件。
- 在网络中传递数据。
7.1 语法格式
<!-- 1.XML中必须进行文档声明,且必须在第一行
version版本信息
encoding 编码
--><?xml version="1.0" encoding="UTF-8" ?><!-- 2.XML的注释 --><!-- 3.标签区分大小写;定义不能有空格或者冒号;属性必须在标签开头--><user><nameid="1"></name><nameid="2"></name><age><labelcommon>内容为文本的标签</labelcommon><insidelabel></insidelabel></age><emptylabel/></user><!-- 4.XML中有且只有一个根元素,就是最外面包裹的那个标签,比如上文中的user标签--><!-- 5.XML中元素可以是文本或标签,支持标签嵌套--><!-- 6.空标签,如上文中的emptylabel标签-->
7.2 XML约束**
约束文档是由框架提供的,指导XML编写。
约束文件开头需要指定xml版本号等信息:**
<?xml version="1.0" encoding="UTF-8" ?>
**
7.2.1 DTD约束
DTD(Document Type Definition),文档类型定义,用来约束XML文档,规定XML文档中元素的名称,子元素的名称及顺序,元素的属性等。
<!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+:根标签中至少有一个student子元素
student(name,age,sex):student标签中可以包含的子元素,必须按顺序出现
#PCDATA:普通的文本内容
ATTLIST:用来定义属性
student number ID:student标签中,有一个ID属性,叫做number
#REQUIRED:number的属性必须填写,ID唯一,值只能是字母或下划线开头。
- 引用
将.dtd文件放到项目package中,而后在.xml文件中添加引用。
//语法格式<!DOCTYPE 根元素名 SYSTEM ".dtd文件路径">
7.2.2 Schema约束
本身是XML文档,但Schema文档的扩展名为xsd
内置多种简单和复杂的数据类型
支持命名空间,一个XML中可以引入多个约束文档
- 引用
<?xml version="1.0" encoding="UTF-8" ?><studentsxmlns="http://wwww.gfcq.com/xml"<!--表示使用的命名空间-->
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <!--引入W3C的标准命名空间,指定数据类型 -->
xsi:schemaLocation="http://www.gfcq.com/xml student.xsd" <!--指定.xsd文档的路径 -->
>
<!-- 具体的内容--></students>
7.3 XML解析
7.3.1 解析方式
- DOM方式> 将整个XML读取到内存,生成一个document对象。- 元素之间由结构关系,可以进行CRUD- 占用的内存多,容易内存溢出
- SAX方式> 边扫描边解析,速度更快。- 占用内存少,速度快- 只能进行解析操作
7.3.2 解析器DOM4jAPI
- 配置复制dmo4j-1.6.1.jar _到上文提到的
myjar
路径下。 - 解析
//1.获取解析对象SAXReader reader =newSAXReader();//2.解析XML获取文档对象Document doc = reader.read("E:\\jdbc_work\\..\\user.xml");//3.获取根元素Element rootElement = doc.getRootElement();//4.获取子节点List<Element> elements = rootElement.elements();//5.获取集合中的第一个子节点Element user = elements.get(0);//6.获取属性String id = user.attributeValue("id");//获取属性id的值String name = user.elementText("name");
7.4 XPath
基本的XPath语法类似于在一个文件系统中定位问渐渐,如果路径以斜线/开始,那么该路径就表示到一个元素的绝对路径
7.4.1 导入配置文件
复制jaxen-1.1-beta-6.jar _到上文提到的
myjar
路径下。
7.4.2 使用XPath解析XML文件
比如给定这样一个XML文件
book.xml
:
<?xml version="1.0" encoding="UTF-8" ?><bookstore><bookid="book1"><name>水浒传</name><author>施耐庵</author><price>99</price></book><bookid="book2"><name>西游记</name><author>吴承恩</author><price>99</price></book></bookstore>
- 使用selectSingleNode()方法查询自定的节点信息
//1.创建XML解析对象SAXReader reader =newSAXReader();//2.解析XML获取文档对象Document doc = reader.read(文件全路径"H:\\jdbc_work\\xmltask\\src\\com\\...\\book.xml);//3.获取name节点Node node1 = doc.selectSingleNode("/bookstore/book/name");//4.获取第二本书的书名Node node2 = doc.selectSingleNode("/bookstore/book[2]/name");String bookname2 = node2.getText();
- 使用selectSingleNode()方法获取属性值或者通过属性值获取节点信息
SAXReader reader =newSAXReader();Document doc = reader.read(路径);//1.获取第一个book节点中的id属性值Node node1 = doc.selectSingleNode("/bookstore/book/attribute::id");//2.获取最后一个book节点的id属性值Node node2 = doc.selectSingleNode("bookstore/book[last()]/attribute::id");String bookid = node2.getText()://3.通过id的值获取book2节点中的书名Node node3 = doc.selectSingleNode("/bookstore/book[@id='book2']");
- 使用selecNode()方法获取所有指定名称的节点
SAXReader reader =newSAXReader();Document doc = reader.read(路径);//1.查询所有节点List<Node> list1 = doc.selectNodes("//");//2.获取所有书名List<Node> list2 = doc.selectNodes("//name");//3.获取id属性为book1的节点中所有的内容List<Node> list3 = doc.selectNodes("bookstore/book[@id='book1']//*")
7.5 JDBC自定义XML
7.5.1 创建配置文件
jdbc-config.xml
<?xml version="1.0" encoding="UTF-8" ?><jdbc><propertyname="driverClass">com.mysql.jdbc.Driver</property><propertyname="jdbcUrl">jdbc:mysql:localhost:3306/db?characterEncoding=UTF-8</property><propertyname="user">root</property><p-rotertyname="password">123456</p-roterty></jdbc>
7.5.2 创建工具类
//1.定义字符串变量,保存连接信息publicstaticString DRIVERNAME;publicstaticString URL;publicstaticString USER;publicstaticString PASSWORD;//2.静态代码块static{//使用XPath语法对xml中的数据进行读取SAXReader reader =newSAXXReader();Document doc = reader.read(xml文件路径);//1.获取驱动名称Node driver = document.selectSingleNode("/jdbc/property[@name='driverClass']");
DRIVERNAME = driver.getText();//2.获取URLNode url = doc.selectSingleNode("/jdbc/property[@name='jdbcUrl']");
URL = url.getText();//3.获取用户名NodeUser= doc.selectSingleNode("/jdbc/property[@name='user']");
USER = user.getText();//4.获取密码Node password = doc.selectSingleNode("/jdbc/property[@name='password']");
PASSWORD = password.getText();//5.注册驱动Class.forNmae(DRIVERNAME);}//获取连接publicstaticConnectiongetConnection(){Connection con =DriverManager.getConnection(URL,USER,PASSWORD);return con;}
版权归原作者 FisrtBqy 所有, 如有侵权,请联系我们删除。