疯狂Java学习笔记(50)-----------JDBC
1、加载合适的JDBC驱动程序
Class.forName(Driver);
MySQL驱动程序:com.mysql.jdbc.Driver
Oracle驱动程序:oracle.jdbc.driver.OracleDriver
SQLServer驱动程序:
com.Microsoft.jdbc.sqlserver.SQLServerDriver
2、建立数据库连接
与MySQL数据库连接的方法:
Connection con=DriverManager.getConnection(“jdbc:mysql://主机IP或主机名:3306/数据库名”,用户名,密码);
java.sql.DriveManager 用来处理装载驱动程序并且为创建新的数据库连接提供支持;
–java.sql.Connection 用于完成对特定定数据库的连接;
–java.sql.Statement 用于对特定的数据库执行SQL语句;java.sql.Statement又包含了以下两个重要的子类型:
java.sql.PreparedStatement 用于执行预编译的SQL语句;
java.sql.CallableStatement 用于执行数据库中存储的过程的调用;
--java.sql.ResultSet 用于保存查询所得的结果集
3、创建Statement对象
Statement st=con.createStatement(); //最后可以不关闭,但推荐关闭
利用Statement对象可以执行静态SQL语句,静态SQL语句可以是Select语句、Delete语句、Update语句和Insert语句。
执行SQL语句
Statement接口提供了三种执行SQL语句的方法:executeQuery()、executeUpdate() 和execute()。具体使用哪一个方法由SQL语句本身来决定。
方法 executeQuery 用于产生单个结果集的语句,例如 SELECT 语句等。
方法 executeUpdate 用于执行INSERT、UPDATE或DELETE 语句以及SQL DDL(数据定义语言)语句,例如 CREATE TABLE 和 DROP TABLE。INSERT、UPDATE 或DELETE 语句的效果是修改表中零行或多行中的一列或多列。executeUpdate 的返回值是一个 整数,指示受影响的行数(即更新计数)。对于 CREATE TABLE 或DROP TABLE 等不操作行的语句,executeUpdate 的返回值总为零。
方法 execute 用于执行返回多个结果集、多个更新计数或二者组合的语句。一般不会需要该高级功能。
①JDBC在编译时并不对将要执行的SQL查询语句作任何检查,只是将其作为一个String类对象,直到驱动程序执行SQL查询语句时才知道其是否正确。对于错误的SQL查询语句,在执行时将会产生 SQLException。
②一个Statement对象在同一时间只能打开一个结果集,对第二个结果集的打开隐含着对第一个结果集的关闭。
③如果想对多个结果集同时操作,必须创建出多个Statement对象,在每个Statement对象上执行SQL查询语句以获得相应的结果集。
④如果不需要同时处理多个结果集,则可以在一个Statement对象上顺序执行多个SQL查询语句,对获得的结果集进行顺序操作。
str="insertinto customer values('wangyang',24,'beijing','wangyang@sina.com')";
int recordNumber=st.executeUpdate(str);执行executeUpdate()方法返回该SQL语句涉及的记录数。
str="select* from mycustomer"; //查询表中记录
ResultSet rs=st.executeQuery(str); 由于SQL语句是select,用executeQuery()方法,返回一个结果集保存在ResultSet对象rs中。
4、分析ResultSet对象
① 执行完毕SQL语句后,将返回一个ResultSet类的对象,它包含所有的查询结果。但对ResultSet类的对象方式依赖于光标(Cursor)的 类型,而对每一行中的各个列,可以按任何顺序进行处理(当然,如果按从左到右的顺序对各列进行处理可以获得较高的执行效率);
ResultSet类中的Course方式主要有:
ResultSet.TYPE_FORWARD_ONLY(为缺省设置):光标只能前进不能后退,也就是只能从第一个一直移动到最后一个。
ResultSet.TYPE_SCROLL_SENSITIVE:允许光标前进或后退并感应到其它ResultSet的光标的移动情形。
ResultSet.TYPE_SCROLL_INSENSITIVE:允许光标前进或后退并不能感应到其它ResultSet的光标的移动情形。
ResultSet类中的数据是否允许修改主要有:
ResultSet.CONCUR_READ_ONLY(为缺省设置):表示数据只能只读,不能更改。
ResultSet.CONCUR_UPDATABLE:表示数据允许被修改。
可以在创建Statement或PreparedStatement对象时指定ResultSet的这两个特性。
Statement stmt=con.createStatement(ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_READ_ONLY);
或
PreparedStatement pstmt=con.PrepareStatement("insert into bookTable values (?,?,?)",ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE);
② ResultSet类的对象维持一个指向当前行的指针,利用ResultSet类的next()方法可以移动到下一行(在JDBC中,Java程序一次只 能看到一行数据),如果next()的返回值为false,则说明已到记录集的尾部。另外JDBC也没有类似ODBC 的书签功能的方法。
③ 利用ResultSet类的getXXX()方法可以获得某一列的结果,其中XXX代表JDBC中的Java数据类型,如 getInt()、getString()、getDate()等。访问时需要指定要检索的列(可以采用 int值作为列号(从1开始计数)或指定列(字段)名方式,但字段名不区别字母的大小写)。
示例:
while(rs.next()){
int id=rs.getInt("id");
String name=rs.getString("cName");
int age=rs.getInt("cAge");
String address=rs.getString("cAddress");
String email=rs.getString("cEmail");
System.out.println(id+" "+name+" "+age+" "+address+" "+email);
}
获得结果集中的结构信息:利用ResultSet类的getMetaData()方法来获得结果集中的一些结构信息(主要提供用来描述列的数量、列的名称、列的数据类型。利用ResulSetMetaData类中的方法)。
ResultsetMetaData rsmd=rs.getMetaData();
rsmd.getColumnCount(); //返回结果集中的列数
rsmd.getColumnLabel(1); //返回第一列的列名(字段名)
例如:
Statement stmt=con.createStatement();
ResultSet rs=stmt.executeQuery("select * from TableName");
for(int i=1; i<=rs.getMetaData().getColumnCount(); i++) //跟踪显示各个列的名称
{ System.out.print(rs. getColumnName (i)+"\t");
}
while(rs.next())
{ //跟踪显示各个列的值
for(int j=1; j<=rs.getMetaData().getColumnCount(); j++)
{ System.out.print(rs.getObject(j)+"\t");
}
}
5、关闭连接
(注意关闭的顺序) 例:
rs.close();
st.close();
con.close()
6、JDBC的常用API
一、Connection接口:
1.createStatement():创建数据库连接
2.prepareStatement(Stringsql):创建预处理语句
3.prepareCall(Stringsql):创建可调用语句
4.getAutoCommit():获取自动提交的模式
5.setAutoCommit():设置自动提交的模式
6.commit():提交所执行的SQL语句
7.rollback():回滚所执行的SQL语句
8.getMetaData():获取一个DatabaseMetaData对象,该对象包含了有关数据库的基本信息
9.close():关闭数据库连接
10.isClose():判断数据库连接是否超时或被显示关闭
二、Statement接口:
1.execute(Stringsql):执行SQL语句,如果返回值是结果集则为true,否则为false
2.executeQuery(Stringsql):执行SQL语句,返回值为ResultSet
3.executeUpdate(Stringsql):执行SQL语句,返回值为所影响的行数
4.addBatch(Stringsql):向当前Statement对象的命令列表中添加新的批处理SQL语句
5.clearBatch():清空当前Statement对象的命令列表
6.executeBatch():执行当前Statement对象的批处理语句,返回值为每个语句所影响的函数数组
7.getConnection():返回创建了该Statement对象的Connection对象
8.getQueryTimeout():获取等待处理结果的时间
9.setQueryTimeout():设置等待处理结果的时间
三、ResultSet接口:
1.first()/beforeFirst():将游标移动到ResultSet中第一条记录(的前面)
2.last()/afterLast():将游标移动到ResultSet中最后一条记录(的后面)
3.absolute(intcolumn):将游标移动到相对于第一行的指定行,负数则为相对于最后一条记录
4.relative(introws):将游标移动到相对于当前行的第几行,正为向下,负为向上
5.next():将游标下移一行
6.previous():将游标上移一行
7.insertRow():向当前ResultSet和数据库中被插入行处插入一条记录
8.deleteRow():将当前ResultSet中的当前行和数据库中对应的记录删除
9.updateRow():用当前ResultSet中已更新的记录更新数据库中对应的记录
10.cancelUpdate():取消当前对ResultSet和数据库中所做的操作
11.findColumn(StringcolumnName):返回当前ResultSet中与指定列名对应的索引
12.getRow():返回ResultSet中的当前行号
13.refreshRow():更新当前ResultSet中的所有记录
14.getMetaData():返回描述ResultSet的ResultSetMetaData对象
15.isAfterLast():是否到了结尾
16.isBeforeFirst(): 是否到了开头
17.isFirst():是否第一条记录
18.isLast(): 是否最后一条记录
19.wasNull():检查列值是否为NULL值,如果列的类型为基本类型,且数据库中的值为0,那么
这项检查就很重要。由于数据库NULL也返回0,所以0值和数据库的NULL不能区分。如果列的类型为对象,可以简单地将返回值与null比较
20.close():关闭当前ResultSet
四、ResultSetMetaData接口:
1.getColumnCount():返回ResultSet中列的数目
2.getColumnName():返回列在数据库中的名称
3.getColumnType():返回列的SQL类型
4.isReadOnly():表示该数据项是否为只读值
5.isNullable():表示该列是否可以存储NULL
实例:
//DBHelper.java
<span style="font-size:18px;">package com.haixu.jdbc; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; public class DBHelper { public static final String url = "jdbc:mysql://127.0.0.1/test"; public static final String name = "com.mysql.jdbc.Driver"; public static final String user = "root"; public static final String password = "root"; public Connection conn = null; public PreparedStatement pst = null; public DBHelper(String sql) { try { Class.forName(name);//指定连接类型 conn = DriverManager.getConnection(url, user, password);//获取连接 pst = conn.prepareStatement(sql);//准备执行语句 } catch (Exception e) { e.printStackTrace(); } } public void close() { try { this.conn.close(); this.pst.close(); } catch (SQLException e) { e.printStackTrace(); } } } </span>
<span style="font-size:18px;">package com.haixu.jdbc; import java.sql.ResultSet; import java.sql.SQLException; public class Demo { static String sql = null; static DBHelper db1 = null; static ResultSet ret = null; public static void main(String[] args) { sql = "select *from teacher";//SQL语句 db1 = new DBHelper(sql);//创建DBHelper对象 try { ret = db1.pst.executeQuery();//执行语句,得到结果集 while (ret.next()) { String uid = ret.getString(1); String ufname = ret.getString(2); String ulname = ret.getString(3); String udate = ret.getString(4); System.out.println(uid + "\t" + ufname + "\t" + ulname + "\t" + udate ); }//显示数据 ret.close(); db1.close();//关闭连接 } catch (SQLException e) { e.printStackTrace(); } } } </span>
在使用JDBC编程时需要连接数据库,导入JAR包是必须的,导入其它的jar包方法同样如此,导入的方法是
打开eclipse
1.右击要导入jar包的项目,点properties
2.左边选择java build path,右边选择libraries
3.选择add External jars
4.选择jar包的按照路径下的
确定后就行了。
Java连接MySQL的最新驱动包下载地址
http://www.mysql.com/downloads/connector/j
有两种方法导入jar包,第一种是先把jar包放在项目的目录下,通过添加jar包,是使用相对地址的,这样把项目复制到其它电脑也可以用
第二种方法是导入外部的jar包,是绝对地址,如果项目要复制到其它电脑又要重新导入
第一种方法 ,建议使用
第二种方法
添加之后就会出现以下
7.数据库连接池(connection pool)的工作原理
由上面的分析可以看出,问题的根源就在于对 数据库 连接资源的低效管理。我们知道,
在 Java 语言中,Connection类本身提供了对事务的支持,可以通过设置Connection的AutoCommit属性为false,然后显式的调用commit或rollback方法来实现。但要高效的进行Connection复用,就必须提供相应的事务支持机制。可采用每一个事务独占一个连接来实现,这种方法可以大大降低事务管理的复杂性。
连接池的实现
2、连接池实现(经过本人改版,可以适用多数据库类型的应用以及一种数据库类型多个数据库且数据 库的数量可以动态增加的应用程序)
1),DBConnectionPool.java 数据库连接池类
2),DBConnectionManager .java 数据库管理类
3),DSConfigBean .java 单个数据库连接信息Bean
4),ParseDSConfig.java 操作多(这个'多'包括不同的数据库和同一种数据库有多个数据库)
数据 配置文件xml
5),ds.config.xml 数据库配置文件xml
DBCP代码实现:
//创建数据源
public static DataSource setupDataSource(String connectURI) {
BasicDataSource ds = new BasicDataSource();
ds.setDriverClassName(org.gjt.mm.mysql.Driver);
ds.setUsername("username");
ds.setPassword("password");
ds.setUrl(connectURI);
return ds;
}
//关闭数据源
public static void shutdownDataSource(DataSource ds) throws SQLException {
BasicDataSource bds = (BasicDataSource)ds;
bds.close();
}
//数据源的使用
DataSource dataSource = getDataSource();
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
conn = dataSource.getConnection();
pstmt = conn.prepareStatement("select * from users");
rs = pstmt.executeQuery();
while(rs.next()) {
System.out.println(rs.getInt("id"));
}
} catch(Exception e) {
e.printStackTrace();
} finally {
try {
rs.close();
pstmt.close();
conn.close();
} catch(Exception ex) {
ex.printStackTrace();
}
}
在Tomcat中配置数据库连接池:
我们使用Tomcat中lib文件夹下的tomcat-dbcp.jar。
1. 修改server.xml文件在<Service>中写入以下代码:
< Context path="/WebProject" docBase="WebProject" reloadable="true" crossContext="true">
<Resource auth="Container" name="jdbc/CompanyDB" type="javax.sql.DataSource"
factory="org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory"
driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver"
url="jdbc:sqlserver://localhost:1433;DataBaseName=Company"
username="sa"
password="root"
maxActive="100"
maxIdle="30"
maxWait="10000"
removeAbandoned=“true”
removeAbandonedTimeOut="10"
logAbandoned="true"/>
</Context>
path:工程路径。
docBase:工程名字。
name:JNDI的名字。
type:数据源的类。
factory:指定生成的DataReource的factory类名;默认DBCP工厂类。
driverClassName:数据库驱动名。
url:数据库连接的URL。
username:数据库用户名。
password:数据库密码。
maxActive:最大连接数据库数,设为0表示没有限制。
maxIdle:最大等待数量,设为0表示没有限制。
maxWait:最大等待秒数,单位为ms。
removeAbandoned:是否自我中断,默认为false。
removeAbandonedTimeOut:几秒后会自我中断,removeAbandoned必须为true。
logAbandoned:是否记录中断事件,默认为false。
2. 修改web.xml文件,增加一个标签,输入以下代码:
<resource-ref>
<description>Company Connection</description>
<res-ref-name>jdbc/CompanyDB</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
< /resource-ref>
res-ref-name:指定JNDI的名字。
res-type:指定资源类名。
res-auth:指定资源的Manager。
3. 代码中使用JNDI代码进行获取:
Context ctx = new InitalContext();
DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/CompanyDB");
Connection conn = ds.getConnection();
注意:java:comp/env/ 是java中JNDI固定写法。
注意:如果该配置出现错误,采用另一种方式进行配置
在tomcat中的server.xml不进行配置,而在context.xml中进行设置
代码如下:
<Resource name="jdbc/CompanyDB" type="javax.sql.DataSource" password="root"
driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver" maxIdle="2" maxWait="5000" username="sa" url="jdbc:sqlserver://localhost:1433;DataBaseName=Company" maxActive="100"/>
web.xml的设置同上一个配置一样。
数据库连接池 : C3P0、DBCP
1、数据库连接池技术的优点:
/** * 1. 加载 dbcp 的 properties 配置文件: 配置文件中的键需要来自 BasicDataSource * 的属性. * 2. 调用 BasicDataSourceFactory 的 createDataSource 方法创建 DataSource * 实例 * 3. 从 DataSource 实例中获取数据库连接. */ @Test public void testDBCPWithDataSourceFactory() throws Exception{ Properties properties = new Properties(); InputStream inStream = JDBCTest.class.getClassLoader() .getResourceAsStream("dbcp.properties"); properties.load(inStream); DataSource dataSource = BasicDataSourceFactory.createDataSource(properties); System.out.println(dataSource.getConnection()); // BasicDataSource basicDataSource = // (BasicDataSource) dataSource; // // System.out.println(basicDataSource.getMaxWait()); } /** * 使用 DBCP 数据库连接池 * 1. 加入 jar 包(2 个jar 包). 依赖于 Commons Pool * 2. 创建数据库连接池 * 3. 为数据源实例指定必须的属性 * 4. 从数据源中获取数据库连接 * @throws SQLException */ @Test public void testDBCP() throws SQLException{ final BasicDataSource dataSource = new BasicDataSource(); //2. 为数据源实例指定必须的属性 dataSource.setUsername("root"); dataSource.setPassword("1230"); dataSource.setUrl("jdbc:mysql:///atguigu"); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); //3. 指定数据源的一些可选的属性. //1). 指定数据库连接池中初始化连接数的个数 dataSource.setInitialSize(5); //2). 指定最大的连接数: 同一时刻可以同时向数据库申请的连接数 dataSource.setMaxActive(5); //3). 指定小连接数: 在数据库连接池中保存的最少的空闲连接的数量 dataSource.setMinIdle(2); //4).等待数据库连接池分配连接的最长时间. 单位为毫秒. 超出该时间将抛出异常. dataSource.setMaxWait(1000 * 5); //4. 从数据源中获取数据库连接 Connection connection = dataSource.getConnection(); System.out.println(connection.getClass()); connection = dataSource.getConnection(); System.out.println(connection.getClass()); connection = dataSource.getConnection(); System.out.println(connection.getClass()); connection = dataSource.getConnection(); System.out.println(connection.getClass()); Connection connection2 = dataSource.getConnection(); System.out.println(">" + connection2.getClass()); new Thread(){ public void run() { Connection conn; try { conn = dataSource.getConnection(); System.out.println(conn.getClass()); } catch (SQLException e) { e.printStackTrace(); } }; }.start(); try { Thread.sleep(5500); } catch (InterruptedException e) { e.printStackTrace(); } connection2.close(); }
username=root password=root driverClassName=com.mysql.jdbc.Driver url=jdbc:mysql:3306/test initialSize=10 maxActive=50 minIdle=5 maxWait=5000 dbcp.propertiesC3P0例子
/** * 1. 创建 c3p0-config.xml 文件, * 参考帮助文档中 Appendix B: Configuation Files 的内容 * 2. 创建 ComboPooledDataSource 实例; * DataSource dataSource = * new ComboPooledDataSource("helloc3p0"); * 3. 从 DataSource 实例中获取数据库连接. */ @Test public void testC3poWithConfigFile() throws Exception{ DataSource dataSource = new ComboPooledDataSource("helloc3p0"); System.out.println(dataSource.getConnection()); ComboPooledDataSource comboPooledDataSource = (ComboPooledDataSource) dataSource; System.out.println(comboPooledDataSource.getMaxStatements()); } @Test public void testC3P0() throws Exception{ ComboPooledDataSource cpds = new ComboPooledDataSource(); cpds.setDriverClass( "com.mysql.jdbc.Driver" ); //loads the jdbc driver cpds.setJdbcUrl( "jdbc:mysql:///atguigu" ); cpds.setUser("root"); cpds.setPassword("1230"); System.out.println(cpds.getConnection()); }
<?xml version="1.0" encoding="UTF-8"?> <c3p0-config> <named-config name="helloc3p0"> <!-- 指定连接数据源的基本属性 --> <property name="user">root</property> <property name="password">1230</property> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql:///atguigu</property> <!-- 若数据库中连接数不足时, 一次向数据库服务器申请多少个连接 --> <property name="acquireIncrement">5</property> <!-- 初始化数据库连接池时连接的数量 --> <property name="initialPoolSize">5</property> <!-- 数据库连接池中的最小的数据库连接数 --> <property name="minPoolSize">5</property> <!-- 数据库连接池中的最大的数据库连接数 --> <property name="maxPoolSize">10</property> <!-- C3P0 数据库连接池可以维护的 Statement 的个数 --> <property name="maxStatements">20</property> <!-- 每个连接同时可以使用的 Statement 对象的个数 --> <property name="maxStatementsPerConnection">5</property> </named-config> </c3p0-config> c3p0-config.xml转载自:https://blog.csdn.net/u011225629/article/details/45938221