Retrieving data from a table based on values in a hashmap - java

I have an hashmap with a key and value (Array of integers) HashMap<key, array> and I would like to retrieve data from a sql table with a column that matches the values in array stored in a hashmap
I can do this in two ways one getting all the data from table and iterating through hashmap and other being iterating through hashmap and applying the where clause in each iteration which makes n calls to database.
Is there an efficient way to do this other than the above ?

Use a PreparedStatement to set up a query having an IN condition in the WHERE clause. This snippet should give you the general idea:
values = new int[]{1,2,3,4,5};
String query =
"SELECT film_id, title\n"
+ "FROM film\n"
+ "WHERE film_Id IN (";
for (int i = 0; i < values.length; ++i) {
if (i > 0) {
query += ",";
}
query += "?";
}
query += ")";
try {
Connection conn = DriverManager.getConnection("db-url", "user", "pwd");
PreparedStatement stmt = conn.prepareStatement(query);
for (int i = 0; i < values.length; ++i)
stmt.setInt(i+1, values[i]);
ResultSet rs = stmt.executeQuery();
while (rs.next()){
// process results
}
} catch (Exception ex) {
ex.printStackTrace();
}

Related

Comparison of different values from ResultSet to database SQL Query

I'm new to java.I have a SQL Query that gives the following output
logtime 2014-09-02 16:05:10.0
BL1_data_SS_ST 2
BL2_data_SS_ST 2
BL3_data_SS_ST 2
BL4_data_SS_ST 1
BL5_data_SS_ST 0
BL6_data_SS_ST 2
/* continues till BL27_data_SS_ST */
st1_prmt_status_p45 1
beam_current 110.58
beam_energy 2500.0635
I have only one row in my output and 31 columns. I'm using Java and JSP .
EDIT
The above result is retrieved by the following method
public String[][] beamline_Status() {
int i = 0;
try {
con = getConnection();
stmt = con.createStatement();
String sql = "SELECT TOP 1 c.logtime, a.BL1_data_SS_ST,a.BL2_data_SS_ST,a.BL3_data_SS_ST,a.BL4_data_SS_ST,a.BL5_data_SS_ST,a.BL6_data_SS_ST,a.BL7_data_SS_ST,a.BL8_data_SS_ST,a.BL9_data_SS_ST,a.BL10_data_SS_ST,a.BL11_data_SS_ST, a.BL12_data_SS_ST,a.BL13_data_SS_ST,a.BL14_data_SS_ST,a.BL15_data_SS_ST,a.BL16_data_SS_ST,a.BL17_data_SS_ST,a.BL18_data_SS_ST,a.BL19_data_SS_ST,a.BL20_data_SS_ST,a.BL21_data_SS_ST,a.BL22_data_SS_ST,a.BL23_data_SS_ST,a.BL24_data_SS_ST,a.BL25_data_SS_ST,a.BL26_data_SS_ST,a.BL27_data_SS_ST,b.st1_prmt_status_p45,c.beam_current,c.beam_energy from INDUS2_BLFE.dbo.main_BLFE_status a inner join INDUS2_MSIS.dbo.main_MSIS_status b on a.logtime=b.logtime inner join INDUS2_BDS.dbo.DCCT c on b.logtime=c.logtime ORDER BY c.logtime DESC ";
stmt.executeQuery(sql);
rs = stmt.getResultSet();
while (rs.next()) {
for (int j = 0; j < 31; j++) {
a[i][j] = rs.getString(j + 1);
}
}
} catch (Exception e) {
System.out.println("\nException (String code):" + e);
} finally {
closeConnection(stmt, rs, con);
}
return a;
}
Now I wan to define a method which retrieve values from the ResultSet where column values are either 0 or 1. How to do that.
EDIT 2
I'm trying to retrieve the column values from resultset where column value is 1 by following code:-
public String[][] beam_CurrentStatus() {
int i = 0;
try
{
con = getConnection();
stmt = con.createStatement();
String sql = "SELECT TOP 1 c.logtime, a.BL1_data_SS_ST,a.BL2_data_SS_ST,a.BL3_data_SS_ST,a.BL4_data_SS_ST,a.BL5_data_SS_ST,a.BL6_data_SS_ST,a.BL7_data_SS_ST,a.BL8_data_SS_ST,a.BL9_data_SS_ST,a.BL10_data_SS_ST,a.BL11_data_SS_ST, a.BL12_data_SS_ST,a.BL13_data_SS_ST,a.BL14_data_SS_ST,a.BL15_data_SS_ST,a.BL16_data_SS_ST,a.BL17_data_SS_ST,a.BL18_data_SS_ST,a.BL19_data_SS_ST,a.BL20_data_SS_ST,a.BL21_data_SS_ST,a.BL22_data_SS_ST,a.BL23_data_SS_ST,a.BL24_data_SS_ST,a.BL25_data_SS_ST,a.BL26_data_SS_ST,a.BL27_data_SS_ST,b.st1_prmt_status_p45,c.beam_current,c.beam_energy from INDUS2_BLFE.dbo.main_BLFE_status a inner join INDUS2_MSIS.dbo.main_MSIS_status b on a.logtime=b.logtime inner join INDUS2_BDS.dbo.DCCT c on b.logtime=c.logtime ORDER BY c.logtime DESC ";
stmt.executeQuery(sql);
rs = stmt.getResultSet();
while (rs.next()) {
for (int j = 1; j < 31; j++) {
if ((rs.getString(j)) == "1")
a[i][j] = rs.getString(j + 1);
}
}
} catch (Exception e) {
System.out.println("\nException in:" + e);
} finally {
closeConnection(stmt, rs, con);
}
return a;
}
But the result I'm getting of above code is
[[Ljava.lang.String;#ea25c1
If you want entire table in the ResultSet and then obtain only the first and second column out of it you can do like:
Statement stmt=conn.createStatement();
ResultSet rs= stmt.executeQuery("select * from tableName");
rs.getInt(1); //assuming your column is of compatible type
rs.getInt(2);
or the other way is that you retrieve only the first two columns from the DB into your ResultSet

java.sql.SQLSyntaxErrorException: ORA-01795: maximum number of expressions in a list is 1000

we all know we see this exception when try to bomabard the query with more than 1000 values. the maximum for the column limit is 1000.. the best possible solution is to split the query into two.guys can u suggest some possible ways of code refactoring to make my problem go away.any help would be appreciated.
we see the exception when audTypeFieldIdList are greater than 1000 values.
try {
String query = "select AUDIT_TYPE_FIELD_ID, FIELD_NAME from AUDIT_TYPE_FIELD where AUDIT_TYPE_FIELD_ID in (";
int x = 0;
for (int y = 1; y <= audTypeFieldIdList.size(); y++) {
query += audTypeFieldIdList.get(x);
if (y != audTypeFieldIdList.size()) {
query += ", ";
}
x++;
}
query += ")";
List<Long> audTypeFieldIdList, Connection connection) {
ResultSet rs = null;
Statement stmt = null;
List<AuditTypeField> audTypeFieldList = new ArrayList<AuditTypeField>();
try {
String query = "select AUDIT_TYPE_FIELD_ID, FIELD_NAME from AUDIT_TYPE_FIELD where AUDIT_TYPE_FIELD_ID in (";
int x = 0;
for (int y = 1; y <= audTypeFieldIdList.size(); y++) {
query += audTypeFieldIdList.get(x);
if (y != audTypeFieldIdList.size()) {
query += ", ";
}
x++;
}
query += ")";
stmt = connection.createStatement();
rs = stmt.executeQuery(query);
while (rs != null && rs.next()) {
AuditTypeField audTypeField = PluginSystem.INSTANCE
.getPluginInjector().getInstance(AuditTypeField.class);
audTypeField.setId(rs.getLong("AUDIT_TYPE_FIELD_ID"));
audTypeField.setName(rs.getString("FIELD_NAME"));
audTypeFieldList.add(audTypeField);
}
return audTypeFieldList;
return audTypeFieldList;
You can't use more than 1000 entries in IN clause. There are 2 solutions as mentioned below:
Use inner query to solve this issue. You can create a temporary table and use that in your IN clause.
Break it in the batch of 1000 entries using multiple IN clause separated by OR clause.
sample query:
select * from table_name
where
column_name in (V1,V2,V3,...V1000)
or
column_name in (V1001,V1002,V1003,...V2000)
...
Read more.. and see Oracle FAQ

How to add data (Jtable data actually) into database. Is there any way to insert an object into database using preparedstmt?

public cntctus()
{
column names for JTable
String column[]= { "Name","Position","Phone"};
rows for JTable
Object [][]row = {
{"Prof. Renu Vig", "Director", "+123456"},
{"Mr. Sukhbir singh", "Assistant Professor", "+9123568989"},
{"Ms. shaweta", "BI teacher","9468645"}
};
table = new JTable(row,column);
TableModel tm = table.getModel();
java.sql.Connection con=null;
try {
Class.forName("com.mysql.jdbc.Driver");
con=DriverManager.getConnection("jdbc:mysql://localhost:3306/training","root","");
try{
java.sql.Statement stmt =con.createStatement();
String maketable = "CREATE TABLE if not exists contacttable(Name Varchar(25),Position Varchar(20),Phone Varchar(20))";
stmt.executeUpdate(maketable);
System.out.print("table created ");
//insert into table contacttable query
PreparedStatement pstmt=con.prepareStatement("INSERT into contacttable select distinct values(?,?,?)");
get some TableModel that will contain the data
for (int i = 0; i < tm.getRowCount(); i++) {
for (int j = 0; j < tm.getColumnCount(); j++) {
Object o = tm.getValueAt(i, j);
System.out.println("object from table is : " +o);
k=j+1;
pstmt.setString(k, (String)o);
}
pstmt.executeUpdate();
}
}
catch(SQLException s)
{
System.out.println(s);
}
}
catch(Exception e)
{
e.printStackTrace();
}
I want to insert this whole object into database.in short how to insert jtable data into databse.?? please help.
error is: you have an error in your sql syntax at line 1 ('"prof. renu vig, "director"...
In the event that you want to have multiple rows on your prepared statement, you could just take what you have now and add a call to pstmt.addBatch() inside the outer loop, and outside the inner loop (the loops which iterate over the JTable, IE add batch once per row). Then after you have iterated over the whole table call pstmt.executeBatch().
A word to the wise though, if you are generating keys on insert, the drivers must also support returning multiple keys on batch inserts, or you will probably just get the first key generated back instead of all of them. Alternatively you could execute the statement each iteration of the outer loop (IE once per row), making sure to call .clearParamters() after each execution. You will want to reuse the preparedStatement for performance reasons.
Your insert statement is also screwed up. Its just going to be INSERT INTO contacttable VALUES(?,?,?). Get rid of the select distinct stuff.
It will probably look like this when its done:
String column[]= { "Name","Position","Phone"};
Object [][]row = {
{"Prof. Renu Vig", "Director", "+123456"},
{"Mr. Sukhbir singh", "Assistant Professor", "+9123568989"},
{"Ms. shaweta", "BI teacher","9468645"}
};
JTable table = new JTable(row,column);
TableModel tm = table.getModel();
java.sql.Connection con=null;
try
{
Class.forName("com.mysql.jdbc.Driver");
con=DriverManager.getConnection("jdbc:mysql://localhost:3306/training","root","");
java.sql.Statement stmt =con.createStatement();
String maketable = "CREATE TABLE if not exists contacttable(Name Varchar(25),Position Varchar(20),Phone Varchar(20))";
stmt.executeUpdate(maketable);
System.out.print("table created ");
PreparedStatement pstmt=con.prepareStatement("INSERT INTO contacttable VALUES(?,?,?)");
for (int i = 0; i < tm.getRowCount(); i++) {
for (int j = 0; j < tm.getColumnCount(); j++) {
Object o = tm.getValueAt(i, j);
System.out.println("object from table is : " +o);
pstmt.setString(j+1, (String)o);
}
pstmt.executeUpdate();
pstmt.clearParameters();
}
}
catch (Exception e) {
e.printStackTrace();
}
The Only one change You have to do with your Code i.e
for (int i = 0; i < tm.getRowCount(); i++) {
for (int j = 0; j < tm.getColumnCount(); j++) {
Object o = tm.getValueAt(i, j);
System.out.println("object from table is : " +o);
pstmt.setObject(j+1, o);
it will send your actual JTable data into your Database file.
i am sure. it will work work.
i have an exemple with jpa i hope that it help you
try{
TableModel tm= table.getModel();
for (int i = 0; i < tm.getRowCount(); i++) {
Object NumeroCin=tm.getValueAt(i, 0);
Object Nomprenom=tm.getValueAt(i, 1);
Object Tel =tm.getValueAt(i, 2);
Object Adresse =tm.getValueAt(i, 3);
Object DateNaissance=tm.getValueAt(i, 5);
Object Sexe=tm.getValueAt(i, 4);
Etudiant e=new Etudiant();
e.setAdresse((String) Adresse);
e.setDateNaissance((String) DateNaissance);
e.setNomprenom((String) Nomprenom);
e.setNumeroCin((String) NumeroCin);
e.setSexe( (String) Sexe );
e.setTel((String) Tel);
Ajouterobjet(e);
}}}
catch (Exception e) {
e.printStackTrace();
}
public void Ajouterobjet(Object o)
{
EntityTransaction tx=entityManager.getTransaction();
tx.begin();
entityManager.persist(o);
tx.commit();
}

Adding multiple strings into SQL database using for loop

I'm currently scraping some scores from a HTML page and then inputting them into a SQL database.
The scores are being parsed using Jsoup into an ArrayList. From here I'm converting the ArrayList to a String to allow it to be parsed into a VARCHAR field in the db. Although I can't seem to work out how to edit the for loop I have to insert all the values at once.
Here is my current code:
Document doc = Jsoup.connect(URL).timeout(5000).get();
for (Element table : doc.select("table:first-of-type")) //selects first table
{
for (Element row : table.select("tr:gt(0)")) { //selects first table cell
Elements tds = row.select("td");//selects row
List1.add(tds.get(0).text());
List2.add(tds.get(1).text());
List3.add(tds.get(2).text());
}
}
PreparedStatement stmt = conn.prepareStatement("INSERT INTO Scores (Home, Score, Away) VALUES (?,?,?)");
String[] List1str = new String[List1.size()];
List1str = List1.toArray(List1str);
for (String s : List1str) {
stmt.setString(1, s);
stmt.setString(2, "test");
stmt.setString(3, "test");
stmt.executeUpdate();
}
for (int i = 0; i < dtm.getRowCount(); i++) {
for (int j = 0; j < dtm.getColumnCount(); j++) {
Object o = dtm.getValueAt(i, j);
System.out.println("object from table is : " + o);
pst.setString(j + 1, (String) o);
}
pst.executeUpdate();
pst.clearParameters();
}

How to improve performance while update column Clob in oracle?

I used the following codes to update column Clob in oracle, it seems to be okay and work properly, after performance testing, it reported that need consumed more than 200ms while the length of string is more than 130000. Is it any good way to improve it?
private void updateClobDetailsField(Map<Integer, String> idToDetails){
long s1 = System.currentTimeMillis();
Connection conn = null;
PreparedStatement pStmt = null;
ResultSet rset = null;
Map<Integer, Clob> idToDetailsClob = new HashMap<Integer, Clob>();
int BATCH_SIZE = CMType.BATCH_UPDATE_MAXSIZE;
try
{
conn = getConnection();
ServerAdapter adapter = ServerAdapter.getServerAdapter();
List<Integer> IDList = new ArrayList<Integer>();
for(Integer id : idToDetails.keySet()){
IDList.add(id);
}
List<Integer> tempIDList = new ArrayList<Integer>(IDList);
while(!tempIDList.isEmpty()){
int size = tempIDList.size() < BATCH_SIZE ? tempIDList.size() : BATCH_SIZE;
List<Integer> currentBatch = tempIDList.subList(0, size);
String inClause = SQLHelper.prepareInClause("ID",currentBatch.size());
pStmt = conn.prepareStatement("SELECT ID, DETAILS FROM PROGRAM_HISTORY WHERE " + inClause);
for(int i = 0; i < currentBatch.size(); i++){
pStmt.setInt(i+1, (currentBatch.get(i)));
}
rset = pStmt.executeQuery();
while(rset.next()){
int id = rset.getInt(1);
Clob detailsClob = rset.getClob(2);
Writer writer = adapter.getCharacterOutputStream(detailsClob);
String details = idToDetails.get(id);
if (details != null) {
writer.write(details);
}
writer.flush();
writer.close();
idToDetailsClob.put(id, detailsClob);
}
currentBatch.clear();
BaseSQLHelper.close(pStmt, rset);
}
int counter = 0;
pStmt = conn.prepareStatement("UPDATE PROGRAM_HISTORY SET DETAILS = ? WHERE ID = ?");
for(int i=0; i<IDList.size(); i++){
int index = 1;
Clob detailsClob = (Clob) idToDetailsClob.get(IDList.get(i));
pStmt.setClob(index++, detailsClob);
pStmt.setInt(index++, IDList.get(i));
pStmt.addBatch();
counter++;
if(counter % BATCH_SIZE == 0) {
pStmt.executeBatch();
pStmt.clearBatch();
counter = 0;
}
}
if(IDList.size() % BATCH_SIZE > 0) {
pStmt.executeBatch();
}
}
catch (SQLException se)
{
se.printStackTrace();
}
catch (IOException se)
{
se.printStackTrace();
}
finally
{
cleanup(conn, pStmt, null);
}
System.out.println(System.currentTimeMillis()-s1);
}
If I understand your code correctly, you are appending text to your details clob column.
Doing it in PL/SQL would be faster since you wouldn't have to fetch the clob across the network. For example you could prepare this statement:
DECLARE
l_details CLOB;
BEGIN
SELECT details INTO l_details FROM program_history WHERE ID = ?;
dbms_lob.append(l_details, ?);
END;
and bind currentBatch.get(i) and idToDetails.get(id).
Notice that you don't need an additional update with PL/SQL.
Execute your query with an updatable ResultSet so that you can update the data as you scroll through without separate update statements being executed.
You need to create your prepared statement with the resultSetConcurrency set to ResultSet.CONCUR_UPDATABLE. Check out the oracle documentation on dealing with streams for the various ways you can handle the clob data.

Categories