(上)
1. JDBC 回顾
介绍: (来自百度百科 JDBC http://baike.baidu.com/view/25611.html)
JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。JDBC为工具/数据库开发人员提供了一个标准的API,据此可以构建更高级的工具和接口,使数据库开发人员能够用纯 Java API 编写数据库应用程序,同时,JDBC也是个商标名。
有了JDBC,向各种关系数据发送SQL语句就是一件很容易的事。换言之,有了JDBC API,就不必为访问Sybase数据库专门写一个程序,为访问Oracle数据库又专门写一个程序,或为访问Informix数据库又编写另一个程序等等,程序员只需用JDBC API写一个程序就够了,它可向相应数据库发送SQL调用。同时,将Java语言和JDBC结合起来使程序员不必为不同的平台编写不同的应用程序,只须写一遍程序就可以让它在任何平台上运行,这也是Java语言“编写一次,处处运行”的优势。
Java数据库连接体系结构是用于Java应用程序连接数据库的标准方法。JDBC对Java程序员而言是API,对实现与数据库连接的服务提供商而言是接口模型。作为API,JDBC为程序开发提供标准的接口,并为数据库厂商及第三方中间件厂商实现与数据库的连接提供了标准方法。JDBC使用已有的SQL标准并支持与其它数据库连接标准,如ODBC之间的桥接。JDBC实现了所有这些面向标准的目标并且具有简单、严格类型定义且高性能实现的接口。
JDBC 的工作原理:通过 JDBC API (或者说是 JDBC 驱动程序管理器 )可以操作其他的任何数据库
(只要有该数据库的驱动程序就可以)
数据库的 URL :用来标识数据库对象
Oracle数据库的驱动程序下载地址: http://www.oracle.com/technetwork/cn/indexes/downloads/index.html
找到 驱动程序 那里就可以下载到了
2. 连接的问题
今天连接 数据库时又出现了问题,首先第一个是 启动服务器时的问题
这个问题以前都木有出现过,不知道问什么这次会出错,不管,再试试,第二次试的时候还是提示上面的错误,但是显示是 已启动了,呵呵呵,随便吧,连接上了就好,那个问题差了不少资料都不怎么给力,放过它吧!
第二个问题:用 scott 连接时输入密码 tiger 却遇到错误,说 密码过期了!!!!
刚开始自己怎么都不相信,搜了一下,感谢一位前辈的指点,呵呵呵
引文地址:http://asleep886.blog.163.com/blog/static/1725066220106192521826/ 网易博客
Oracle提示错误消息ORA-28001: the password has expired
今天一上来 客户就是出问题了。就look了 一下 。 小记一下。 不过客户的是10g
Oracle提示错误消息ORA-28001: the password has expired,
经调查是由于Oracle11G的新特性所致, Oracle11G创建用户时缺省密码过期限制是180天, 如果超过180天用户密码未做修改则该用户无法登录。
可通过
SELECT * FROM dba_profiles WHERE profile='DEFAULT' AND resource_name='PASSWORD_LIFE_TIME'
语句查询密码的有效期设置,LIMIT字段是密码有效天数。在密码将要过期或已经过期时可通过
ALTER USER 用户名 IDENTIFIED BY 密码 ;
语句进行修改密码,密码修改后该用户可正常连接数据库。
长久对应可通过
ALTER PROFILE DEFAULT LIMIT PASSWORD_LIFE_TIME UNLIMITED
语句将口令有效期默认值180天修改成“无限制”。出于数据库安全性考虑,不建议将PASSWORD_LIFE_TIME值设置成UNLIMITED,
建议客户定期修改数据库用户口令。
于是,我用 sys 连接,打开“其他用户”,找到了 scott ,然后查看(编辑用户)
看这个内容果然是 密码过期了,口令失效了!!!
于是我重新设置了一个密码,但还是 tiger,呵呵,经典嘛!!!!把口令失效的勾去掉
在结果中显示结果为:
最后,重新点击 scott 连接,呵呵呵
成功了!!!!!连接上了,呵呵呵!!
3. JDBC 编程
在 Oracle 数据库中 新建了一个表 users ,只有两列,name 和 password ,没有任何记录
然后新建了一个 Java Project ,添加了 (Build Path) OracleDriver (Oracle 数据库驱动程序)
编写JDBC 程序的一般步骤:
源码:
package com.yinger;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class JDBCExample {
/**
* @param args
*/
public static void main(String[] args) {
String driver="oracle.jdbc.driver.OracleDriver";
String url="jdbc:oracle:thin:@192.168.1.107:1521:orcale"; // 数据库 url
String username="scott";
String password="tiger";
String sql="insert into users(name,password) values(?,?)";
try {
Class.forName(driver); // 可能产生异常 ClassNotFoundException
Connection conn = DriverManager.getConnection(url, username, password); // 获取连接
PreparedStatement pstmt = conn.prepareStatement(sql); // 设置sql语句,并执行
pstmt.setString(1, "yinger");
pstmt.setString(2, "yinger");
pstmt.executeUpdate();
pstmt.close();
conn.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
结果是我想得到的结果,呵呵,肯定是出错的!
结果显示:
错误异常:The Network Adapter could not establish the connection
在网上查找资料,觉得应该是那个 ip 的设置错了
我的项目中的 ip 地址是我的电脑的 ipv4 地址 192.168.1.107 如下所示:
并且 监听服务是开启了的,使用命令 netstat -na
如图: 127.0.0.1:1521 0.0.0.0 listening
看网上说,添加的数据库驱动程序是要 添加到 classpath 中的,于是我将 用户库 中的 OracleDriver 放进了 class path中,但是还是没有用
结果还是那样!!!
我还看到网上说,可以在 net-manager 中查看网络配置
打开后的 net-manager
我先后察看了 数据库实例 orcale 和 listener 的地址配置
使用的都是 TCP/IP 协议,主机名都是 localhost ,端口号也都是 1521 (默认的),这些都没有什么异常
实在不行了,我又查了查资料,呵呵呵,有了收获
引文地址:http://hi.baidu.com/futurekey/blog/item/e6b38fa9409b99b8ca130c46.html 百度空间
Oracle Io异常: The Network Adapter could not establish the connection
今天项目运行时总时是报(Io异常: The Network Adapter could not establish the connection)异常,一直奇怪,在学校做的好好为什么回来了就不行了?无意间看到连到电脑上的网线,再想到刚才打开数据库登录时报了什么监听程序没有效的服务器(后来把网线插上后好了),突然恍然大悟,原来问题出在我本机的IP上,因为在我安装oracle时报过一个网络配置的警告,当时没有管,装好后才发现监听服务无法打开,后来手动设置的监听程序(如果在安装时网络配置那项成功,会自动建一个监听服务的),当时写的IP是本机内网地址192.168.1.101,这样在项目中写连接字符串时就不能用"localhost(127.0.0.1)",必须写192.168.1.101,由于在学校时用的是localhost,回来后没有改过来,所以在运行时监听程序无法找到localhost(127.0.0.1),就报了上面的异常,一直想把这个地址给改过来,可是试了很多次都不行,如果哪位看到后,能说一方法,先谢谢了!
当然出现以上的异常不只是IP错误才会出现,还有其它的原因,下面是几种可能的原因:
1.IP错误。
在设置URL时错误,例如:jdbc:oracle:thin:@192.168.0.36:1521:sharp
数据库服务器不正确:ping 服务器IP是否正确。不正确,将URL更改为正确
端口号错误:一般不会错误。
2.防火墙
如果机器上安装有放火墙,可能是服务器端口号屏蔽而造成的。关闭防火墙后,尝试重新连接。3.数据库监听未启动 修改PC上注册表中的ImagePath值。
----------------------------------------------------------
问题已经解决
首先打开oracle配置和移植工具 --> Net manager --> 本地 --> 监听程序 -- > listener(一般是这个,但如果改过也可能不是这个) --> 网络地址 ---> 把主机那一项改为"localhost(或者直接写你本机的计算名,如果写的是localhost保存后再重新打开,它会自动变成本机的计算机名)" ---> 复制主机名然后同样 到本地 --> 服务器名 --> 找到服务器名(就是你安装数据库时的全局数据库名) --->
把刚复制的内容粘贴到 "主机名" 中 , 保存退出, 这样就可以了.....
----------------------------------------------------------------------
引文地址:
http://hi.baidu.com/moonhai/blog/item/c02119c6d7ba49dbd000601a.html 百度空间
The Network Adapter could not establish the connection
org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot create PoolableConnectionFactory (Io 异常: The Network Adapter could not establish the connection)
Caused by: java.sql.SQLRecoverableException: Io 异常: The Network Adapter could not establish the connection
路由重启后我局域网的ip地址,改变了。重新配置Tomcact的连接池和数据源
具体的配置是通过修改Tomcat服务器conf目录下的context.xml文件(以我的为例)
<Context reloadable="true">
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<Resource name="jdbc/oracleds" auth="Container" type="javax.sql.DataSource"
maxActive="100" maxIdle="30" maxWait="10000"
username="sys as sysdba" password="oa2008"
driverClassName="oracle.jdbc.OracleDriver"
url="jdbc:oracle:thin:@192.168.1.102:1521:ora11"/>
</Context>
我以前的ip是192.168.1.102 现在的是192.168.1.101 把上面的102改成101。
有了这次的教训,以后变乖了。我的oracle都是在本机运行的,没有再网络上。把oracle中所有的ip都换成127.0.0.1了,以后不管怎么变我都不会出错了。
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
看了之后,我觉得 ip 应该改成 127.0.0.1
源码:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class JDBCExample {
/**
* @param args
*/
public static void main(String[] args) {
String driver="oracle.jdbc.driver.OracleDriver";
String url="jdbc:oracle:thin:@127.0.0.1:1521:orcale";
String username="scott";
String password="tiger";
String sql="insert into users(name,password) values(?,?)";
try {
Class.forName(driver);
Connection conn = DriverManager.getConnection(url, username, password);
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, "yinger");
pstmt.setString(2, "yinger");
pstmt.executeUpdate();
pstmt.close();
conn.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
测试一下,哈哈,成功了,没有报错!打开 SQL Developer 查看数据,果然插进去了!
总结:通过各种不同的方式连接,只要我要连接的是我本机安装的Oracle数据库,那么IP地址就是 127.0.0.1 ,永远都不会改变!
而不是我本机的实际 IPv4 地址!虽然纠结了很多,但是还是有了不少其他的收获,呵呵呵,加油!
(中)
(1)Java 实现 数据库连接池
1.数据库连接的配置文件 dbpool.properties
driverClassName=oracle.jdbc.driver.OracleDriver
username=scott
password=tiger
url=jdbc\:oracle\:thin\:@127.0.0.1\:1521\:orcale // 对应的数据库连接 地址
poolSize=10
2. 数据库连接池类
package webbook.util;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
import java.util.Vector;
public class ConnectionPool {
private Vector<Connection> pool;
private String url;
private String username;
private String password;
private String driverClassName;
/**
* 连接池的大小,也就是连接池中有多少个数据库连接。
*/
private int poolSize = 1;
private static ConnectionPool instance = null;
/**
* 私有的构造方法,禁止外部创建本类的对象,要想获得本类的对象,通过getIstance方法。
* 使用了设计模式中的单例模式。
*/
private ConnectionPool() {
init();
}
/**
* 连接池初始化方法,读取属性文件的内容 建立连接池中的初始连接
*/
private void init() {
pool = new Vector<Connection>(poolSize);
readConfig();
addConnection();
}
/**
* 返回连接到连接池中
*/
public synchronized void release(Connection conn) {
pool.add(conn);
}
/**
* 关闭连接池中的所有数据库连接
*/
public synchronized void closePool() {
for (int i = 0; i < pool.size(); i++) {
try {
((Connection) pool.get(i)).close();
} catch (SQLException e) {
e.printStackTrace();
}
pool.remove(i);
}
}
/**
* 返回当前连接池的一个对象
*/
public static ConnectionPool getInstance() {
if (instance == null) {
instance = new ConnectionPool();
}
return instance;
}
/**
* 返回连接池中的一个数据库连接
*/
public synchronized Connection getConnection() {
if (pool.size() > 0) {
Connection conn = pool.get(0);
pool.remove(conn);
return conn;
} else {
return null;
}
}
/**
* 在连接池中创建初始设置的的数据库连接
*/
private void addConnection() {
Connection conn = null;
for (int i = 0; i < poolSize; i++) {
try {
Class.forName(driverClassName);
conn = java.sql.DriverManager.getConnection(url, username, password);
pool.add(conn);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 读取设置连接池的属性文件
*/
private void readConfig() {
try {
String path = System.getProperty("user.dir") + "\\dbpool.properties";
FileInputStream is = new FileInputStream(path);
Properties props = new Properties();
props.load(is);
this.driverClassName = props.getProperty("driverClassName");
this.username = props.getProperty("username");
this.password = props.getProperty("password");
this.url = props.getProperty("url");
this.poolSize = Integer.parseInt(props.getProperty("poolSize"));
} catch (Exception e) {
e.printStackTrace();
System.err.println("读取属性文件出错. ");
}
}
}
3.测试类
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class ConnectionPoolTest {
public static void main(String[] args) throws Exception {
String sql = "select * from users";
long start = System.currentTimeMillis();
ConnectionPool pool = null;
for (int i = 0; i < 100; i++) {
pool = ConnectionPool.getInstance();
Connection conn = pool.getConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql);
while (rs.next()) {
}
rs.close();
stmt.close();
pool.release(conn);
}
pool.closePool();
System.out.println("经过100次的循环调用,使用连接池花费的时间:" + (System.currentTimeMillis() - start) + "ms\n");
// String hostName = "192.168.1.20";
String hostName = "127.0.0.1";
String driverClass = "oracle.jdbc.driver.OracleDriver";
String url = "jdbc:oracle:thin:@" + hostName + ":1521:orcale";
String user = "scott";
String password = "tiger";
start = System.currentTimeMillis();
for (int i = 0; i < 100; i++) {
Class.forName(driverClass);
Connection conn = DriverManager.getConnection(url, user, password);
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql);
while (rs.next()) {
}
rs.close();
stmt.close();
conn.close();
}
System.out.println("经过100次的循环调用,不使用连接池花费的时间:" + (System.currentTimeMillis() - start) + "ms");
}
}
输出结果:由结果可以看出,使用连接池大大的缩短了与数据库交互和数据处理的时间!
下图是 SQL PLUS 的一个简单使用,呵呵呵,如果你不想打开庞大的 Oracle SQL Developer ,那么就用它吧,呵呵呵,比较简单,还可以让你熟悉 Sql 语句呢
desc table_name 显示一张表的结构
程序测试出来的结果就是 使用连接池技术大大的提高了数据库的性能,操作上更加快捷,节省了大量的时间,哈哈,不过现在的很多服务器什么的都已经有了该技术,且相当成熟,所以一般都不用程序员自己去写,但是这个例子是连接池常用的处理方式,其中利用了单例模式,原理简单说就是每次并不是立即关闭某个数据库连接,而是将它放到连接池的容器中
(2)配置 Tomcat 的连接池 和 数据源
我的设置:
<!-- Default set of monitored resources -->
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<Resource name="jdbc/oracleds" auth="Container" type="javax.sql.DataSource"
maxActive="100" maxIdle="30" maxWait="1000" name="scott" password="tiger"
driverClassName="oracle.jdbc.OracleDriver" url="jdbc:oracle:thin:@127.0.0.1:1521:orcale" />
<!-- Uncomment this to disable session persistence across Tomcat restarts -->
<!--
<Manager pathname="" />
-->
<!-- Uncomment this to enable Comet connection tacking (provides events
on session expiration as well as webapp lifecycle) -->
<!--
<Valve className="org.apache.catalina.valves.CometConnectionManagerValve" />
-->
</Context>
(下)
DBUtils 的使用
1.Commons DBUtils 小巧的Java数据库操作工具,它在JDBC的基础上做了科学的封装,旨在简化JDBC代码混乱与重复。
下载地址:http://commons.apache.org/dbutils/
2. DbUtils 框架结构
MapListHandler 和 BeanListHandler 这两个类都是 ResultSetHandler 接的实现类
QueryRunner类 是处理sql 语句的
3. 实例
【注意:项目中还是要导入OracleJDBC驱动程序,因为 DbUtils 只是对数据库操作进行了一次封装而已,使代码更加简洁】
使用 MapListHandler 类:把数据库中读出的数据放入List,每条记录就是一个Map
package com.yinger;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.MapListHandler;
public class MapListDemo {
public static void main(String arg[]){
String url = "jdbc:oracle:thin:@127.0.0.1:1521:orcale";
String sql = "select name,password from users";
DbUtils.loadDriver("oracle.jdbc.driver.OracleDriver");
try {
Connection conn = DriverManager.getConnection(url, "scott", "tiger");
QueryRunner qr = new QueryRunner();
List result = qr.query(conn, sql, new MapListHandler());
DbUtils.close(conn);
Map map = null;
for(int i=0;i<result.size();i++){
map = (Map)result.get(i);
System.out.println("name:"+map.get("name")+"\t");
System.out.println("password:"+map.get("password")+"\n");
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
输出结果:
使用BeanListHandler 类:把数据库中读出的数据放入List,每条记录就是一个Map
首先定义一个 JavaBean (也就是一个类)
package com.yinger;
public class User {
private String name;
private String password;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
在编写 代码读取数据库中的数据
package com.yinger;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;
public class BeanListDemo {
public static void main(String[] args) {
String url = "jdbc:oracle:thin:@127.0.0.1:1521:orcale";
String sql = "select name,password from users";
DbUtils.loadDriver("oracle.jdbc.driver.OracleDriver");
try {
Connection conn = DriverManager
.getConnection(url, "scott", "tiger");
QueryRunner qr = new QueryRunner();
List result = qr.query(conn, sql, new BeanListHandler(User.class));
DbUtils.close(conn);
User user = null;
for (int i = 0; i < result.size(); i++) {
user = (User) result.get(i);
System.out.println("name:" + user.getName() + "\t");
System.out.println("password:" + user.getPassword() + "\n");
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
输出结果:和前者相同
4. 更多的关于 DbUtils 的内容
DbUtils源码阅读: http://cuics-100.iteye.com/blog/814491
Apache Commons DbUtils 快速上手 http://lavasoft.blog.51cto.com/62575/222771/