Column result doesn't as be expected - java

Here i have query to join two table and merge it into one result by using this query
String query = "SELECT * FROM tb_barang RIGHT JOIN tb_jenis ON tb_barang.kd_jenis = tb_jenis.kd_jenis ";
And here is my table structures for both of tables
Table "tb_barang"
https://i.stack.imgur.com/6OpeC.png
And Table "tb_jenis"
https://i.stack.imgur.com/UhLty.png
I was expecting the output like this
https://i.stack.imgur.com/zhtHx.png
However, when I take column "jenis", java throw exception into it because either out of range or column not found.
Then i check whether the column is exist or not using :
ResultSet resTabel = new mysqlDriver().getKolomBarangList();
ResultSetMetaData metaData = resTabel.getMetaData();
int colCount = metaData.getColumnCount();
if (resTabel.next()) {
for (int i = 1; i <= colCount; i++) {
System.out.println("Col(" + i + ") '" + metaData.getColumnName(i) + "' value:" + resTabel.getString(i));
}
The output:
Col(1) 'kd_barang' value:BAR0000
Col(2) 'nama_barang' value:A
Col(3) 'kd_jenis' value:J_1
Col(4) 'jumlah_barang' value:1
Col(5) 'harga_satuan' value:1
BUILD SUCCESSFUL (total time: 35 seconds)
How to achieve this? Thanks for response

Apparently, i was miss type the method name thanks to #forpas. the getKolomBarangList() refer to field name of table tb_barang and not executing "JOIN" clauses
protected ResultSet getBarangList()throws SQLException, NullPointerException, ClassNotFoundException{
String query = "SELECT * FROM tb_barang RIGHT JOIN tb_jenis ON tb_barang.kd_jenis = tb_jenis.kd_jenis ";
if(resForListBarang == null){
resForListBarang = alwaysDoResultSet(query);
}
return resForListBarang;
}
protected ResultSet getKolomBarangList() throws SQLException, Exception{
String query = "SELECT * FROM tb_barang";
if(getBarangKolom == null){
getBarangKolom = alwaysDoResultSet(query);
}
return getBarangKolom;
}
And the output for getBarangList() was expected as the final result
Col(1) 'kd_barang' value:BAR0000
Col(2) 'nama_barang' value:A
Col(3) 'kd_jenis' value:J_1
Col(4) 'jumlah_barang' value:1
Col(5) 'harga_satuan' value:1
Col(6) 'kd_jenis' value:J_1
Col(7) 'jenis' value:Pakan Hewan
BUILD SUCCESSFUL (total time: 21 seconds)
Thanks to anyone who helping me out :)

Related

sql query to check existing records

I have data in following format:
HashMap<PageID, Set<SubscriberIDS>>
What I need to check is how many SubscriberIDS for each of the PageIDs do not exist in a MySQL table already. MySQL table has PageID and SubscriberID columns.
This is what I have so far:
String NEW_SUBSCRIBER_COUNT = "SELECT ? - COUNT(*) as new_subscribers from FB_SUBSCRIPTIONS WHERE PAGEID=? AND SUBSCRIBERID IN (?)";
First parameter being numberOFSubscriberIDs, Second being PageId and Third being SubscriberIds
but this will need to be hit for each pageId. How do I modify it to give me number of new subscribers for each PageID using single query.
Is there any specific need to do it in one query? Because while it can, it might actually be more readable to use your original solution and invoke a query for each page id. In any case, what you want can't be done in a single line, so you need to expect to loop at a given point.
// Build dynamic query
StringBuilder whereClause = new StringBuilder();
Iterator<PageID> it = yourMap.keySet().iterator();
while(it.hasNext()){
PageID key = it.next();
Set<SubscriberIDS> value = yourMap.get(key);
// You need to fill the 'IN' clause with multiple parameters, one for each subscriber id
StringBuilder inClause = new StringBuilder();
for(SubscriberIDS subId : value){
if(inClause.length > 0){
inClause.append(", ");
}
inClause.append("?");
preparedStatement.setInt(paramIndex++, subId.getId());
}
// For each page id we append a new 'OR' to our query
if(whereClause.lenght > 0){
whereClause.append(" OR ");
}
whereClause.append("(PAGEID=? AND SUBSCRIBERID IN (").append(inClause.toString()).append("))");
}
String query = "SELECT PAGEID, COUNT(SUBSCRIBERID) AS SUBSCRIBERS FROM FB_SUBSCRIPTIONS WHERE " + whereClause.toString() + " GROUP BY PAGEID";
// Create prepared statement and set parameters
PreparedStatement preparedStatement = connection.prepareStatement(query);
int paramIndex = 0;
it = yourMap.keySet().iterator();
while(it.hasNext()){
PageID key = it.next();
Set<SubscriberIDS> value = yourMap.get(key);
preparedStatement.setInt(paramIndex++, key.getId());
for(SubscriberIDS subId : value){
preparedStatement.setInt(paramIndex++, subId.getId());
}
}
// Execute query, loop over result and calculate new subscriptions
ResultSet rs = preparedStatement.executeQuery();
while(rs.next()){
int pageId = rs.getInt("PAGEID");
int newSubscriptions = yourMap.get(pageId).size() - rs.getInt("SUBSCRIBERS");
System.out.println(pageId + ", " + newSubscriptions);
}
Given following data in your map:
PAGEID SUBSCRIBERIDS
1 1,3,4,5,9
2 3,4,5,6,8,9
3 2,5,6
And following data in the DB:
PAGEID SUBSCRIBERIDS
1 3,4,10,11
2 1,2,5,7
3 1,2,5,6,7,8,9
This should give following output:
1,3
2,6
3,0
I haven't actually ran the code, so it might need some adjustments, but it gives you the general idea...

