最近忙完iKnow,难得忙里偷闲,打开N久没有打开过的NetBeans工程,继续开始Java的学习,之前已经有用Struts访问mysql、mssqlserver、derby数据库的实现,前几天正好把oracle数据库装好了,正好把jdbc连oracle数据库的功能实现一下。昨日感恩节,收到两位同学的祝福短信,心怀着感恩的心,我也感谢大家一路有你们,晚上听着欧阳菲菲感恩的心好几遍。
段今日一大早,终于解决了java读取Oracle数据库timestamp类型的问题,至此,oracle数据库的创建程序读取告一段段落,让我来记录每一步遇到的一些问题。
oracle数据库基本语法
--创建表空间dbTest
CREATE TABLESPACE dbTest
LOGGING
DATAFILE 'D:\J2ee\NetBeansProjects\JavaWeb\PowerDesigner\sql\dbTest.ora' SIZE 2M
EXTENT MANAGEMENT LOCAL SEGMENT SPACE MANAGEMENT AUTO;
--创建用户blogadmin,默认表空间dbTest;
CREATE USER blogadmin IDENTIFIED BY blogadmin
DEFAULT TABLESPACE dbTest;
--授予其三个权限:DBA,CONNECT,RESOURCE
GRANT DBA, CONNECT, RESOURCE TO blogadmin;
--查看用户角色
SELECT * FROM DBA_ROLE_PRIVS where grantee = 'blogadmin';
--提交
commit;
查看当前用户角色和表
--使用blogadmin登陆
connect blogadmin/blogadmin
--查看当前用户角色
SELECT * FROM USER_ROLE_PRIVS;
--查看当前用户的表
select table_name,TABLESPACE_NAME from user_tables;
--查看所有表
select table_name from dba_tables where TABLESPACE_NAME = 'DBTEST';--查看表空间--清除删除表
SELECT TABLESPACE_NAME FROM DBA_DATA_FILES;
PURGE TABLE USER_TABLE;
创建和修改表
--创建FA_User表
create table FA_User (
fdUserID int not null,
fdUserName VARCHAR2(50) not null,
fdUserEmail VARCHAR2(50) not null,
fdUserSex int,
fdUserCity VARCHAR2(50),
fdUserTime TIMESTAMP,
constraint PK_FA_USER primary key (fdUserID)
);
--修改表名
alter table FA_User rename to tmp_FA_User;
--修改字段类型
alter table FA_User rename column fdUserID to tmp_fdUserID;
alter table FA_User modify tmp_fdUserID number(10,0) null;
alter table FA_User modify tmp_fdUserID number(4,0);
alter table FA_User add fdUserID number(10,0);
update FA_User set fdUserID = cast(fdUserID_temp as number(10,0) );
alter table FA_User drop column fdUserID;
alter talbe FA_User rename column fdUserID_temp to fdUserID;
--添加字段
alter table FA_User add fdUserTime TimeStamp;
序列时间使用
--创建序列
create sequence FA_User_Sequence
increment by 1 start with 1;
--插入记录
insert into FA_User values (FA_User_Sequence.NextVal,'Jonllen','jonllen@hotmail.com',1,'广州',current_timestamp);
--当前时间
select to_char(sysdate,'YYYY-MM-DD HH24-MI-SS') from dual;
--获取当前序列号
select FA_User_Sequence.CurrVal from dual;
备份数据库脚本
--备份数据库bat文件脚本
@echo off
echo 开始备份数据库.....
set dir=D:\J2ee\NetBeansProjects\JavaWeb\PowerDesigner\sql\bak
exp system/dddddd@orcl owner=blogadmin file=%dir%\bak.dmp log=%dir%\bak.log buffer=409600000 feedback=100000 direct=y consistent=n compress=n;
echo 备份结束
删除表空间
--删除表空间
drop tablespace dbTest including contents;
--删除序列
drop Sequence FA_User_Sequence;
--创建新的表空间
CREATE TABLESPACE dbTest
LOGGING
DATAFILE 'D:\J2ee\NetBeansProjects\JavaWeb\PowerDesigner\sql\dbTest.ora' SIZE 2M REUSE
EXTENT MANAGEMENT LOCAL SEGMENT SPACE MANAGEMENT AUTO;
导入数据库bat脚本
--导入还原
@echo off
echo 开始导入数据库.....
set dir=D:\J2ee\NetBeansProjects\JavaWeb\PowerDesigner\sql\bak
imp system/dddddd@orcl file=%dir%\bak.dmp log=%dir%\bak.log full=y ignore=y
echo 导入完成
后来使用Java读取Oracle数据库的遇到的问题较多,由于我之前使用了反射,通用不同的数据库,不需要单独判断某个数据库列字段的类型再赋值,之前已经也使用它反射过mysql、sqlserver、derby数据库,而放在oracle数据库却有问题,最终只能对oracle数据库一些字段做特殊的判断,修改后的反射ResultSet到JavaBean的方法如下:
/*
* Bean实体抽象基类
*/
package db;
import java.lang.reflect.*;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.List;
/**
* @author Jonllen
* @create 2009-05-24 15:13:58
* @update 2009-11-27 14:11:12
*/
public abstract class BeanBase {
public void ReflectBean( ResultSet rs)
{
System.out.println();
try {
ResultSetMetaData columns = rs.getMetaData();
Field[] fields = this.getClass().getDeclaredFields();
for(int i=1;i<=columns.getColumnCount();i++)
{
String filedName = columns.getColumnName(i);
for(int j=0;j<fields.length;j++)
{
//System.out.println("filedName:"+filedName+",类字段:"+fields[j].getName());
if(filedName.equalsIgnoreCase((fields[j].getName())) && rs.getObject(filedName)!=null)
{
Field field = fields[j];
field.setAccessible(true);
if (java.math.BigDecimal.class.getName().equalsIgnoreCase(rs.getObject(filedName).getClass().getName()))
{
//oracle number类型特殊处理
field.set(this, ((java.math.BigDecimal)rs.getObject(filedName)).intValue());
}else if( rs.getObject(filedName).getClass().getName().equalsIgnoreCase("oracle.sql.TIMESTAMP1") )
{
//oracle timestamp类型特殊处理
Class clz = rs.getObject(filedName).getClass();
Method m = clz.getMethod("timestampValue");
java.sql.Timestamp t = (java.sql.Timestamp) m.invoke(rs.getObject(filedName));
field.set(this,t);
}
else
{
field.set(this, rs.getObject(filedName));
}
String msg = java.text.MessageFormat.format("第{0}行第{1}列 {2}:{3}", rs.getRow(), i, filedName, rs.getObject(filedName));
System.out.println( msg );
break;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
错误一:java.lang.IllegalArgumentException: Can not set java.util.Date field bean.User.fdUserTime to oracle.sql.TIMESTAMP
这是在反射的时候从oracle的timestamp日期类型转换到java日期类型出错,所以我不得不在反射的时候加上if( rs.getObject(filedName).getClass().getName().equalsIgnoreCase("oracle.sql.TIMESTAMP") )的特殊判断,如果是oracle.sql.TIMESTAMP数据类型的列,则使用反射调用它的timestampValue,这样才能强制转换成java.sql.Timestamp,再反射转换成它的基类java.util.Date,直接转换出错。另外还有oracle的number类型我也做了特殊判断,它返回的类型是java.math.BigDecimal,没办法直接强制转换成int或Integer,而只能用((java.math.BigDecimal)rs.getObject(filedName)).intValue()获取它的int类型值,因为oracle的number是数值的一种通用类型,是可能包含小数位的。
错误二:can bind a LONG value only for insert into a LONG column
这是一个oracle数据库驱动版本兼容问题,错误原因是程序使用的classes12驱动文件和访问的oracle数据库版本不对应,在服务器段oracle安装目录的product\10.2.0\db_1\jdbc\lib\也有一个classes12.jar驱动文件,拷贝使用此驱动文件覆盖到项目内即可解决问题。