how to pass data from array to database using jackcess - java

Hi basically im doing this to retrieve data from database to array
for(i=0;i<numfilas;i++){
HashMap<Object, Object> rowdata = new HashMap<Object, Object>(cur.getNextRow());
for(j=0;j<numcolumnas;j++){
datos[posicion]=rowdata.get(nombrecolumnas[j]).toString();
posicion++;
}
}
then I pass the data to EditTexts so the user can edit it and after that I update the array, the problem is how do I take this data and send it back to the database?
Am I getting in trouble with datatypes? because the array is String type and the database had int Type, String Type, long type .....
thanks in advance

Am I getting in trouble with datatypes? because the array is String type and the database had int Type, String Type, long type .....
You could be, if any of the fields you are trying to update are Date/Time fields in Access. Jackcess is able to implicitly cast strings to numbers (in many cases, anyway), but it is not able to do that when it comes to dates.
For the sample data in a table named [Members]
MemberID MemberName SponsorID DateJoined FeePaid
-------- ---------- --------- ---------- -------
1 Gord 2014-01-16 0
the following code works fine
try (Database db = DatabaseBuilder.open(new File("C:/Users/Public/mdbTest.mdb"))) {
Table table = db.getTable("Members");
Row row = CursorBuilder.findRow(table, Collections.singletonMap("MemberID", 1));
if (row != null) {
row.put("SponsorID", "0"); // "Long Integer" in Access
row.put("FeePaid", "130"); // "Currency" in Access
table.updateRow(row);
}
else {
System.out.println("row not found.");
}
} catch (Exception e) {
e.printStackTrace(System.out);
}
However, this will not work
row.put("DateJoined", "2014-01-23"); // "Date/Time" in Access
because Jackcess cannot implicitly cast the string value to its internal (numeric) date value, Instead you need to do something like this
org.joda.time.DateTime dt = new org.joda.time.DateTime("2014-01-23");
row.put("DateJoined", dt.getMillis());
As an alternative, you may want to investigate UCanAccess. It is a pure-Java JDBC driver that uses Jackcess to perform reads and writes on the Access database but lets you do it using more "normal" SQL methods like this:
Connection conn=DriverManager.getConnection(
"jdbc:ucanaccess://C:/Users/Public/mdbTest.mdb");
PreparedStatement ps = conn.prepareStatement(
"UPDATE Members SET " +
"SponsorID=?, " +
"DateJoined=?, " +
"FeePaid=? " +
"WHERE MemberID=1");
ps.setInt(1, Integer.parseInt("0"));
org.joda.time.DateTime dt = new org.joda.time.DateTime("2014-01-23");
ps.setTimestamp(2, new Timestamp(dt.getMillis()));
ps.setBigDecimal(3, new BigDecimal("130"));
ps.executeUpdate();

Related

How to read CLOB type to Spring Boot? [duplicate]

I have a table in Database where datatype of a column(STATUS) is CLOB.I need to read that STATUS
create table STATUS_TABLE
(
STATE_ID number(20,0),
STATUS clob
)
I am trying to read CLOB column as below
String getStatus = "SELECT STATUS FROM STATUS_TABLE WHERE STATE_ID="+id;
Query statusResults = session.createSQLQuery(getStatus);
List statusRes = statusResults.list();
if ((statusRes != null) && (statusRes.size() > 0)) {
oracle.sql.CLOB clobValue = (oracle.sql.CLOB) statusRes.get(0);
status = clobValue.getSubString(1, (int) clobValue.length());
log.info("Status->:" + status.toString());
}
And getting the error as
java.lang.ClassCastException: $Proxy194 cannot be cast to oracle.sql.CLOB
How can i read clob data from DB and convert to String ?
Here is the corrected version, and an explanation appears below the code:
Query query = session.createSQLQuery("SELECT STATUS FROM STATUS_TABLE WHERE STATE_ID = :param1");
query.setInt("param1", id);
query.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);
List statusRes = query.list();
if (statusRes != null) {
for (Object object : statusRes) {
Map row = (Map)object;
java.sql.Clob clobValue = (java.sql.Clob) row.get("STATUS");
status = clobValue.getSubString(1, (int) clobValue.length());
log.info("Status->:" + status.toString());
}
}
Problems I saw with your code:
You were building a raw query string using concatenation. This leaves you vulnerable to SQL injection and other bad things.
For whatever reason you were trying to cast the CLOB to oracle.sql.CLOB. AFAIK JDBC will return a java.sql.Clob
You are performing a native Hibernate query, which will return a list result set whose type is not known at compile time. Therefore, each element in the list represents one record.

