I am trying to use ActiveJDBC to properly convert an integer[] from my PostgreSQL database into the java equivalent int[]. I get the fetch done properly, but the object that is returned is weblogic.jdbc.wrapper.Array_org_postgresql_jdbc_PgArray. I have yet to find a way to convert that.
I have tried 2 different ways of accessing the data:
First, using the standard record.findFirst("id = ?", id) format. Because I have multiple schemas in my database, I added the #Table notation to my Model.
Second, I tried doing a record.findBySQL("select array from record where id = ?", id). I also tried array::integer[].
Each time I get back the PgArray type. I have searched for a way to convert this type into something else for use, but nothing has worked.
Is there a way to do this? Do I need to use a different way of data retrieval other than ActiveJDBC?
JDBC defines java.sql.Array to handle array typed columns. PgArray is just the Postgres implementation of java.sql.Array.
Given the array object a you can call (Integer[])a.getArray() to get an Integer array from the JDBC array object (if the JDBC driver has decided that it will return you Integer objects and not some other Numbers). A helper method to extract the value and convert to int[] would probably be a good idea.
Don't know if activejdbc has support to do this conversion behind the scenes.
Related
Summary
I am calling a stored procedure(SP) in an Oracle 12c database from a Spring-boot application. I am using CallableStatement to do this. One of the OUT parameters of the SP is an associative array with elements of a custom object type. I am having trouble retrieving the data in a proper method.
Code
TYPE trans_list IS TABLE OF T_RPT_TXN_DTLS_OBJ INDEX BY PLS_INTEGER;
TYPE T_RPT_TXN_DTLS_OBJ AS OBJECT( id VARCHAR2(20), amount NUMBER(10,2), desc VARCHAR2(100))
Connection connection = jdbcTemplate.getDataSource().getConnection();
OracleCallableStatement callableStatement = connection.prepareCall("{call SAMPLE_PROC(?,?)}").unwrap(OracleCallableStatement.class);
callableStatement.setString(1, ID);
--Here I don't know what to do--
callableStatement.registerIndexTableOutParameter(2, 500, OracleTypes.OTHER, 0);
--------------------------------
Things I have tried
I looked through different websites using google. Went through stackoverflow as well. The above code is where I am stuck at. Since the 3rd argument is the datatype of the array elements, I put in OracleTypes.OTHER but that throws an SQLException: invalid column type 1111.
I read in the official docs that for custom object types, we can map them to Java objects. I have no idea how to do that either. Please refer to User_defined types in https://docs.oracle.com/cd/B19306_01/java.102/b14355/datacc.htm#BHCGCBJC
What I am asking in brief
Any sample code, detailed docmentation, links to online examples that fits my case. I specifically need to know arg[2] of the out parameter registration, and how I might go about mapping to a custom Java object from the callableStatement (perhaps using .getObject(int) but I don't know about the mapping).
See this answer.
You cannot.
You need to define the data type in the SQL scope (using CREATE TYPE) rather than in the PL/SQL scope, in a package as JDBC can only work with SQL defined data types.
A consequence of point 1 is that JDBC does not support associative arrays, as they are a PL/SQL only data type, and you need to use collections (unlike C#, which only supports associative arrays and does not support collections). So you need to remove the INDEX BY clause from the type.
You need to be able to map from the type in the array to a Java data structure; one way of doing this is to use the SQLData interface. An example is in this answer.
Define:
callableStatement.registerOutParameter(2, OracleTypes.ARRAY,"trans_list");
Call proc:
callableStatement.executeUpdate();
Then get out parameter as
java.sql.Array array = callableStatement.getArray(2);
Object outputParamValue = array.getArray();
Type Caste outputParamValue if needed.
I'm looking for opinions so I guess this is a 'which is better' question. I have a webapp build in Javascript/jQuery and struts that uses Hibernate to access data in a relational DB (MySQL). When an object/database field has a limited set of strings for values, is it better to use the full string in the object/DB or a 'code' for that string, like a single CHAR instead of the entire string?
class User {
int id;
String userName;
String type; // Values of 'Administrator', 'Regular'
OR
char type // Values of 'A', 'R'
OR
char type // Values of 'A', 'R'
String typeString; // Can be returned on the fly based on 'type' or by DB in SQL CASE statement
}
If the database has the full text string, then its easy coding all the way around, but its wasting the space (in the DB, data transfer) on something that only has a few values.
If the database has just a 'code' then when presenting this field to a user ( like in a grid of existing users, or a dropdown selection list when creating a new user ) the char value must be converted to the full string. Then the question is where should that conversion be done? It could be at the DB level where Hibernate can fill in the full string value from a CASE statement. This saves DB space, but not in data transfer or memory. It could be at the object level where its done in the getter/setter for the 'type' field. Or it could be all the way in the GUI where Javascript converts the 'char' to the appropriate string for the user to see.
Also... if either method is OK to use, what might influence the choice you make? The number of different values? The max length of the strings? How many rows are expected in the table?
I'm sure every DB/programmer has come across this situation many times and probably has a preference.
If you only have a fixed set of user types like Admin and Regular, I think it will easier to use a static hashmap in your code and just store A and R in your code. Something like:
static HashMap<Character,String> userRoles = new HashMap<>();
static{
userRoles.put("A","Admin");
userRoles.put("R", "Regular");
}
When ever you get result from DB, you can just do userRoles.get(type) to check the actual type. This saves space and also it's readable.
I would put the full name in the database alongside an associated short code or ID in some kind of lookup table. Use the shortcode/ID as the primary key for the lookup table, and as a foreign key from other tables. If someone needs to investigate the database layer, or someone needs to use the database for reporting, data warehousing, or analytics this will simplify things greatly.
It's commonly seen as bad practice to name variables, database tables, database columns, functions, etc. with unclear names or abbreviations that not everyone will understand - short codes like this should be seen the same way.
I think its better to do the conversion from the typecode to type (and vice versa) as close to database interaction as possible - in this case Hibernate. This is because your application logic would become more readable and intuitive if it uses the explicit types.
In my opinion- if(BMW.equals(carTypeCode)) {} is lot more readable than if("X".equals(carTypeCode)) {}.
I am not very familiar with Hibernate, but it would be awesome if you could leverage Hibernate for the mapping of String to DB representation and vice versa (maybe using CASE as you mentioned). Personally, I would probably have modeled these Strings as enums and used something like Hibernate Enum Type mapping. Also, you should think about making these type codes a little bit readable by making them at least few chars because these may come in handy when you are debugging some issue by looking at DB dump and you don't have to consult your type-code to type conversion chart.
I don't think performance wise either would not impact much in the average case.
I am working in Java. I have an class called Command. This object class stores a variable List of parameters that are primitives (mostly int and double). The type, number, and order of parameters is specific to each command, so the List is type Object. I won't ever query the table based on what these parameter values are so I figured I would concatenate them into a single String or serialize them in some way. I think this may be a better approach that normalizing the table because I will have to join every time and that table will grow huge pretty quickly. (Edit: The Command object also stores some other members that won't be serialized such as a String to identify the type of command, and a Timestamp for when it was issued.)
So I have 2 questions:
Should I turn them into a delimited String? If so, how do I get each object as a String without knowing which type to cast them to? I attempted to loop through and use the .toString method, but that is not working. It seems to be returning null.
Or is there some way to just serialize that data of the array into a column of the DB? I read about serialization and it seems to be for the context of serializing whole classes.
I would use JSON serializer and deserializer like Jackson to store and retrieve those command objects in DB without losing the specific type information. On a side note, I would have these commands implement a common interface and store them in a list of commands and not in a list of objects.
I am developing a java application which needs a special component for dynamic attributes. The arguments are serialized (using JSON) and stored in a database and then deserialized at runtime. All attributes are displayed in a JTable with 3 columns (attribute name, attribute type and attribute value) and stored in a hashmap.
I have currently two problems to solve:
The hashmap can also store objects and the objects can be set to null. And if set to null i dont know which class they belong to. How could i store objects even if they are null and known which class they belong to? Do i need to wrap each object in a class that will holds the class of the stored object?
The objects are deserialized from json at runtime. The problem with this is that there are many different types of objects and i don't actually know all object types that will be stored in the hashmap. So i am looking for a way to dynamicly deserialize objects.. Is there such a way? Would i have to store the class of the object in the serialized json string?
Thanks!
Take a look to the Null Object Pattern. You can use an extra class to represent a Null instance of your type and still could contain information about itself.
There is something called a Class Token, Which is the use of Class objects as keys for heterogeneous containers. Take a look to Effective Java By Joshua Bloch, Item 29. I'm not sure how this approach could work for you since you may have many instances of the same type but I leave it as a reference.
First of all, can you motivate why you use JSON serialization for your attributes ?
This method is disadvantageous in many ways in my opinion, it can cause problems with database search and indexing, make database viewing painful and caus unnecessary code in your application. These problems can be not an issue, it depends how you want to use your attributes.
My solution for situation like these is simple table containing columns like:
id - int
attribute_name - varchar
And then add columns for each supported data type:
string_value - varchar
integer_value - int
date_value - date
... and any other types you want.
This design allow for supreme performance using simple and typesafe ORM mapping without any serialization or other boilerplate. It can store values of any type, you just set correct column for attribute type, leaving all other with null. You can simulate null value by using null in all data columns. Indexing and searching also becomes a piece of cake.
I want to pass an Arraylist of Objects for e.g.
Arraylist <SomeObject> listOFSomeObject
Where SomeObject is having two attributes key and value.
On DB side i have a table type of variable i.e.
create or replace type tableTypeVariable is table of SomeType;
CREATE OR REPLACE TYPE SomeTypeAS OBJECT
(key VARCHAR2(50),value VARCHAR2(50))
Now i want to map my each object of type SomeObject from a listOFSomeObject to the tableTypeVariable.
Can any body help me with that ?
Convert your ArrayList to an Array using toArray(), and pass it in as described here, How do you write arrays to an Oracle 10g XE db using iBatis?
Note that this a partial answer, it has nothing to do with mybatis. It could well be the case that mybatis won't support this and you'll have to fall back to plain JDBC. In this case this answer may be useful for you.
As far as I remember you cannot do this with plain JDBC, you'll need to use the Oracle driver.
For the custom type refer to this:
http://download.oracle.com/docs/cd/B13789_01/java.101/b10979/oraoot.htm#g1104293
For passing collections, refer to this:
http://asktom.oracle.com/pls/asktom/f?p=100:11:3714089787721267::::P11_QUESTION_ID:712625135727