Get RowId from QueryChangeDescription - java

To my Oracle Database I have registered a DatabaseChangeNotification with a SQL-Query. I like to get any changes on the defined TABLE.
DatabaseChangeRegistration changeRegistration;
Properties properties = new Properties();
properties.setProperty(OracleConnection.DCN_NOTIFY_ROWIDS, "true");
properties.setProperty(OracleConnection.DCN_QUERY_CHANGE_NOTIFICATION, "true")
changeRegistration = connection.registerDatabaseChangeNotification(properties);
DCNListener dcnListener = new DCNListener(this);
changeRegistration.addListener(this);
Statement statement = connection.createStatement();
((OracleStatement) statement).setDatabaseChangeRegistration(changeRegistration);
String sql = "SELECT * from TABLE";
statement.executeQuery(sql);
In my Listener I receive the DatabaseChangeEvents
public void onDatabaseChangeNotification(DatabaseChangeEvent databaseChangeEvent) {
TableChangeDescription[] tableChangeDescription = databaseChangeEvent.getTableChangeDescription();
QueryChangeDescription[] queryChangeDescription = databaseChangeEvent.getQueryChangeDescription();
for (QueryChangeDescription qcd: queryChangeDescription) {
String result = qcd.toString();
System.out.println(qcd);
}
}
tabelChangeDescription is null
My result is:
query ID=201, query change event type=QUERYCHANGE
Table Change Description (length=1): operation=[UPDATE], tableName=USER.TABLE, objectNumber=67385
Row Change Description (length=1):
ROW: operation=UPDATE, ROWID=AAAQc5AAHAAAAG/AAB
Is there any nice way to get the ROWID from the Changes row else than String-Parsing? I can't find any getRowId-Method on the QueryChangeDescription.

I found the was to get the RowId. From the queryChangeDescription you can get the TabeleChangeDesciptions which has nothing in Common with the TableChangeDecription from the event. If there are changes on more than one Table, these tables where listed in the Array.
Because I am registered to only one Table I don't have to iterate over the list.
After habing the the TableChangeDescriptionyou can get the RowChangeDescription for each changed row. From this you can get the RowId.
for (QueryChangeDescription queryChangeDescription : databaseChangeEvent.getQueryChangeDescription()) {
RowChangeDescription[] rowChangeDescriptions = queryChangeDescription.getTableChangeDescription()[0].getRowChangeDescription();
for (RowChangeDescription rowChangeDescription : rowChangeDescriptions) {
handleEvent(rowChangeDescription.getRowid());
}
}

Related

How to get data from database?

I have created 'smphas' table in my database. To retrieve the data, I write this code:
function goBack() {
window.location.replace("dashboardproject.jsp");
}
function getQuarter(phase){
if(phase==""){
alert("PLEASE CHOOSE PHASE");
} else {
document.getElementById("phase").value = phase;
constructionprogress.submit();
}
}
function selected(){
$('#phaseCons').val('<%=phase%>');
}
Mysql command is:
public List<String[]> constPeriodPhase (String projCde,String co_no){
System.out.println("/*** constPeriodPhase ***/");
String sql = "SELECT distinct smh_phase_num, smh_phase_nme FROM c"+co_no+".smphas WHERE smh_proj_cde = '"+projCde+"'";
System.out.println("Execute = "+sql);
return super.execListStrArr(sql,false);
}
However, the error is:
/* constPeriodPhase */
Execute = SELECT distinct smh_phase_num, smh_phase_nme FROM cnull.smphas WHERE smh_proj_cde = 'null'
nullnulle-Solicitor[cnull.smphas]
2020-03-12 09:53:58.165 SGT EXECUTE: SELECT distinct smh_phase_num, smh_phase_nme FROM cnull.smphas WHERE smh_proj_cde = 'null'
java.sql.SQLSyntaxErrorException: Unknown database 'cnull'
How can i retrieve the database from mysql?
Unknown database 'cnull'
with a query:
...FROM c"+co_no+".smp
mean co_no is null when the function was called.

