MySQL/Java error - java

Newbie programmer here. Upon doing mvn tomcat:run I get the following error:
SEVERE: Servlet.service() for servlet appServlet threw exception
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 'values (?, ?)' at line 1
The code in question is as follows:
public void create(User user) {
this.jdbcTemplate.update("INSERT INTO xyz.user(user_name, user_password values (?, ?)");
user.getUserName(); user.getId();
}
public void delete(User user) {
this.jdbcTemplate.update("DELETE FROM xyz.user WHERE id = ?");
}
public void update(User user) {
this.jdbcTemplate.update(
"UPDATE xyz.user SET UserName = ? password = ? WHERE id = ?");
Googled - couldn't find a solution for (?, ?) scenarios. Pls. help - Thx in advance :)
Here's the complete code (almost) - I am doing something wrong but can't figure out what.
public User find(String login) {
System.out.println("Trying to find the user...." + login);
User user = this.jdbcTemplate.queryForObject(
"select * from xyz where user_name = ?",
new Object[]{login},
new RowMapper<User>() {
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User user = new User();
user.setId(Long.valueOf(rs.getInt(1)));
user.setUserName(rs.getString(2));
user.setPassword(rs.getString(3));
return user;
}
});
System.out.println("Found user..." + user);
return user;
}
public void create(User user) {
this.jdbcTemplate.update("INSERT INTO ibstechc_dev.user(user_name, user_password) VALUES (?,?)");
user.getUserName(); user.getId() ;
}
public void delete(User user) {
this.jdbcTemplate.update("DELETE FROM xyz WHERE id = ?");
// TODO Auto-generated method stub
}
public void update(User user) {
this.jdbcTemplate.update(
"UPDATE xyz SET user_name = ?, user_password = ? WHERE id = ?");
// TODO Auto-generated method stub
}
}
I am stuck with the same error - tomcat:run throws the following -
SEVERE: Servlet.service() for servlet appServlet threw exception
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 '?,?)' at line 1

Use this code:
this.jdbcTemplate.update("INSERT INTO xyz.user(user_name, user_password) values (?, ?)");
There was an issue with your SQL statement. To give you perspective you were trying to do:
INSERT INTO xyz.user(user_name, user_password values ('testuser','testpass'))
instead of
INSERT INTO xyz.user(user_name, user_password) values ('testuser','testpass'))
Hope this makes sense?