Postgres query - update field in json column with text type

I have a column in my postgres DB called metadata which stores a JSON string, and the type is TEXT.
I'm trying to run a query to update a field named myCount inside the JSON. I'm using Spring Boot and JDBC.
String query = "UPDATE " + mTableName + " SET metadata = jsonb_set(metadata::jsonb, '{myCount}', ?)::text" +
" WHERE scope = ?";
PreparedStatement preparedStmt = jdbcTemplate.getDataSource().getConnection().prepareStatement(query);
preparedStmt.setInt (1, myCount);
preparedStmt.setString(2, scope);
// execute the java preparedstatement
return preparedStmt.executeUpdate();
I got the following error: ERROR: function jsonb_set(jsonb, unknown, integer) does not
Any ide ahow I can run a query that updates the myCount column inside the JSON?
function jsonb_set(jsonb, unknown, integer) does not
Tells you that you are trying to call the function with an integer value as the last parameter. But the function is defined as jsonb_set(jsonb, text[], jsonb) so you will need to convert the integer value to a JSONB value:
SET metadata = jsonb_set(metadata::jsonb, '{myCount}'::text[], to_jsonb(?))::text"

Spring JDBC ResultSetMetaData "getColumnName()" method returns an empty string

I have the following section of code to implement a drop-down menu. Based on the two parameters selected from the menu, I run the corresponding query by replacing the selected column with the mapped column name.
String sql = "SELECT ?, ? FROM <table_name>";
ArrayList<Some_POJO> res = this.jdbcTemplate.query(sql, new ResultSetExtractor<Some_POJO>()
{//logic goes here.},
user_inputs_as_object_array);
Now, in the logic section, I'm using the following command to map the returned values:
while(rs.next()) {
Some_POJO = new SOME_POJO();
Some_POJO.setParam1(rs.getString("SOME_COLUMN_NAME")); //ERROR
}
Now, the marked line fails when I refer to column by name. But what is surprising is, the following workaround works:
while(rs.next()) {
Some_POJO = new SOME_POJO();
int i = 1;
Some_POJO.setParam1(rs.getString(i)); //Works(?!)
}
I tried to modify the JDBC template call to return the ResultSetMetaData object instead of an ArrayList of Some_POJO:
String sql = "SELECT ?, ? FROM <table_name>";
ResultSetMetaData res = this.jdbcTemplate.query(sql, new ResultSetExtractor<ResultSetMetaData>()
{//extractData now returns rs.getMetaData()},
user_inputs_as_object_array);
try
{
System.out.println("Column cout: " + res.getColumnCount());
for(int i = 1; i <= res.getColumnCount(); i++)
System.out.println("Label: " + res.getColumnLabel(i) + "\nName: " + res.getColumnName(i));
}
catch(SQLException sqle)
Only to get:
Column cout: 2
Label: :1
Name:
Label: :2
Name:
Could someone please shed some light into what is happening and (except for suggestions suggesting a complete redesign) what would be the most optimal way to achieve the expected functionality? I would prefer not to use column indexes since order changes would break the functionality.
Just for refactoring code, get values as:
ArrayList result = new ArrayList(0);
result.addAll(this.jdbcTemplate.query(sql, (RowMapper) (rs, rowNum) -> {
POJO out = new POJO();
out.setProperty1(rs.getString("prop1"));
out.setProperty2(rs.getString("prop2"));
...
return out;
}));
For me it works fine, passing field name in method, don't think that there are some troubles with spring jdbc. Maybe is something wrong in your sql query.

how to return a cursor along with new variable added to each row?

I want to call a procedure from java.
Example:
CREATE OR REPLACE PROCEDURE helloworld
AS
cursor data_test is
with required_data as( select *
from EMPLOYEES) select * from required_data rd join DEPARTMENTS d on d.department_id=rd.DEPARTMENT_ID ;
emp_rec data_test%ROWTYPE;
more_detail varchar2(50);
BEGIN
open data_test;
LOOP
FETCH data_test INTO emp_rec;
exit when data_test%NOTFOUND;
more_detail =BLA.GET_MORE_DATA(data_test.empid);// Lets say the fuction return varchar2 I've total of 4 similar fields to be added in total
END LOOP;
END;
/
Now how do I return all the data in the cursor(data_test ) along with more_detail in each row?? i.e I want my ResultSet in java to have all the values from the select statement as well as the value of more_detail.Also will my helloworld have out parameter as SYS_REFCURSOR or something else?? and when calling from java all I've to do is create a callable statement and register out parameter as Cursor to use this?
Well, when I look at it today, How could I ask this question. This so wrong.
I didn't have much understanding of PLSQL then and asked the question without reading much. Anyway, there are many ways to solve it as I mentioned in the comment one can send back an associative array but that is a pain on the java side if you don't know the number of expected result. or one can create a nested array with an user with defined object something like this:
CREATE OR REPLACE TYPE keyvalue AS object (col Number(10), col2 VARCHAR2(30));
CREATE OR replace TYPE map IS TABLE OF keyvalue ;
hear's how I did it. You cannot add a column to cursor but you can create you own custom defined data type.
CREATE OR REPLACE TYPE dbObject AS OBJECT
(
empId NUMBER (6),// here add as many fields you want to return or want your object to have
emailId VARCHAR2 (25),
hiredate DATE
);
CREATE OR REPLACE TYPE datalist IS TABLE OF DBOBJECT;
PROCEDURE get_emp_data (list OUT datalist)
AS
CURSOR emp_cursor
IS
SELECT employee_id AS empId,
EMPLOYEES.EMAIL AS emailId,
EMPLOYEES.HIRE_DATE AS hiring
FROM EMPLOYEES;
c_datatype emp_cursor%rowtype;
BEGIN
OPEN emp_cursor();
list := datalist();
LOOP
fetch emp_cursor into c_datatype;
EXIT WHEN emp_cursor%NOTFOUND;
list.extend;
list(emp_cursor%ROWCOUNT):=DBOBJECT(c_datatype.empId,c_datatype.emailId,c_datatype.hiring);
END LOOP;
END get_emp_data;
Now you want to call this from java: here is the code:
String dataTypeName = "DBOBJECT";
String dataTypeListName = "datalist";
StructDescriptor structDescriptor = StructDescriptor.createDescriptor(dataTypeName.toUpperCase(), connection);
ResultSetMetaData metaData = structDescriptor.getMetaData();
CallableStatement cs = connection.prepareCall("{call TEST_PACKAGE.get_emp_data(?)}");
cs.registerOutParameter(1, OracleTypes.ARRAY, dataTypeListName.toUpperCase());
cs.execute();
Object[] data = (Object[]) ((Array)cs.getObject(1)).getArray();
for(Object tmp : data) {
Struct row = (Struct) tmp;
int index = 1;
for(Object attribute : row.getAttributes()) {
System.out.println(metaData.getColumnName(index) + " : " + attribute);
++index ;
}
}
cs.close();

Sql query return nothing in the second time of executing (SQlite database)

i have a problem with sqlite data base , i want that every moment that i type a character in an editable JcomboBox i get the data from sqlite database and add it as items to JComboBox after removing all existing items .(i intend to create Autocompleting JComboBox )
this is the jComboBox code:
jComboBox1 = new javax.swing.JComboBox();
con = new Connect();
jComboBox1.setEditable(true);
for(String items :con.SelectDataforComboBox(
"SELECT Reference FROM Articles",
"SELECT COUNT(*) As COUNTER FROM Articles","") ){
jComboBox1.addItem(items);}
con.CloseDB();
jComboBox1.getEditor().getEditorComponent().addKeyListener(
new KeyAdapter(){
public void keyTyped(java.awt.event.KeyEvent evt) {
con = new Connect();
char c = evt.getKeyChar();
s = s+ c;
System.out.println(s);
jComboBox1.removeAllItems();
for(String items :con.SelectDataforComboBox(
"SELECT Reference FROM Articles",
"SELECT COUNT(*) As COUNTER FROM Articles",s) ){
jComboBox1.addItem(items);}
con.CloseDB();
}}
);
and this the method returning items from database :
public String [] SelectDataforComboBox(String sqlSelectlist , String sqlCount,String likeText){
int k=0;
try {
if(!likeText.equals("")){
sqlCount = sqlCount + " WHERE Reference LIKE '"+likeText+"%'";
sqlSelectlist = sqlSelectlist + " WHERE Reference LIKE '"+likeText+"%'";
}
System.out.println(sqlCount);
System.out.println(sqlSelectlist);
RsComboList = stmt.executeQuery(sqlCount);
while(RsComboList.next()){
ListofComboBox = new String[RsComboList.getInt("COUNTER")];
System.out.println(RsComboList.getInt("COUNTER"));
}
RsComboList = stmt.executeQuery(sqlSelectlist);
while(RsComboList.next()){
ListofComboBox[k]=RsComboList.getString("Reference");
System.out.print("Combobox : "+ListofComboBox[k]+"\n");
k++;
}
} catch (SQLException ex) {
Logger.getLogger(Connect.class.getName()).log(Level.SEVERE, null, ex);
}
return ListofComboBox ;
}
So the problem is , when i type the first character i get the items , and when i add the second character the items removed and nothing returned from database and the jCombobox still empty , but when i execute the query in SQL Command (using Navicat) i get the data as usually .What the solution?
Edited
This is the output of the query statement :
Opened database successfully
Records created successfully
m
SELECT COUNT(*) As COUNTER FROM Articles WHERE Reference LIKE 'm%'
SELECT Reference FROM Articles WHERE Reference LIKE 'm%'
1
Combobox : Mehdi
DB closed
Opened database successfully
Records created successfully
SELECT COUNT(*) As COUNTER FROM Articles WHERE Reference LIKE '%'
SELECT Reference FROM Articles WHERE Reference LIKE '%'
0
DB closed
Opened database successfully
Records created successfully
t
SELECT COUNT(*) As COUNTER FROM Articles WHERE Reference LIKE 't%'
SELECT Reference FROM Articles WHERE Reference LIKE 't%'
0
DB closed
Opened database successfully
Records created successfully
tm
SELECT COUNT(*) As COUNTER FROM Articles WHERE Reference LIKE 'tm%'
SELECT Reference FROM Articles WHERE Reference LIKE 'tm%'
0
DB closed
I suggest that you may retrieve the full range of datas into a sorted list (cached in memory), then you can put only those items in combobox list, thats first x letters are equals to the entered text. On the beginning all items can be added. By this way you can reduce the I/O on database and it is faster to update the list of combobox...
Your combobox can be a general combobox with an internal protected sorted list for cache the full range of retireved data, that can be prepared (populated) with an external object (in this case a database handler object, that manages your SQLite access), that implements for example a populateComboBox(YourComboBoxClass cb, String sql) method...
The populateComboBox() can add retrieved data to the cached list of your combobox for example by calling your implemented addCachedItem(String item) function of your combobox...
By this way it will be most flexible and reusable, also you can populate the combobox by other datasources... may be you can add datas from more than one datasources if you dont clead th items...

Categories

Resources