JDBC dynamic query, only put value to string if not -1

I have a problem with JDBC and java.
I have a Query like this:
String updateSql = "UPDATE league SET season=?, playedMatches=?, percentHomeWins=?, percentDraws=?, percentAwayWins=?, averageGoalsPerGame=?, averageGoalsHomePerGame=?, averageGoalsAwayPerGame=?, percentOverOne=?, percentOverTwo=?, percentOverThree=?, percentBothTeamsScored=?, scoredGoalsTotal=? " + whereClause + " and country='" + l.getCountry() + "'";
all values after "season" can either be a number >= 0 or -1. -1 means, that there is no value. the values come from a class that holds data (like an object model).
I want only the values in my query, which are >= 0. The other one should not be in the query, because they replace data in the database, which they should not.
Can anyone help me archiving this?
Use a StringBuilder to dynamically build the SQL statement, e.g.
StringBuilder sql = new StringBuilder("UPDATE league SET season=?");
List<Integer> numValues = new ArrayList<>();
if (l.getPlayedMatches() != -1) {
sql.append(", playedMatches=?");
numValues.add(l.getPlayedMatches());
}
if (l.getPercentHomeWins() != -1) {
sql.append(", percentHomeWins=?");
numValues.add(l.getPercentHomeWins());
}
// ... more code ...
sql.append(whereClause)
.append(" and country=?");
try (PreparedStatement stmt = conn.prepareStatement(sql.toString())) {
int paramIdx = 0;
stmt.setInt(++paramIdx, l.getSeason());
for (Integer numValue : numValues)
stmt.setInt(++paramIdx, numValue);
stmt.setString(++paramIdx, l.getCountry());
stmt.executeUpdate();
}

Unexpected behaviour of SELECT query after UPDATE

Following is the logic in my java code :
con.setAutoCommit(false);
int starIndex = 0;
List Details = new ArrayList();
while (true) {
isRsEmpty = true;
String my_Query = "select * from x,y,z where"
+ " x.a = y.b"
+ " x.a = z.c"
+ "y.b = z.e"
+ " ORDER BY a ASC"
+ " limit 5"
+ " offset " + starIndex;
preparedStatement = con.prepareStatement(my_Query);
rs = preparedStatement.executeQuery();
while (rs.next()) {
isRsEmpty = false;
//Other processing steps
starIndex++;
Details.add(rs.getInt("id"));
}
if(isRsEmpty){
starIndex = 0;
}
Iterator itr = Details.iterator();
String updateTable = "UPDATE x SET status = ? where i = ? and j = ? and k = ?";
updatePreparedStatement = con.prepareStatement(updateTable);
while (itr.hasNext()) {
updatePreparedStatement.setInt(1, 1);
updatePreparedStatement.setString(2, "zzz");
updatePreparedStatement.setInt(3, 9);
updatePreparedStatement.setInt(4, 10);
updatePreparedStatement.addBatch();
}
updatePreparedStatement.executeBatch();
con.commit();
Details.clear();
}
The Problem :
I have 13 entries in my table which meets the select query.
When I first time run the query my Limit is 5 and Offset is 0 and I get
5 records correctly from the table and the selected 5 records are updated.
After doing the update to the table when the select query runs again it gives me 3 records.This is unexpected since I have more 8 records left in the table.Again the 3 records are updated.
Again when the select query runs it gives me 0 records.
Then again a select query runs which gives me 5 records and updates the 5 records.
I am not able to understand this behaviour. If I run my select query without update then it runs correctly which gives me 5,5,3 records , but with the above logic it gives me 5,3,0,5 records.
What is the problem here ?
Note : In the above program all the variables like PreparedStatement and other are declared correctly.
Thank you
Is there any chance you are missing "and" keyword between your conditions in the select query?
String my_Query = "select * from x,y,z where"
+ " x.a = y.b"
+ " AND x.a = z.c"
+ " AND y.b = z.e"
+ " ORDER BY a ASC"
+ " limit 5"
+ " offset " + starIndex;
I don't know if that would solve the problem but I find it weird that it works like this.

