Same Neo4j query does not work in with jdbc - java

Playing around on my Neo4j on my localhost, I constructed this query to toggle the node property 'Active' between 'true' and 'false'
I works fine when executed in the browser but when I put it in my java class using JDBC the result is none.
String query = "MATCH (i:Item) "
+ "WHERE id(i)=? "
+ "SET i.active = NOT i.active";
PreparedStatement ps = con.prepareStatement(query);
ps.setInt(1, id);
int updates = ps.executeUpdate();

Your query should be changed as follows. You should define parameters in {}
String query = "MATCH (i:Item) "
+ "WHERE id(i)= {1} "
+ "SET i.active = NOT i.active";
Since you are not return anything you are getting return value as 0. executeUpdate() return either the row count for statement or 0 for statements that return nothing.

Related

Prepared Statement in Java/SQL Server not returning any results

List<Guest> guestList = new ArrayList<>();
String query = "select * from Guests where ? like ?";
System.out.println("select * from Guests where " + property + " like '%" + value + "%'");
PreparedStatement preparedStatement = connection.prepareStatement(query);
preparedStatement.setString(1, property);
preparedStatement.setString(2, "'%" + value + "%'");
ResultSet resultSet = preparedStatement.executeQuery();
guestList = getGuestListFromResultSet(resultSet);
return guestList;
As you can see above, I created a Prepared Statement, which is later populated with 2 values: property and value. Running the above query should give me some results in SQL Server.
I also tried these variations for setting the second parameter(value):
preparedStatement.setString(2, "%" + value + "%");
preparedStatement.setString(2, value);
None of these seem to work. What does work is simply building the query from string concatenation:
PreparedStatement preparedStatement = connection.prepareStatement("select * from Guests where " + property + " like '" + value + "'");
However, I want to use a Prepared Statement.
You can't use a variable as a column name. Instead, you can use dynamic SQL
String query = """
DECLARE #sql nvarchar(max) = '
select *
from Guests
where ' + QUOTENAME(?) + ' like #value;
';
EXEC sp_executesql #sql,
N'#value nvarchar(100)',
#value = ?;
""";
Note the use of QUOTENAME to correctly escape the column name.
Note also the use of sp_executesql to pass the value all the way through.
I'm not sure about the JDBC driver, but ideally you should use proper named parameters, rather than ?

Can't find an Error in SQL update statement

I'm working in one quiz game. There is question maker window. Which works good for saving question. But when want update one of text Field and press save, than error is happening. something is wrong with syntax?!
void insertCell(String tableNamer, String column, String value, int id) throws ClassNotFoundException, SQLException{
Class.forName("org.h2.Driver");
Connection conn = DriverManager.getConnection("jdbc:h2:file:C:/Users/Juris Puneiko/IdeaProjects/for_my_testings/src/sample/DB/Questions/For_Private/Easy", "Juris", "1");
PreparedStatement ps = conn.prepareStatement("UPDATE ? SET ? = ? where ID = ?");
ps.setString(1, tableNamer);
ps.setString(2, column);
ps.setString(3, value);
ps.setInt(4, id);
ps.executeUpdate();
ps.close();
conn.close();
}
org.h2.jdbc.JdbcSQLException: Syntax error in SQL statement "UPDATE ?[*] SET ? = ? WHERE ID = ? "; expected "identifier"; SQL statement:
UPDATE ? SET ? = ? where ID = ? [42001-196]
What is this >>> [*]?
What does it mean?
String sql = "UPDATE " + tableNamer + " SET " + column + " = ? where ID = ?";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, value);
ps.setInt(2, id);
ps.executeUpdate();
ps.close();
conn.close();
The placeholders can only be used for values in most SQL databases, not for identifiers like table or column names:
"UPDATE myTable SET myCol = ? where ID = ?" -- OK
"UPDATE ? SET ? = ? where ID = ?" -- not OK
The reason is that those parameters are also used for prepared statements, where you send the query to the database once, the database "prepares" the statement, and then you can use this prepared statement many times with different value parameters. this can improve DB performance because DB can compile and optimize the query and then use this processed form repeatedly - but to be able to do this, it needs to know names of the tables and columns involved.
To fix this, you only leave the ?s in for the values, and you concatenate the tableNamer and column manually:
"UPDATE " + tableNamer + " SET " + column + " = ? where ID = ?"
Keep in mind though that by doing this, tableNamer and column are now potentially vulnerable to SQL injection. Make sure that you don't allow user to provide or affect them, or else sanitize the user input.

How to merge multiple "SELECT" statement into one?

