用SQLData读写数据库自定义类型
如何读写自定义类型?SQLData是个很直观的解决办法
在oracle使用手册上找到了很好的资料
http://docs.oracle.com/cd/B10501_01/java.920/a96654/oraoot.htm#1039738
还有详细例子(例子很好)
https://docs.oracle.com/cd/F49540_01/DOC/java.815/a64685/samapp4.htm
但原文太长,我精炼提取了关于SQLData的关键部分如下(大家只能读英文了),红色部分是实例代码,我创建了一个自定义类型MyTime由小时和分组成,比如13点
55分就是13:55
create or replace type MyTime as OBJECT(h int, m int);
Oracle object types provide support for composite data structures in the database.
JDBC materializes Oracle objects as instances of particular Java classes. Two main
steps in using JDBC to access Oracle objects are: 1) creating the Java classes for
the Oracle objects, and 2) populating these classes. You have two options:
1.Let JDBC materialize the object as a STRUCT.
2.Explicitly specify the mappings between Oracle objects and Java classes.you can define
your classes to implement either the JDBC standard java.sql.SQLData interface or the Oracle
extension oracle.sql.ORAData interface
If you want to create custom object classes for your Oracle objects, then you must define
entries in the type map that specify the custom object classes that the drivers will
instantiate for the corresponding Oracle objects.
Map<String, Class<?> > map = sample.getTypeMap();
/* Use the getTypeMap() method of your OracleConnection object to return the connection's
* type map object.
If the type map in the OracleConnection instance has not been initialized, then the first
call to getTypeMap() returns an empty map.*/
map.put("MYTIME", MyTime.class);
/*Use the type map's put() method to add map entries. The put() method takes two arguments:
* a SQL type name string and an instance of a specified Java class that you want to map to.
myMap.put(sqlTypeName, classObject);
SQL type names in the type map must be all uppercase, because that is how the Oracle
database stores SQL names.
The sqlTypeName is a string that represents the fully qualified name of the SQL type in
the database. The classObject is the Java class object to which you want to map the SQL
type. Get the class object with the Class.forName() method, as follows:
myMap.put(sqlTypeName, Class.forName(className));
*/
sample.setTypeMap(map);
/* When you finish adding entries to the map, use the OracleConnection object's setTypeMap()
* method to overwrite the connection's existing type map. For example:
oraconn.setTypeMap(newMap);
In this example, setTypeMap() overwrites the oraconn connection's original map with newMap.
If you do not provide a type map with an appropriate entry when using a getObject() call,
then the JDBC driver will materialize an Oracle object as an instance of the
oracle.sql.STRUCT class.
*/
String sql = "insert into train values(?, ?, ?, ?, ?, ?)";//第五个参数是MyTime
PreparedStatement pstmt = sample.prepareStatement(sql);
/* Use the setObject() method of the prepared statement to bind your Java datatype
* object to the prepared statement.
pstmt.setObject(1, emp);
Use the getObject() method to retrieve the employee object. The following code
assumes that there is a type map entry to map the Oracle object to Java type Employee:
Employee emp = (Employee)ocs.getObject(1);
*/
pstmt.setObject(5, mt2);
下面是MyTime的类定义
static class MyTime implements SQLData
{
/*The SQLData interface defines methods that translate between SQL and Java for Oracle
* database objects.
* If you create a custom object class that implements SQLData, then you must provide a
* readSQL() method and a writeSQL() method, as specified by the SQLData interface.
The JDBC driver calls your readSQL() method to read a stream of data values from the database
and populate an instance of your custom object class. Typically, the driver would use this
method as part of an OracleResultSet object getObject() call.
Similarly, the JDBC driver calls your writeSQL() method to write a sequence of data values
from an instance of your custom object class to a stream that can be written to the database.
Typically, the driver would use this method as part of an OraclePreparedStatement object
setObject() call.
*
*
* */
public int h;
public int m;
private String sqlUdt = "MYTIME";
public MyTime(int hh, int mm) {
h = hh;
m = mm;
}
/*The SQLInput implementation is an input stream class, an instance of which must be passed
* in to the readSQL() method.
* Each readXXX() method converts SQL data to Java data and returns it into an output parameter
* of the corresponding Java type. For example, readInt() returns an integer.
* The SQLOutput implementation is an output stream class, an instance of which must be passed
* in to the writeSQL() method. SQLOutput includes a writeXXX() method for each of these Java
* types. Each writeXXX() method converts Java data to SQL data,
* taking as input a parameter of the relevant Java type. For example, writeString() would take
* as input a string attribute from your Java class.
* */
/*You must implement writeSQL() as follows:
public void writeSQL(SQLOutput stream) throws SQLException
The writeSQL() method takes as input a SQLOutput stream.
When your Java application calls setObject(), the JDBC driver creates
a SQLOutput stream object and populates it with data from a custom object
class instance. When the driver calls writeSQL(), it passes in this stream parameter.
For each Java datatype that maps to an attribute of the Oracle object, writeSQL() must
call the appropriate writeXXX() method of the SQLOutput stream that is passed in.
For example, if you are writing to EMPLOYEE objects that have an employee name as a
CHAR variable and an employee number as a NUMBER variable, then you must have a writeString()
call and a writeInt() call in your writeSQL() method. These methods must be called according
to the order in which attributes appear in the SQL definition of the Oracle object type.
The writeSQL() method then writes the data converted by the writeXXX() methods to the
SQLOutput stream so that it can be written to the database once you execute the prepared
statement.
*
*
*
* */
public void writeSQL(SQLOutput stream) throws SQLException//Java data to SQL data
{
stream.writeInt(h);
stream.writeInt(m);
}
public String getSQLTypeName() throws SQLException {
return sqlUdt;
}
/* You must implement readSQL() as follows:
public void readSQL(SQLInput stream, String sql_type_name) throws SQLException
The readSQL() method takes as input a SQLInput stream and a string that indicates
the SQL type name of the data (in other words, the name of the Oracle object type,
such as EMPLOYEE).
When your Java application calls getObject(), the JDBC driver creates a SQLInput
stream object and populates it with data from the database. The driver can also determine
the SQL type name of the data when it reads it from the database. When the driver calls
readSQL(), it passes in these parameters.
For each Java datatype that maps to an attribute of the Oracle object, readSQL() must
call the appropriate readXXX() method of the SQLInput stream that is passed in.
For example, if you are reading EMPLOYEE objects that have an employee name as a CHAR
variable and an employee number as a NUMBER variable, you must have a readString() call
and a readInt() call in your readSQL() method. JDBC calls these methods according to
the order in which the attributes appear in the SQL definition of the Oracle object type.
The readSQL() method takes the data that the readXXX() methods read and convert, and
assigns them to the appropriate fields or elements of a custom object class instance.*/
public void readSQL(SQLInput stream, String typeName)throws SQLException//SQL data to Java data
{
sqlUdt = typeName;
h = stream.readInt();
m = stream.readInt();
}
public String toString() {
String res = h + ":" + m;
return res;
}
}
}
附上
Reading SQLData Objects from a Result Set
This section summarizes the steps to read data from an Oracle object into your Java application when you choose the SQLData implementation for your custom object class.
These steps assume you have already defined the Oracle object type, created the corresponding custom object class, updated the type map to define the mapping between the Oracle object and the Java class,
and defined a statement object stmt.
- Query the database to read the Oracle object into a JDBC result set.
ResultSet rs = stmt.executeQuery("SELECT emp_col FROM personnel");The
PERSONNELtable contains one column,EMP_COL, of SQL typeEMP_OBJECT. This SQL type is defined in the type map to map to the Java classEmployee. - Use the
getObject()method of your result set to populate an instance of your custom object class with data from one row of the result
set. ThegetObject()method returns the user-definedSQLDataobject because the type map contains an entry forEmployee.if (rs.next())
Employee emp = (Employee)rs.getObject(1);Note that if the type map did not have an entry for the object, then
getObject()would return anoracle.sql.STRUCTobject. Cast the output to typeSTRUCT, because thegetObject()method signature
returns the genericjava.lang.Objecttype.if (rs.next())
STRUCT empstruct = (STRUCT)rs.getObject(1);The
getObject()call triggersreadSQL()andreadXXX()calls from theSQLDatainterface, as described above.
Note:If you want to avoid using a type map, then use the
getSTRUCT()method. This method always returns aSTRUCTobject, even if there is a mapping entry in the type map.
- If you have
getmethods in your custom object class, then use them to read data from your object attributes. For example, ifEMPLOYEEhas
anEmpName(employee name) of typeCHAR, and anEmpNum(employee number) of typeNUMBER, then provide agetEmpName()method that returns a JavaStringand agetEmpNum()method
that returns an integer (int). Then invoke them in your Java application, as follows:String empname = emp.getEmpName();
int empnumber = emp.getEmpNum();
Note:Alternatively, fetch data by using a callable statement object, which also has a
getObject()method.
Writing Data to an Oracle Object Using a SQLData Implementation
This section describes the steps in writing data to an Oracle object from your Java application when you choose the SQLData implementation for your custom object class.
This description assumes you have already defined the Oracle object type, created the corresponding Java class, and updated the type map to define the mapping between the Oracle object and the Java class.
- If you have
setmethods in your custom object class, then use them to write data from Java variables in your application to attributes
of your Java datatype object.emp.setEmpName(empname);
emp.setEmpNum(empnumber);This statement uses the
empobject and theempnameandempnumbervariables assigned in "Reading
SQLData Objects from a Result Set". - Prepare a statement that updates an Oracle object in a row of a database table, as appropriate, using the data provided in your Java datatype object.
PreparedStatement pstmt = conn.prepareStatement
("INSERT INTO PERSONNEL VALUES (?)");This assumes
connis your connection object. - Use the
setObject()method of the prepared statement to bind your Java datatype object to the prepared statement.pstmt.setObject(1, emp);
- Execute the statement, which updates the database.
pstmt.executeUpdate();
用SQLData读写数据库自定义类型的更多相关文章
- mybatis 自定义类型转换器 (后台日期类型插入数据库)
后台日期类型插入数据库 有以下几种发法: 1 调用数据库 日期字符串转日期函数 str_to_date("日期","yyyy-MM-dd HH:mm:ss") ...
- C#基础视频教程6.2 如何简单读写数据库
上一节我们简单介绍了数据库的读写,所使用的数据库都是随便写的(用水果代替,但不是真正的食品零售数据表,至少没有价格,销量等等).这一节我们思考如何实现一个测试题的数据库,所谓的测试题数据库就是假定系统 ...
- 《精通C#》自定义类型转化-扩展方法-匿名类型-指针类型(11.3-11.6)
1.类型转化在C#中有很多,常用的是int类型转string等,这些都有微软给我们定义好的,我们需要的时候直接调用就是了,这是值类型中的转化,有时候我们还会需要类类型(包括结构struct)的转化,还 ...
- Object类型转换成自定义类型(向下转型)
Object类型转换成自定义类型 场景: 从数据库或者别的途径接收对象的时候用Object,但是用的时候怎么object点(方法提示 | alt+'/'),都点不出自定义类型的方法. 比如,数据库查询 ...
- GreenDao存储自定义类型对象解决方案(转)
最近公司项目选用GreenDao作为Android客户端本地数据库的对象关系映射框架.对于GreenDao虽然以往也有简单用过,但这还是笔者第一次在实际业务中使用.碰到了题目所述的两个问题,虽然在Tu ...
- Python 基本语法,文件读写,数据结构和类型
Python 基本语法,文件读写,数据结构和类型 1.基本语法 解释型(无需编译).交互式.面向对象.跨平台.简单好用 中文编码:http://www.cnblogs.com/huxi/archive ...
- C# 使用Newtonsoft.Json序列化自定义类型
Json.Net是一个读写Json效率比较高的.Net框架.Json.Net 使得在.Net环境下使用Json更加简单.通过Linq To JSON可以快速的读写Json,通过JsonSerializ ...
- 转载:oracle 自定义类型 type / create type
标签:type create oracle object record 一:Oracle中的类型有很多种,主要可以分为以下几类: 1.字符串类型.如:char.nchar.varchar2.nvarc ...
- oracle 自定义类型 type / create type
一:Oracle中的类型有很多种,主要可以分为以下几类: 1.字符串类型.如:char.nchar.varchar2.nvarchar2. 2.数值类型.如:int.number(p,s).integ ...
随机推荐
- 了解Git
对于计算机软件初学者来说Git并没有太多了解, 以前没有接触过,但是老师说对其进行了解,也没有什么概念,只有通过上网进行了解 . 了解到的大概内容如下: ...
- 缓存应用--Memcached分布式缓存简介
一. 什么是Memcached Memcached 是一个高性能的分布式内存 对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象 来减少读取数据库的次数,从而提供动态. ...
- win8.1 环境下搭建PHP5.5.6+Apache2.4.7
本文主要阐述在windows8及win8.1 环境下搭建PHP5.5.6+Apache2.4.7. 1.软件准备 apache 2.4.7:http://pan.baidu.com/s/1iUPif ...
- 网络(一),libevent客户端部分
网络模块() 一.服务端: 暂时就以libevent模块,共享内存等下 .GS打开,首先创建4个libevent子线程,当然为每个线程设置连接通知回调函数,这个是基于sockpair的,然后再创建一个 ...
- Vim 中使用cscope
使用cscope碰到的问题 1. E568: duplicate cscope database not added 根据提示,cscope数据库重复添加了,我使用的是vim7.2版本,而这个版本在已 ...
- TestDriven.Net
转: http://www.cnblogs.com/AlexLiu/archive/2008/12/01/1345002.html
- 常用的CSSreset整理
说道CSSreset,大家又爱又恨,cssreset好处是,覆盖了浏览器的默认样式,使前端攻城狮能更加精确的添加样式,各个浏览器中的界面效果都相同.可是大量的.固定的CSSreset也给网页加载带来一 ...
- 1024: [SCOI2009]生日快乐
暴力题,N<=10,没注意到平均分,读题真是.. 我们对于一个矩形分成两块进行搜.然后求较大值. ans=min(ans,max(dfs(x,y/n*i,i),dfs(x,y/n*(n-i),n ...
- ”sql Server2008 应用程序无法启动,因为应用程序的并行配置不正确。 找不到从属程序集。“C:\windows\SysWOW64\DTSPipelinePerf100.dll”的激活上下文生成失败“的解决方案
一:控制面板->管理工具->事件查看器->windows日志->应用程序 查看错误原因: 二:在其他机子上拷贝一个DTSWizard.exe.config文件替换本机上已经 ...
- 正确使用HTML title属性
如果你想对使用手机,平板电脑和辅助技术的用户隐藏某些内容,而只对键盘用户显示,那么请使用title属性. 细节 HTML的title属性本身有问题.之所以有问题是因为它在一些重要的方面表现的不够好,尽 ...