I think here is the sql syntax problem:
INSERT INTO xyz.user(user_name, user_password values (?, ?)
replace this by
INSERT INTO xyz.user(user_name, user_password) values (?, ?);

There is a sql syntax error in update
public void update(User user) {
this.jdbcTemplate.update(
"UPDATE xyz.user SET UserName = ? password = ? WHERE id = ?");
this is not the way to update,give a comma(,) like this
public void update(User user) {
this.jdbcTemplate.update(
"UPDATE xyz.user SET UserName = ? ,password = ? WHERE id = ?");

your error is this statement
this.jdbcTemplate.update("INSERT INTO xyz.user(user_name, user_password values (?, ?)");
It should be
this.jdbcTemplate.update("INSERT INTO xyz.user(user_name, user_password) values (?, ?)");
Hope it helps
Cheers

Try this:-
this.jdbcTemplate.update("INSERT INTO xyz.user(user_name, user_password) values (?, ?)");
instead of
this.jdbcTemplate.update("INSERT INTO xyz.user(user_name, user_password values (?, ?)");

Related

Why does the location of persist() affect the number of HQL requests?

Why does the flash() consider intermediate instructions after persist()? I'm talking about case case 2, where a separate update request was made for setName.
// 1
#Transactional
public void persist1(){
Post post = new Post();
post.setName("name1");
entityManager.persist(post);
}
// 2
#Transactional
public void persist2(){
Post post = new Post();
entityManager.persist(post);
post.setName("name2");
}
// 1
Hibernate: insert into post (name, id) values (?, ?)
// 2
Hibernate: insert into post (name, id) values (?, ?)
Hibernate: update post set name=? where id=?

How to read uncommitted data using jdbc?

I want to test how JDBC transactions work. Particularly, I want to see a read of uncommitted data. I've written one integration test in spring boot environment using a locally installed PostgreSQL database.
I'm trying to insert a row into a table, read it from one transaction, then update from another transaction without committing it, and read it again hoping it would change.
Table for the test (DDL):
create table users
(
id integer default nextval('user_id_sequence'::regclass) not null
constraint users_pkey
primary key,
first_name varchar(255) not null,
second_name varchar(255) not null,
email varchar(255)
);
alter table users
owner to postgres;
The test:
public void testHealthCheck() throws SQLException {
Connection zeroConnection = dataSource.getConnection();
Integer insertedUserId = insertUserSilently(zeroConnection, new User()
.setFirstName("John")
.setSecondName("Doe")
.setEmail("johndoe#gmail.com"));
zeroConnection.close();
Connection firstConnection = dataSource.getConnection();
firstConnection.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
firstConnection.setAutoCommit(false);
Connection secondConnection = dataSource.getConnection();
secondConnection.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
secondConnection.setAutoCommit(false);
List<User> users = getAllUsersSilently(firstConnection);
log.info("Got users: {}", silentToJsonString(users));
PersistenceUtils.updateUserEmailSilently(secondConnection, insertedUserId, "johndoe#yahoo.com");
users = getAllUsersSilently(firstConnection);
log.info("Got users: {}", silentToJsonString(users));
secondConnection.rollback();
secondConnection.close();
users = getAllUsersSilently(firstConnection);
log.info("Got users: {}", silentToJsonString(users));
firstConnection.close();
}
Utility class:
private static final String INSERT_USER_SQL = "insert into users(first_name, second_name, email) values (?, ?, ?)";
private static final String UPDATE_USER_SQL = "update users set email = ? where id = ?;";
private static final String SELECT_ALL_USERS_SQL = "select * from users";
public static List<User> extractUsersSilently(ResultSet resultSet) {
List<User> resultList = newArrayList();
try {
while (resultSet.next()) {
Integer id = resultSet.getInt(1);
String firstName = resultSet.getString(2);
String secondName = resultSet.getString(3);
String email = resultSet.getString(4);
resultList.add(new User(id, firstName, secondName, email));
}
} catch (SQLException e) {
log.error("Error while extracting result set", e);
return emptyList();
}
return resultList;
}
public static Integer insertUserSilently(Connection connection, User user) {
try {
PreparedStatement insertStatement = connection.prepareStatement(INSERT_USER_SQL, Statement.RETURN_GENERATED_KEYS);
insertStatement.setString(1, user.getFirstName());
insertStatement.setString(2, user.getSecondName());
insertStatement.setString(3, user.getEmail());
insertStatement.execute();
ResultSet resultSet = insertStatement.getGeneratedKeys();
resultSet.next();
return resultSet.getInt(1);
} catch (Exception exception) {
log.error(format("Exception while inserting user %s", user), exception);
return -1;
}
}
public static List<User> getAllUsersSilently(Connection connection) {
try {
PreparedStatement selectStatement = connection.prepareStatement(SELECT_ALL_USERS_SQL);
selectStatement.execute();
return extractUsersSilently(selectStatement.getResultSet());
} catch (Exception exception) {
log.error("Exception while getting all users", exception);
return Collections.emptyList();
}
}
public static void updateUserEmailSilently(Connection connection, Integer userId, String userEmail) {
try {
PreparedStatement updateStatement = connection.prepareStatement(UPDATE_USER_SQL);
updateStatement.setString(1, userEmail);
updateStatement.setInt(2, userId);
updateStatement.execute();
} catch (Exception exception) {
log.error(format("Exception while updating user %d", userId), exception);
}
}
}
Actual results are (you have to clear table manually before the test):
Got users:
[{"id":55,"firstName":"John","secondName":"Doe","email":"johndoe#gmail.com"}]
Got users:
[{"id":55,"firstName":"John","secondName":"Doe","email":"johndoe#gmail.com"}]
Got users:
[{"id":55,"firstName":"John","secondName":"Doe","email":"johndoe#gmail.com"}]
Although second read should've seen uncommitted change to email.
Cannot read uncommitted data in Postgres
See section 13.2. Transaction Isolation of the PostgreSQL documentation:
In PostgreSQL, you can request any of the four standard transaction isolation levels, but internally only three distinct isolation levels are implemented, i.e. PostgreSQL's Read Uncommitted mode behaves like Read Committed. This is because it is the only sensible way to map the standard isolation levels to PostgreSQL's multiversion concurrency control architecture.
This means that if you want to test TRANSACTION_READ_UNCOMMITTED, you need a DBMS other than PostgreSQL.

why spring jdbcTemplate batchUpdate insert row by row

I have 200K rows to be inserted in one single database table. I tried to use jdbcTemplate.batchUpdate in spring in order to do insertion 10,000 per batch. However, this process consumes too much time (7 mins for 200K rows). So on database side, I check the number of rows inserted by select count(*) from table_X. I found the number of rows increased slightly instead of 10K expected. Can anyone explain what's reason or is it something which should be configurated on Database side ?
PS: I am using sybase ....
There are lot of approaches available on the web.
Performance directly depends on the
Code you have written
JDBC driver you are using
database server and number of connection you are using
table indexes leads to slowness for insertion
Without looking at your code anyone can guess, but no one can find the exact solution.
Approach 1
//insert batch example
public void insertBatch(final List<Customer> customers){
String sql = "INSERT INTO CUSTOMER " +
"(CUST_ID, NAME, AGE) VALUES (?, ?, ?)";
getJdbcTemplate().batchUpdate(sql, new BatchPreparedStatementSetter() {
#Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
Customer customer = customers.get(i);
ps.setLong(1, customer.getCustId());
ps.setString(2, customer.getName());
ps.setInt(3, customer.getAge() );
}
#Override
public int getBatchSize() {
return customers.size();
}
});
}
reference
https://www.mkyong.com/spring/spring-jdbctemplate-batchupdate-example/
http://docs.spring.io/spring-framework/docs/3.0.0.M4/reference/html/ch12s04.html
Approach 2.1
//insert batch example
public void insertBatch(final List<Customer> customers){
String sql = "INSERT INTO CUSTOMER " +
"(CUST_ID, NAME, AGE) VALUES (?, ?, ?)";
List<Object[]> parameters = new ArrayList<Object[]>();
for (Customer cust : customers) {
parameters.add(new Object[] {cust.getCustId(),
cust.getName(), cust.getAge()}
);
}
getSimpleJdbcTemplate().batchUpdate(sql, parameters);
}
Alternatively, you can execute the SQL directly.
//insert batch example with SQL
public void insertBatchSQL(final String sql){
getJdbcTemplate().batchUpdate(new String[]{sql});
}
reference
https://www.mkyong.com/spring/spring-simplejdbctemplate-batchupdate-example/
Approach 2.2
public class JdbcActorDao implements ActorDao {
private SimpleJdbcTemplate simpleJdbcTemplate;
public void setDataSource(DataSource dataSource) {
this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
}
public int[] batchUpdate(final List<Actor> actors) {
SqlParameterSource[] batch = SqlParameterSourceUtils.createBatch(actors.toArray());
int[] updateCounts = simpleJdbcTemplate.batchUpdate(
"update t_actor set first_name = :firstName, last_name = :lastName where id = :id",
batch);
return updateCounts;
}
// ... additional methods
}
Approach 2.3
public class JdbcActorDao implements ActorDao {
private SimpleJdbcTemplate simpleJdbcTemplate;
public void setDataSource(DataSource dataSource) {
this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
}
public int[] batchUpdate(final List<Actor> actors) {
List<Object[]> batch = new ArrayList<Object[]>();
for (Actor actor : actors) {
Object[] values = new Object[] {
actor.getFirstName(),
actor.getLastName(),
actor.getId()};
batch.add(values);
}
int[] updateCounts = simpleJdbcTemplate.batchUpdate(
"update t_actor set first_name = ?, last_name = ? where id = ?",
batch);
return updateCounts;
}
// ... additional methods
}
Approach 3 :JDBC
dbConnection.setAutoCommit(false);//commit trasaction manually
String insertTableSQL = "INSERT INTO DBUSER"
+ "(USER_ID, USERNAME, CREATED_BY, CREATED_DATE) VALUES"
+ "(?,?,?,?)";
PreparedStatement = dbConnection.prepareStatement(insertTableSQL);
preparedStatement.setInt(1, 101);
preparedStatement.setString(2, "mkyong101");
preparedStatement.setString(3, "system");
preparedStatement.setTimestamp(4, getCurrentTimeStamp());
preparedStatement.addBatch();
preparedStatement.setInt(1, 102);
preparedStatement.setString(2, "mkyong102");
preparedStatement.setString(3, "system");
preparedStatement.setTimestamp(4, getCurrentTimeStamp());
preparedStatement.addBatch();
preparedStatement.executeBatch();
dbConnection.commit();
reference
https://www.mkyong.com/jdbc/jdbc-preparedstatement-example-batch-update/
/*Happy Coding*/
Try setting below for connection string - useServerPrepStmts=false&rewriteBatchedStatements=true. Have not tried but its from my bookmarks. You can search on these lines..
Connection c = DriverManager.getConnection("jdbc:<db>://host:<port>/db?useServerPrepStmts=false&rewriteBatchedStatements=true", "username", "password");
For us moving the code to a wrapper class and annotating the batch insert method with #Transactional did solve the problem.

Spring MVC + Hibernate executing a not coded update

I'm using Spring MVC with Hibernate but I've reached a weird situation, when my Service annotated with #Transational finishes it's execution it seems that hibernate is executing an extra update in my entity, an update that is not coded anywhere. Could someone help me?
My Controller:
#Controller
public class UserController {
#Resource(name="userService")
private UserService userService;
#RequestMapping(value="/user/create", method=RequestMethod.GET)
public ModelAndView createUser(User user) throws GenericException {
this.userService.doTestOnUpdateUser();
return new ModelAndView("createUser");
}
My Service:
#Service("userService")
public class UserServiceImpl implements UserService {
#Resource(name = "userDao")
private UserDao userDao;
#Override
#Transactional(rollbackFor = CauseTrasactionRollback.class)
public void doTestOnUpdateUser() {
try {
User user = this.userDao.findById(40l);
user.setFirstName("Rogerio1234");
user.setLastName("R123");
user.setEmail("rro#gmail.com");
user.setPassword("novo password");
this.userDao.save(user);
System.out.println("why ?");
} catch (DaoException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
My DAO:
#Repository("userDao")
public class UserDaoImpl extends CrudDaoImpl<User> implements UserDao {
#Autowired
public UserDaoImpl(SessionFactory sessionFactory) {
super(sessionFactory);
}
#Override
public void save(User user) throws DaoException {
try {
String sql = "";
User userBefore = null;
if (user.getId() == null) {
user.setCreated(new Date());
sql = "insert into users (first_name, last_name, email, password, created, last_updated, email_confirmed_at)"
+ "values (:firstName, :lastName, :email, md5(:password), :created, :lastUpdated, :emailConfirmedAt)";
} else {
userBefore = this.findById(user.getId());
user.setLastUpdated(new Date());
if (userBefore.getPassword() != user.getPassword()) {
sql = "update users set first_name=:firstName, last_name=:lastName, email=:email, "
+ " password=md5(:password), created=:created, last_updated=:lastUpdated, "
+ " email_confirmed_at=:emailConfirmedAt where id=:id";
} else {
sql = "update users set first_name=:firstName, last_name=:lastName, email=:email, "
+ "created=:created, last_updated=:lastUpdated, email_confirmed_at=:emailConfirmedAt where id=:id";
}
}
SQLQuery sqlQuery = this.sessionFactory.getCurrentSession()
.createSQLQuery(sql);
if (user.getId() != null) {
sqlQuery.setLong("id", user.getId());
if (userBefore.getPassword() != user.getPassword()) {
sqlQuery.setString("password", user.getPassword());
}
} else {
sqlQuery.setString("password", user.getPassword());
}
sqlQuery.setString("firstName", user.getFirstName());
sqlQuery.setString("lastName", user.getLastName());
sqlQuery.setString("email", user.getEmail());
sqlQuery.setDate("created", user.getCreated());
sqlQuery.setDate("lastUpdated", user.getLastUpdated());
sqlQuery.setDate("emailConfirmedAt", user.getEmailConfirmedAt());
sqlQuery.executeUpdate();
} catch (Exception e) {
throw new DaoException("Error at saving "
+ user.getClass().getSimpleName(), e);
}
}
}
Console log shows this:
Hibernate: select user0_.id as id8_, user0_.created as created8_, user0_.last_updated as last3_8_, user0_.email as email8_, user0_.email_confirmed_at as email5_8_, user0_.first_name as first6_8_, user0_.last_name as last7_8_, user0_.password as password8_ from users user0_ where user0_.id=?
Hibernate: update users set created=?, last_updated=?, email=?, email_confirmed_at=?, first_name=?, last_name=?, password=? where id=?
Hibernate: select user0_.id as id8_, user0_.created as created8_, user0_.last_updated as last3_8_, user0_.email as email8_, user0_.email_confirmed_at as email5_8_, user0_.first_name as first6_8_, user0_.last_name as last7_8_, user0_.password as password8_ from users user0_ where user0_.id=?
Hibernate: update users set first_name=?, last_name=?, email=?, created=?, last_updated=?, email_confirmed_at=? where id=?
why ?
Hibernate: update users set created=?, last_updated=?, email=?, email_confirmed_at=?, first_name=?, last_name=?, password=? where id=?
I'm not understanding why is executing this two updates that are not coded anywhere. The problem is that I'm using MD5 on postgres to encrypt the user's password, and I cannot let it update the password every time some other attribute gets updated, or else the password will be encrypted again, changing it, but right now those two updates not coded are setting the password in database without encrypting it to "novo password".
Any help will be appreciated.

Can PreparedStatementSetter will be used for Delete query in Spring

I am using Spring 3.1.2,am using PreparedStatementSetter for Select, update and insert, but how can I use for Delete query?
jdbcTemplate.update() can be used for delete's
e.g.
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
jdbcTemplate.update("delete from my_table where value=? ", new PreparedStatementSetter() {
public void setValues(PreparedStatement ps) throws SQLException {
ps.setLong(1, 2L);//or setString or whatever
}
});
you can also execute a delete without the PreparedStatementSetter as shown here: http://www.java2s.com/Code/Java/Spring/UseJdbcTemplateToExecuteDeleteStatementWithParameter.htm
You can use PreparedStatement for deletion like this
String sql = "DELETE FROM MY_TABLE WHERE ID = ?";
PreparedStatement ps = yourDBConnection.prepareStatement(sql);
ps.setInt(1, 1001);
// execute delete SQL stetement
ps.executeUpdate();

Categories