Currently, I am using for loop, which is unacceptably slow when orgList has thousands of elements inside:
String sql = "SELECT xua.XUAID, xua.XUA01, xua.XUA02 "
+ "FROM dbo.XDSysUseArea xua "
+ "WHERE xua.XUA03=?";
conn = ds.getConnection();
ps = conn.prepareStatement(sql);
for(HotelSource org : orgList) {
ps.setString(1, org.getPrimaryKey());
rs = ps.executeQuery();
while (rs.next()) {
// do sth
}
}
What is the right way to do the SELECT?
You should use SQL IN, for example:
SELECT ... FROM ... WHERE xua.XUA03 IN (x, y, z, ...)
You can still parameterise your query, but you need to generate the correct number of ? in the statement. So some psuedocode here because I don't do Java:
String params = "?, ?, ?, ?"; //you will have to generate enough of these yourself
//This is an exercise for you!
String sql = "SELECT xua.XUAID, xua.XUA01, xua.XUA02 "
+ "FROM dbo.XDSysUseArea xua "
+ "WHERE xua.XUA03 IN (" + params + ")";
conn = ds.getConnection();
ps = conn.prepareStatement(sql);
int index = 1;
for(HotelSource org : orgList) {
ps.setString(index, org.getPrimaryKey());
// ^^^^^ use index here
index++;
}
rs = ps.executeQuery();
while (rs.next()) {
// do sth
}
Note: The downside of this is that you mention you have thousands of entries in orgList which makes it really bad practice to use this method. In fact, SQL Server will not allow you to use more than a couple of thousand parameters.
Use IN operator no need to hit the query for each value
SELECT xua.XUAID, xua.XUA01, xua.XUA02
FROM dbo.XDSysUseArea xua
WHERE xua.XUA03 in (val1,val2,val3,..) -- pass the list here
Store org.getprimarkey() in a arraylist List<Integer> past it to where clause using in operator
SELECT xua.XUAID, xua.XUA01, xua.XUA02 "
+ "FROM dbo.XDSysUseArea xua "
+ "WHERE xua.XUA03 IN (mylist);
NOTE: replace [ ] in list using replaceall method.
You can use operator IN for this purpose. Example,
SELECT column_name(s)
FROM table_name
WHERE column_name IN (value1, value2, ...);

why does execute() return true on an empty table?

Through the following snippet, I am trying to run a query that either updates the data or inserts a new data into the table named JustPinged. The table contains a column named NodesThatJustPinged and LastPingedAt. If there is already a node in NodesThatJustPinged then the time in milliseconds in LastPingedAt is updated. Otherwise a new node information is inserted.
The problem is, that the following snippet is unable to insert the data into the database's table. The reason is the statement:
boolean duplicateExists = searchToEliminateDuplicates.execute();
returns true to start with. (Initially the table is empty) Why does this statement return true? According to the documentation it returns true if the first result is a ResultSet object; false if the first result is an update count or there is no result. So here the boolean should contain a false value. But it contains a true value and thus the if statement always works. (And in if section,update query works when there is nothing to update !)
String searchQuery = "select NodesThatJustPinged from JustPinged where NodesThatJustPinged = '" + nodeInfo + "'";
PreparedStatement searchToEliminateDuplicates = connection.prepareStatement(searchQuery);
boolean duplicateExists = searchToEliminateDuplicates.execute();
if(duplicateExists) {
// update the LastPingedAt column in the JustPinged table
String updateQuery = "update JustPinged set LastPingedAt='" + pingedAt + "' where NodesThatJustPinged = '" + nodeInfo + "'";
PreparedStatement updateStatement = connection.prepareStatement(updateQuery);
updateStatement.executeUpdate();System.out.println("If statement");
} else {
// make a new entry into the database
String newInsertionQuery = "insert into JustPinged values('" + nodeInfo + "','" + pingedAt + "')";
PreparedStatement insertionStatement = connection.prepareStatement(newInsertionQuery);
insertionStatement.executeUpdate();System.out.println("else statement");
}
So how should I edit the code, so that duplicate values are updated and new values are inserted?
Your searchQuery will return ResultSet. hence the execute method returns 'true'. Try using executeQuery instead.
So your code would become:
String searchQuery = "select NodesThatJustPinged from JustPinged where NodesThatJustPinged = '" + nodeInfo + "'";
Statement searchToEliminateDuplicates = connection.createStatement();
ResultSet duplicateExists = searchToEliminateDuplicates.executeQuery(searchQuery);
if(duplicateExists.next()) {
// update the LastPingedAt column in the JustPinged table
String updateQuery = "update JustPinged set LastPingedAt='" + pingedAt + "' where NodesThatJustPinged = '" + nodeInfo + "'";
PreparedStatement updateStatement = connection.prepareStatement(updateQuery);
updateStatement.executeUpdate();System.out.println("If statement");
} else {
// make a new entry into the database
String newInsertionQuery = "insert into JustPinged values('" + nodeInfo + "','" + pingedAt + "')";
PreparedStatement insertionStatement = connection.prepareStatement(newInsertionQuery);
insertionStatement.executeUpdate();System.out.println("else statement");
}
P.S. If you are using PreparedStatement, then use parameters in your query and call ps.setString etc.
PPS. Don't use execute() method. Use executeQuery or executeUpdate. execute() is used where you don't know in advance whether your query is INSERT or UPDATE.
PPPS Close your resultset and statements as soon as you are done with them.
PPPPS A more better approach is to use count aggregate function in your SQL statement i.e.
select count(NodesThatJustPinged) from JustPinged where NodesThatJustPinged = '" + nodeInfo + "'";
Now you can check whether count is 0 or greater than 1 and branch your code accordingly.
A SELECT statement that returns zero rows will still return a ResultSet -- just one that immediately returns false when calling next(). You need to check the number of rows in the returned ResultSet.