Obtaining a count of data from one SQL table with a relationship to another and using this in java

I have 2 database tables for my program: GameInfo and Characters.
How this works is that a Game has 4 maps with different names and each character added to the game must be assigned any of the 4 maps. Now I have the sql statement which returns a result set named "Expr1001, of the number of characters on each map. I then need to add this information to a jTable and link up the corresponding amount of each characterson a map, with the mapname.
My ResultSet with the query which returns the amount of characters on each map:
ResultSet qs = dbm.queryDatabase("SELECT Expr1001 FROM (SELECT GameInfo.mapname, SUM(IIF(Map = GameInfo.mapname,1,0)) FROM (SELECT * FROM [Character] INNER JOIN Player ON Character.PlayerID=Player.[ID]) AS A RIGHT JOIN GameInfo ON A.Character.map = GameInfo.mapname GROUP BY GameInfo.mapname) AS [%$###_Alias]");
The whole method which gets the Game Info from the database from the GameInfo table, which comprises of a GameID and MapName only.
public Game[] getGameInfo(){
Game[] arr = null; //Creates an array of Games
try { //getting list from database
ResultSet rs = dbm.queryDatabase("Select Count(GameID) as NumGames from GameInfo" );
//While there are still more rows to read from the database.
rs.next();
int count = rs.getInt("NumGames");
arr = new Game[count];
String sql = "Select * from GameInfo";
// System.out.println(sql);
rs = dbm.queryDatabase(sql);
//Take the info from the current row
//Add the info to the array
ResultSet qs = dbm.queryDatabase("SELECT Expr1001 FROM (SELECT GameInfo.mapname, SUM(IIF(Map = GameInfo.mapname,1,0)) FROM (SELECT * FROM [Character] INNER JOIN Player ON Character.PlayerID=Player.[ID]) AS A RIGHT JOIN GameInfo ON A.Character.map = GameInfo.mapname GROUP BY GameInfo.mapname) AS [%$###_Alias]");
for(int i = 0; rs.next(); i++){
arr[i] = new Game(
rs.getInt("GameInfo.GameID"),
rs.getString("GameInfo.mapname"),
qs.getInt(i));
}//Creates a Game from the currently selected info
} catch (Exception e) {
JOptionPane.showMessageDialog(null, "Failed to get Games");
e.printStackTrace();
}
return arr;
}
}
The data is then added to the jTable which is on a Panel in the GameInfoPanel class:
public void refreshTable() {
//remove old stuff
refreshing = true;
Game[] arr = gim.getGameInfo();
DefaultTableModel model = (DefaultTableModel) GameInfoTable.getModel();
while (model.getRowCount() > 0) {
model.removeRow(0);
}
for (int i = 0; i < arr.length; i++) {
model.addRow(new Object[]{
arr[i].getNumberOfCharacters(),
arr[i].getID(),
arr[i].getMapName()});
}
refreshing = false;
//load new data from database using manager
}
I keep getting the error which points to the ResultSet qs line: "user lacks privilege or object not found: A.CHARACTER.MAP" when I try and run the program even though when I copy this statement into Microsoft Access and run it, it's fine.
Help please!
Thanks.
(I am still at school so not really a genius on this at all so please have mercy if I've done some stupid things)
Don't run a select count(*) first to get the number of games for allocating an array. Build you result in a List, which will auto-expand as needed. You can always convert the list to an array later, if needed.
Don't run two queries when one can do the job, especially when you already join to the table in question.
Your SQL is unreadable, so here it is in a more readable format:
String sql = "SELECT Expr1001" +
" FROM (SELECT GameInfo.mapname" +
", SUM(IIF(Map = GameInfo.mapname,1,0))" +
" FROM (SELECT *" +
" FROM [Character]" +
" INNER JOIN Player ON Character.PlayerID=Player.[ID]" +
") AS A" +
" RIGHT JOIN GameInfo ON A.Character.map = GameInfo.mapname" +
" GROUP BY GameInfo.mapname" +
") AS [%$###_Alias]";
The outer query does nothing. Get rid of it.
Don't SELECT *. Select the columns you want, i.e. Character.map.
Since you want GameID, add it to the GROUP BY.
Specify an alias for the SUM value.
public Game[] getGameInfo(){
String sql = " SELECT GameInfo.GameID" +
", GameInfo.mapname" +
", SUM(IIF(C.map = GameInfo.mapname,1,0)) AS CharacterCount" +
" FROM ( SELECT Character.map" +
" FROM [Character]" +
" JOIN Player ON Player.[ID] = Character.PlayerID" +
") C" +
" RIGHT JOIN GameInfo ON GameInfo.mapname = C.map" +
" GROUP BY GameInfo.GameID" +
", GameInfo.mapname";
try (ResultSet rs = dbm.queryDatabase(sql)) {
List<Game> games = new ArrayList<>();
while (rs.next())
games.add(new Game(rs.getInt("GameID"),
rs.getString("mapname"),
rs.getInt("CharacterCount")));
return games.toArray(new Game[games.size()]);
} catch (Exception e) {
JOptionPane.showMessageDialog(null, "Failed to get Games");
e.printStackTrace();
return null;
}
}

JdbcTemplate does not support Parameterized Query 'IN' case? Must by NamedParameterJdbcTemplate?

Aimed at preventing SQL injection attacks, all the SQL Statement code in my project should transformed to Parameterized Query. But I got a problem when the query condition includes a 'IN' case. Like this (Using DB2 database):
String employeeId = 'D2309';
String name = "%brady%";
List<Integer> userRights = new ArrayList<Integer>();
userRights.add(1);
userRights.add(2);
userRights.add(3);
String sql = "SELECT * FROM T_EMPLOYEE WHERE EMPLOYEE_ID = ? AND NAME LIKE ?
AND RIGHT IN (?)";
jdbcTemplate.query(sql, new Object[] {employeeId, name, userRights}, new
EmployeeRowMapper());
The above code runs failed with the exception:
org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad
SQL grammar [SELECT * FROM T_EMPLOYEE WHERE EMPLOYEE_ID = ? AND NAME LIKE ? AND
RIGHT IN (?)]; nested exception is com.ibm.db2.jcc.am.io: [jcc][1091][10824]
[3.57.82] .... ERRORCODE=-4461, SQLSTATE=42815
The question here is that does not JdbcTemplate support Parameterized Query for IN case? and I know this work can be done by NamedParameterJdbcTemplate, and whether only NamedParameterJdbcTemplate can do IN case query?
Thanks a lot.
As I already mentioned in the comments, I'm not happy with this solution as it dynamically generates a number of SQL statements. Given the number of userRights is between 1 and n, it requires up to n prepared statements in the cache.
The below should work (I did not try it).
String employeeId = 'D2309';
String name = "%brady%";
List<Integer> userRights = new ArrayList<Integer>();
userRights.add(1);
userRights.add(2);
userRights.add(3);
// build the input string
StringBuilder sb = new StringBuilder();
for (int i = 0; i < userRights.size; i++) {
sb.append("?");
if (i < userRights.size() - 1) {
sb.append(", ");
}
}
// build the SQL
String sql = "SELECT * FROM T_EMPLOYEE WHERE EMPLOYEE_ID = ?" +
" AND NAME LIKE ?" +
" AND RIGHT IN (" + sb.toString() + ")";
// init the object array
// size is employeeId + name + right
Object[] param = new Object[2 + userRights.size()];
// fill it
param[0] = employeeId;
param[1] = name;
for (int i = 0; i < userRights.size(); i++) {
param[i + 2] = userRights.get(i);
}
jdbcTemplate.query(sql, param, new EmployeeRowMapper());

Categories

Resources