Java JTable data from database

I'm new to java and I need help with displaying a joined table/query in jtable.
First, I have done displaying data from 1 table which is:
Select data from 1 table
insert the result to its entity and insert each one of it to a List
return the list to view and insert row to jtable
I am using a DAO pattern, which has a factory, interface, implement, entity and view.
So what if I select data from other table?
Here is my get method in implement for getting book
public List get(String find) {
try {
ps = db.connect().prepareStatement("SELECT * FROM books WHERE title like ? ");
ps.setString(1, "%" + find + "%");
status = db.execute(ps);
if (status) {
books = db.get_result();
listBooks = new ArrayList<>();
while (books.next()) {
entity_books b = new entity_books();
b.setId(books.getInt(1));
b.setId_category(books.getInt(2));
b.setTitle(books.getString(3));
listBooks.add(b);
}
books.close();
return listBooks;
}
} catch (SQLException e) {
System.out.println(e.getMessage());
}
return null;
}
and then in my view:
listBooks = booksDAO.get(find.getText());
model = (DefaultTableModel) book_table.getModel();
model.setRowCount(0);
listBooks.forEach((data) -> {
model.addRow(new Object[]{
data.getId(),
data.getId_category(),
data.getTitle(),
});
});
This works fine, but I want the query to join table so I can see the category name instead of just ID category. I can do the query, but how do I apply that to my code?
Here is the query for joined table
select title,category from book b
join category c on c.id = b.id_category
Normally if I select only 1 table, I would insert it to its entity ( book table -> book entity ), so how do I handle this with multiple tables?
I didn't use prepared statement, but this code works on my end.
String sql = "SELECT * FROM customer c JOIN company cmp ON c.company_idcompany = cmp.idcompany";
ResultSet rs = stmt.executeQuery(sql);
//STEP 5: Extract data from result set
while (rs.next()) {
//Retrieve this from customer table
int id = rs.getInt("idcustomer");
//Retrieve this from customer table
String username = rs.getString("company_username");
//Display values
System.out.println("ID: " + id);
System.out.println("Username: " + username);
}

jdbc left join 3 tables