Cannot issue data manipulation statements with executeQuery()

In MySQL I have two tables, tableA and tableB. I am trying to execute two queries:
executeQuery(query1)
executeQuery(query2)
But I get the following error:
can not issue data manipulation statements with executeQuery().
What does this mean?
To manipulate data you actually need executeUpdate() rather than executeQuery().
Here's an extract from the executeUpdate() javadoc which is already an answer at its own:
Executes the given SQL statement, which may be an INSERT, UPDATE, or DELETE statement or an SQL statement that returns nothing, such as an SQL DDL statement.
When executing DML statement , you should use executeUpdate/execute rather than executeQuery.
Here is a brief comparison :
If you're using spring boot, just add an #Modifying annotation.
#Modifying
#Query
(value = "UPDATE user SET middleName = 'Mudd' WHERE id = 1", nativeQuery = true)
void updateMiddleName();
For Delete query - Use #Modifying and #Transactional before the #Query like:-
#Repository
public interface CopyRepository extends JpaRepository<Copy, Integer> {
#Modifying
#Transactional
#Query(value = "DELETE FROM tbl_copy where trade_id = ?1 ; ", nativeQuery = true)
void deleteCopyByTradeId(Integer id);
}
It won't give the java.sql.SQLException: Can not issue data manipulation statements with executeQuery() error.
Edit:
Since this answer is getting many upvotes, I shall refer you to the documentation as well for more understanding.
#Transactional
By default, CRUD methods on repository instances are transactional. For read operations,
the transaction configuration readOnly flag is set to true.
All others are configured with a plain #Transactional so that default transaction
configuration applies.
#Modifying
Indicates a query method should be considered as modifying query as that changes the way
it needs to be executed. This annotation is only considered if used on query methods defined
through a Query annotation). It's not applied on custom implementation methods or queries
derived from the method name as they already have control over the underlying data access
APIs or specify if they are modifying by their name.
Queries that require a #Modifying annotation include INSERT, UPDATE, DELETE, and DDL
statements.
Use executeUpdate() to issue data manipulation statements. executeQuery() is only meant for SELECT queries (i.e. queries that return a result set).
#Modifying
#Transactional
#Query(value = "delete from cart_item where cart_cart_id=:cart", nativeQuery = true)
public void deleteByCart(#Param("cart") int cart);
Do not forget to add #Modifying and #Transnational before #query. it works for me.
To delete the record with some condition using native query with JPA the above mentioned annotations are important.
That's what executeUpdate is for.
Here's a very brief summary of the difference: http://www.coderanch.com/t/301594/JDBC/java/Difference-between-execute-executeQuery-executeUpdate
This code works for me: I set values whit an INSERT and get the LAST_INSERT_ID() of this value whit a SELECT; I use java NetBeans 8.1, MySql and java.JDBC.driver
try {
String Query = "INSERT INTO `stock`(`stock`, `min_stock`,
`id_stock`) VALUES ("
+ "\"" + p.get_Stock().getStock() + "\", "
+ "\"" + p.get_Stock().getStockMinimo() + "\","
+ "" + "null" + ")";
Statement st = miConexion.createStatement();
st.executeUpdate(Query);
java.sql.ResultSet rs;
rs = st.executeQuery("Select LAST_INSERT_ID() from stock limit 1");
rs.next(); //para posicionar el puntero en la primer fila
ultimo_id = rs.getInt("LAST_INSERT_ID()");
} catch (SqlException ex) { ex.printTrace;}
executeQuery() returns a ResultSet. I'm not as familiar with Java/MySQL, but to create indexes you probably want a executeUpdate().
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/java_swing_db", "root", "root");
Statement smt = conn.createStatement();
String sql = "SELECT * FROM `users` WHERE `email` = " + email + " AND `password` = " + password + " LIMIT 1;";
String registerSql = "INSERT INTO `users`(`email`, `password`, `name`) VALUES ('" + email + "','" + password + "','" + name + "')";
System.out.println("SQL: " + registerSql);
int result = smt.executeUpdate(registerSql);
System.out.println("Result: " + result);
if (result == 0) {
JOptionPane.showMessageDialog(this, "This is alredy exist");
} else {
JOptionPane.showMessageDialog(this, "Welcome, Your account is sucessfully created");
App.isLogin = true;
this.dispose();
new HomeFrame().show();
}
conn.close();
Besides executeUpdate() on the parentheses, you must also add a variable to use an SQL statement.
For example:
PreparedStatement pst = connection.prepareStatement(sql);
int numRowsChanged = pst.executeUpdate(sql);

Categories

Resources