Prepared Statement INSERT JDBC MySQL - mysql

I am getting an error on doing ' mvn tomcat:run " . The error I am getting is:
exception
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [INSERT INTO ibstechc_dev.device (key, ip_address, type, name) VALUES (?, ?, ?, ?)]; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'key, ip_address, type, name) VALUES ('abcd', 'abcd', 1234, 'abcd')' at line 1
root cause
org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [INSERT INTO ibstechc_dev.device (key, ip_address, type, name) VALUES (?, ?, ?, ?)]; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'key, ip_address, type, name) VALUES ('abcd', 'abcd', 1234, 'abcd')' at line 1
org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:237)
org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72
My code segment is:
List<Device> devices = this.jdbcTemplate.query(
"select * from xyz.device a,xyz.user_device b "
+ "where b.user_id = ? and a.device_id = b.device_id and "
+ "a.type = ?",
new Object[]{userId,type},
new RowMapper<Device>() {
public Device mapRow(ResultSet rs, int rowNum) throws SQLException {
Device device = new Device();
device.setId(Long.valueOf(rs.getInt(1)));
device.setKey(rs.getString(2));
device.setIPAddress(rs.getString(3));
device.setType(rs.getInt(4));
device.setName(rs.getString(5));
return device;
}
});
System.out.println("Found for user..." + userId);
return devices;
}
public void create(Device device) {
this.jdbcTemplate.update("INSERT INTO xyz.device (key, ip_address, type, name) VALUES (?, ?, ?, ?)",
new Object[]{device.getKey(), device.getIPAddress(), device.getType(), device.getName()});
}
public void delete(Device device) {
this.jdbcTemplate.update("DELETE FROM xyz.device WHERE device_id = ?", new Object[] {device.getId()});
}
public void update(Device device) {
this.jdbcTemplate.update(
"UPDATE xyz.device SET key = ?, ip_address = ?, type = ?, name =? WHERE device_id = ?", new Object[]{device.getId(),device.getKey(), device.getIPAddress(), device.getType(), device.getName()});
And my Debug.java code is:
public String getNavBarData(){
Device device = new Device();
device.setKey("abcd");
device.setIPAddress("abcd");
device.setType(1234);
device.setName("abcd");
deviceDao.create(device);
return "";
The MySQL table has the same columns as in my code above with NOT NULL for each field. I have used the same code for a different functionality and it works there. Why am I getting this error for this one? Pls. Help.

KEY is a reserved word in Mysql. Therefore you either rename the column (which is better in a long run) or use back ticks around it.
That being said you insert statement should look like this
INSERT INTO xyz.device (`key`, ip_address, type, name) VALUES (?, ?, ?, ?)
^ ^
The same goes to your update statement
UPDATE xyz.device SET `key` = ?, ip_address = ?, type = ?, name =? WHERE device_id = ?
^ ^

Related

Rollback transaction not working properly

In database manipulation command such as insert, update or delete can sometime throws exception due to invalid data. To protect the integrity of application data we must make sure when we a transaction was failed we must rollback
PreparedStatement ps = null;
Connection conn = null;
try {
conn = DriverManager.getConnection( URL, USERNAME, PASSWORD );
String query = "INSERT INTO tbl1(id, username) " +
"VALUES (?, ?)";
ps = conn.prepareStatement( query );
ps.setString( 1, "javaduke" );
ps.execute();
query = "INSERT INTO tbl2 (id, tbl1_id, " +
"quantity, price) VALUES (?, ?, ?, ?)";
ps = conn.prepareStatement( query );
ps.setInt( 1, id );
ps.setInt( 2, tbl_id );
ps.setInt( 3, 10 );
ps.setDouble( 4, 29.99 );
ps.execute();
}
catch ( SQLException e )
{
conn.rollback()
e.printStackTrace();
}
I guess this is Java.
Right after you get your connection object, turn off autocommit, like so.
conn = DriverManager.getConnection( URL, USERNAME, PASSWORD );
conn.setAutoCommit(false);
Right after your last execute() do this.
conn.commit();
Then the rollback() in your exception handler should do what you expect.
This should extend the scope of your transaction to beyond a single SQL query.

"Cannot set property 'length' of undefined " error when querying my mySQL using NodeJs

Im trying to query mySQL database using NodeJS to check if a row exists if it doesn't to create it if it does to update it however am getting an error of 'Cannot set property 'length' of undefined' not sure why kindly assist. Below is my code
const latitude = req.body.latitude;
const longitude = req.body.longitude;
const user_email = req.body.user_email;
db.query('SELECT * FROM location WHERE user_email =?', [user_email],
(error, results, fields)=>{
if (error) {
console.error(error.message);
res.send("success");
} else if(results && results.length == 0){
db.query('INSERT INTO location(latitude, longitude, user_email) VALUES("'+latitude+'", "'+longitude+'", "'+user_email+'")',
[latitude, longitude, user_email]);
res.send("success");
}else{
db.query('UPDATE location SET latitude = ? , longitude = ?, WHERE user_email = ? '[latitude, longitude,user_email]);
res.send("success");
}
}
)
Suggested changes:
db.query(
'SELECT * FROM location WHERE user_email =?',[user_email],
(error, results, fields)=>{
if (error) {
console.error(error.message);
res.send("success");
} else if (results && results.length == 0){
db.query(
'INSERT INTO location(latitude, longitude, user_email)
VALUES("'+latitude+'", "'+longitude+'", "'+user_email+'")',
[latitude, longitude, user_email]);
res.send("success");
}else{
...
Notes:
Check for errors. Always check for errors :)
I believe there should be a comma before [user_mail]
Check if "results" null before attempting to reference results.length
In Javascript, "==" means "check for equality", whereas "=" means "assign to variable".
One option here would be to take advantage of MySQL's ON DUPLICATE KEY functionality. Assuming your had a unique index on the user_email column, you may try this syntax:
INSERT INTO location (latitude, longitude, user_email)
VALUES (?, ?, ?)
ON DUPLICATE KEY UPDATE latitude = ?, longitude = ?;
This would only require a single query in Node:
db.query('INSERT INTO location (latitude, longitude, user_email) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE latitude = ?, longitude = ?',
[latitude, longitude, user_email, latitude, longitude]);
res.send("success");
The major potential problem with doing a select first, and basing the decision on whether or not to insert on that select, is that another process might insert in between these two commands. That is, unless you use a certain type of transaction to ensure that the select and update happen atomically, your code's current approach could still result in a duplicate record being inserted. Using ON DUPLICATE KEY places this responsibility on the database.

How to read a data file and insert data into a mysql database

I am new to Java and I'm trying to insert data into a mysql database using a text file. My text file has 5 rows. I have 3 SQL insert Queries. Each query will insert 5 rows into the database.
Example queries are:
INSERT INTO `session` (`emp`, `SessionID`, `SessionDate`, `SessionStartTime`, 'SessionEndTime') VALUES (Tyler, NULL, ?, ?, ?);
INSERT INTO `session` (`emp`, `SessionID`, `SessionDate`, `SessionStartTime`,'SessionEndTime') VALUES (MAX, NULL, ?, ?, ?);
INSERT INTO `session` (`emp`, `SessionID`, `SessionDate`, `SessionStartTime`,'SessionEndTime') VALUES (James, NULL, ?, ?, ?);
Example text file:
textfile
Here is a snippet of my code. I having problems with figuring out how to read the text file and inserting it into the database. Note that the code only has one my queries. I'm trying to get one query to work before adding the others.
I'm looking for some advice on reading the file and the prepared statements for the date, start time, and end time.
any suggestions?
try
{
//Create a mysql database connection
String dbUrl = "jdbc:mysql://localhost:3306/mytest";
String username = "root"; //Database Username
String password = "abcdefg"; //Database Password
Class.forName("com.mysql.jdbc.Driver"); //Load mysql jdbc driver
Connection con = DriverManager.getConnection(dbUrl,username,password); //Create Connection to DB
// mysql query to insert data into session table
String query = " INSERT INTO `session` (`emp`, `SessionID`,
`SessionDate`, `SessionStartTime`) VALUES (Tyler, NULL, ?, ?, ?);
try {
BufferedReader bReader = new BufferedReader(newFileReader("c:/sessionstime"));
String line = "";
while ((line = bReader.readLine()) != null)
{
try
{
if (line != null)
{
String[] array = line.split(",");
for(String result:array)
{
// create mysql insert preparedstatement
PreparedStatement preparedStmt = con.prepareStatement(query);
preparedStmt.setDate (1, sessiondate[0]);
preparedStmt.setTime (2, sessionstarttime[1]);
preparedStmt.setTime (3, sessionendtime[2]);
preparedStmt.addBatch();
// execute the preparedstatement
preparedStmt.executeBatch();
// close database connection
con.close();
}
catch (Exception e)
{
System.err.println("Got an exception!");
System.err.println(e.getMessage());
}

update some attributes of an object and return the whole object

I am trying to update a Customer password having his email, and after my update i want the ResponseEntity to return the whole Customer Object after modification is done.
But I am having this error into postman:
"error": "Internal Server Error",
"error_description": [
"could not execute batch; SQL [insert into tcustomer (authentication_uid, creation_date, attribute_uid, default_payment_method_uid, guid, last_edit_date, pref_bill_address_uid, pref_ship_address_uid, status, storecode, type, user_id, uidpk) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute batch"
]
I am passing a JSON with the the password and email:
{
"password": "miam",
"userId": "ton.nya#yahoo.fr"
}
here is the serviceImpl:
public CustomerDto updateCustomerPassword( String userId, String password) {
CustomerAuthentication customerAuthentication = new CustomerAuthentication();
customerAuthentication.setPassword(password);
Customer customer = new Customer();
customer.setAuthenticationUid(customerAuthentication);
customer.setUserId(userId);
Customer result = customerRepository.save(customer);
return customerMapper.customerToCustomerDto(result);
}
here is the ressource
#PutMapping(CUSTOMER_ENDPOINT)
#ResponseStatus(value = HttpStatus.NO_CONTENT)
#ApiResponses(value = {
#ApiResponse(code = 201, message = "The Customer has been created", response = CustomerDto.class),
#ApiResponse(code = 204, message = "The Customer has been updated", response = CustomerDto.class),
#ApiResponse(code = 500, message = "Unexpected error")
})
#Timed
public ResponseEntity updateCustomer(final HttpServletRequest request, #RequestBody String userId, String password)throws MethodArgumentNotValidException{
log.debug("[CustomerResource] PUT {} Updating Customer", CUSTOMER_ENDPOINT);
CustomerDto result = customerService.updateCustomerPassword(userId,password);
log.debug("[CustomerResource] Customer ({}) Updated",result.getUidpk());
return new ResponseEntity<>(result,null, HttpStatus.NO_CONTENT);
}
Are there any other solution? Thanks.

Entity inheritance an error while refreshing with EntityManager

When using entity inheritance hierarchy witch #DiscriminatorColumn storing DiscriminatorType.STRING values in MySQL ENUM. Below code example:
#Entity
#DiscriminatorColumn(name ="account_type", discriminatorType = DiscriminatorType.STRING,
columnDefinition = "ENUM('natural_person', 'firm', 'provider', 'employee', 'administrator', 'moderator', 'user')")
#DiscriminatorValue("user")
public class User implements Serializable { ... }
and inherited entity:
#Entity
#DiscriminatorValue("firm")
public class Firm extends User { ... }
when I create Firm object or removes everything works ok, even when I find it with EntityManager, but if I make EnityManager.refresh(firm) than there is an error complaining about:
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'firm0_.account_type' in 'field list'
UPDATE:
When I changed this columnDefinition of #DescriminatorColumn by deleting it and storing strings "firm", "user", ERROR ALSO OCCURES!
UPDATE 2:
I have a little suggestion that as Firm extends UserAccount this discriminator column account_type should be in user_account table. So error firm0.account_type seems stupid as it search this column in user_account.account_type!
I have another subclass Person and it persists and than saves OK, but Firm only persists, removes but DON'T REFRESH!
UPDATE 3:
Found sql log like this:
Hibernate:
insert
into
user_account
(activation_code, email, last_failed_login, last_logged, login, password, registration_date, account_type)
values
(?, ?, ?, ?, ?, ?, ?, 'firm')
Hibernate:
insert
into
firm
(address_city, address_country, address_office_no, address_building_no, address_state, address_street, address_zip_code, client_id, company_number, name, phone_number, skype_name, statistic_number, vatin, user_id)
values
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate:
select
firm0_.user_id as user_id2_14_0_,
firm0_1_.activation_code as activati3_14_0_,
firm0_1_.email as email4_14_0_,
firm0_1_.last_failed_login as last_fai5_14_0_,
firm0_1_.last_logged as last_log6_14_0_,
firm0_1_.login as login7_14_0_,
firm0_1_.password as password8_14_0_,
firm0_1_.registration_date as registra9_14_0_,
firm0_.address_city as address_1_3_0_,
firm0_.address_country as address_2_3_0_,
firm0_.address_office_no as address_3_3_0_,
firm0_.address_building_no as address_4_3_0_,
firm0_.address_state as address_5_3_0_,
firm0_.address_zip_code as address_7_3_0_,
firm0_.client_id as client_15_3_0_,
firm0_.company_number as company_8_3_0_,
firm0_.name as name9_3_0_,
firm0_.skype_name as skype_n11_3_0_,
firm0_.statistic_number as statist12_3_0_,
firm0_.vatin as vatin13_3_0_,
firm0_2_.corporation_id as corporat5_8_0_,
firm0_2_.description as descript1_8_0_,
firm0_2_.name as name2_8_0_,
firm0_2_.type as type3_8_0_,
firm0_.account_type as account_1_14_0_
from
firm firm0_
inner join
user_account firm0_1_
on firm0_.user_id=firm0_1_.user_id
left outer join
provider firm0_2_
on firm0_.user_id=firm0_2_.provider_id
where
firm0_.user_id=?
Jun 10, 2015 5:37:16 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
WARN: SQL Error: 1054, SQLState: 42S22
Jun 10, 2015 5:37:16 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
ERROR: Unknown column 'firm0_.account_type' in 'field list'
Jun 10, 2015 5:37:16 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl stop
INFO: HHH000030: Cleaning up connection pool
I'm guessing that when JPA generates the DDL it is using the columnDefinition string as a literal for the column definition. Thus, it should be "account_type ENUM('natural_person', 'firm', 'provider', 'employee', 'administrator', 'moderator', 'user')"
Ok It seems I found solution but it is odd, and I will be testes it later.
private String accountType;
#Column(name = "account_type", insertable = false, updatable = false)
public String getAccountType() {
return accountType;
}
public void setAccountType(String accountType) {
this.accountType = accountType;
}
I have added this code into UserAccount (superclass - root of inheritance hierarchy), where discriminator column is defined... BUT it seems odd behaviour to define explicite discriminator column in entity! I read that it is anit-pattern, not recommanded to add, and moreover to use such discriminator column in code...