There are three tables <Table 1>, <Table 2> and <Table 3>
My SQL is something like this:
"Select table1.col1, table1.col2, table1.col3, table2.col4, table2.col5, table2.col6,
table3.col7, table3.col8 from Table 1 as table1
LEFT JOIN Table 2 as table2 on (table1.col1 = table2.col4)
LEFT JOIN Table 3 as table3 on (table1.col1 = table3.col8)"
The normal way to get the resultset is:
public List getExportDataList() throws ClassNotFoundException, SQLException {
Connection connect = null;
String url = "jdbc:.....";
String username = "username ";
String password = "password ";
try {
connect = DriverManager.getConnection(url, username, password);
} catch (SQLException ex) {
System.out.println("in exec");
System.out.println(ex.getMessage());
}
List dataList = new ArrayList<>();
PreparedStatement pstmt = connect.prepareStatement(
THE SQL CODE SHOWN ABOVE
}
ResultSet rs = pstmt.executeQuery();
while(rs.next()){
Table1 table1 = new Table1();
table1.setCOL1(rs.getString("col1"));
table1.setCOL2(rs.getString("col2"));
dataList.add(table1);
}
rs.close();
pstmt.close();
connect.close();
return dataList;
}
so that the "dataList" can be used to display the data in Primefaces dataTable.
However, this way only can save the columns in Table1 to the "dataList". I tried to dataList.add(table2) as well as dataList.add(table3) at the same time, but there is an error : "/reportGenerate.xhtml #50,75 value="#{reportData.dateCreated}": The class 'net.picary.model.Liaison' does not have the property 'dateCreated'."
Can someone tell me how to save all the selected columns from the three tables into "dataList"? Or any alternative way to achieve it?
error: "/reportGenerate.xhtml #50,75
value="#{reportData.dateCreated}": The class
'net.picary.model.Liaison' does not have the property 'dateCreated'."
Your problem is not with Query or JDBC, you should to make sure that attribute dateCreated exist in your net.picary.model.Liaison class with getter and setter like this :
private Date dateCreated;
public String name;
public String experience;
public Date getDateCreated() {
return dateCreated;
}
public void setDateCreated(Date dateCreated) {
this.dateCreated = dateCreated;
}
So when your page reportGenerate.xhtml try to load this attribute it not find it, because :
Not exist in your class
It exist but it is private and without getter and setter.
So make sure that your attribute exist and have gtter and setter, this can solve your error.
EDIT
You have two choices :
When you get your result you should to use 3 List of type table1, table2, table3 and fill them in the same loop like this :
List dataList1 = ...;
List dataList2 = ...;
List dataList3 = ...;
while(rs.next()){
table1 = new Table1();
table1.setCOL1(rs.getString("col1"));
...
dataList1.add(table1);
table2 = new Table2();
table2.setCOL1(rs.getString("col1"));
...
dataList2.add(table2);
table3 = new Table3();
table3.setCOL1(rs.getString("col1"));
...
dataList3.add(table3);
}
and in your xhtml page you had to use this three List instead to one
Create a new Object which combine this three Table like this :
class MyObject {
private Table1 table1;
private Table2 table2;
//constructor
//getters and setters
}
Then create a List<MyObject> list = ....; and set information in each table.
Hope you get my point, good luck
First, Check whether column names (col1,col2,col3,..) are with same name in your code in java with all the three db tables (table1,table2,table3).
(ie)
...
Table1 table1 = new Table1();
table1.setCOL1(rs.getString("col1"));
table1.setCOL2(rs.getString("col2"));
dataList.add(table1);
....
In the above code check you have "col1" is in same name with db column in Table1,Table2,Table3.If the column name(s) is different in database and in your code ,add aliases to your MySQL query and match it with same name in your java code.
If the column name matches, then set the column value for your table 2 and 3.
Then, add it to your Datalist.
....
....
table2.setCOL1(rs.getString("col1"));
dataList.add(table2);
....
and so on. Also, check you have added try/catch for your code to avoid exceptions like Nullpointer,SQLException etc.. which may arise during SQL transactions.

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.

Java, MySQL updating table using ID (primary key)

I have a program in which working with MySql and Java JDBC.
My question is:
I have a table (TEMP) with ID as only 1 column and another table with user personal details like ID, name, age etc..
Im trying to retrieve the ID from TEMP table and update unfilled information like name, age, address etc in USER table.
This is the query I wrote:
update m_auth_info
set name = '"+name+"',
addr = '"+addr+"',
email = '"+email+"',
affiliation = '"+affil+"',
status = '"+1+"'
where a_id = '"+ResultSet+"'";
and when my getIdMethod retrieves ID into ResultSet from TEMP table. I couldn't able to update USER TABLE.
But it works if I give ID directly.. example.
update m_auth_info
set name = '"+name+"',
addr = '"+addr+"',
email = '"+email+"',
affiliation = '"+affil+"',
status = '"+1+"'
where a_id = '"+8989+"'";
Please tell me if I have to write which step to write in my getIdMethod, so that ill get the value into ResultSet.
int id=0;
String sql = "Select ID from Temp";
ResultSet rs = statement.executeQuery(sql);
while(rs.next(){
id = rs.getInt(1);
/* pass your update query here and use like this it should work for you
update m_auth_info set name = '"+name+"',
addr = '"+addr+"', email = '"+email+"',
affiliation = '"+affil+"', status = '"+1+"' where a_id = '"+id+"'";*/
}
I believe what you are trying to do is to get the result from ResultSet, which you can do with something rs.getLong(0), your ResultSet variable.getYourIdType(0) or columnName

Categories

Resources