I'm trying to insert a row in Sql Server 2008 using JDBC Spring framework:
Here is the code:
BdClass bdclass= new BdClass(BdClass.BdConfig.ConnectionString_MYHOME);
Person personaNueva = new Person();
personaNueva.setIdPerson(5);
personaNueva.setUsuario("JavaUser");
personaNueva.setClave("JavaPassword");
personaNueva.setNombre("JavaNombreUsuario");
personaNueva.setActivo("S");
personaNueva.AddPerson(bdclass);
//Person class
public void AddPerson(BdClass bdclass)
{
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put(Constantes.idperson, this.getIdperson());
parameters.put(Constantes.usuario,this.getUsuario());
parameters.put(Constantes.clave,this.getClave());
parameters.put(Constantes.nombre,this.getNombre());
parameters.put(Constantes.activo, this.getActivo());
bdclass.Insert(parameters,Constantes.Table_Name);
}
//BdClass Insert
In this step I am enabling IDENTITY INSERT
public void Insert(Map<String, Object> parameters, String TableName)
{
this.jdbcTemplate.execute("SET IDENTITY_INSERT " + TableName + " ON");
JdbcInsert = new SimpleJdbcInsert(this.jdbcTemplate).withTableName(TableName);
JdbcInsert.execute(parameters);
}
When running the execute statement I am getting the following exception:
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: Cannot
insert explicit value for identity column in table 'Persons' when
IDENTITY_INSERT is set to OFF
I have already tried the command SET IDENTITY_INSERT PERSONS ON in sql management studio with no luck.
EDIT: idperson field is identity, but it doesn't matter if I pass the parameter and value or not... I'm getting the same error
EDIT 2:
Ok, I fixed it by using the usingColumns Property, So I can specify every column:
public void Insert(Map<String, Object> parameters, String TableName)
{
this.jdbcTemplate.execute("SET IDENTITY_INSERT " + TableName + " OFF");
JdbcInsert = new SimpleJdbcInsert(this.jdbcTemplate).withTableName(TableName)
.usingColumns(Person.Constantes.usuario,Person.Constantes.clave,
Person.Constantes.nombre,Person.Constantes.activo);
JdbcInsert.execute(parameters);
}
SQL Server's SET IDENTITY is session scoped. That means you must execute the command SET IDENTITY_INSERT " + TableName + " ON" under the same transaction you are using to insert your data.
Spring JDBC Template opens a new connection for each statement, and thats why you are not being able to set it under the same session.
//connection opened --> statement executed --> connection closed
this.jdbcTemplate.execute("SET IDENTITY_INSERT " + TableName + " ON");
I think the best approach is not to the IDENTITY_INSERT ON and do the following:
public void Insert(Map<String, Object> parameters, String TableName)
{
JdbcInsert = new SimpleJdbcInsert(this.jdbcTemplate).withTableName(TableName);
//This column won't be included on the insert statement (it will be autogenerated by SQL Server)
JdbcInsert.setGeneratedKeyName("id");
JdbcInsert.execute(parameters);
}
Another alternative is to execute both statements under the same transaction, but I don't think you could use SimpleJdbcInsert for that.
Related
I'm trying to add designation and its salary using a JDBC transaction.
The problem is this throws an exception about duplicate key.
This is the first time I put some invalid data in salary columns and after that everything is correct. It shows duplicate key exception for designation id
but the designation id is not stored already and not even for first attempt.
The first transaction that is invalid is rolled back, but storing on next time it shows duplicate key exception.
Below is my code:-
public boolean addDesignation(ObservableList nodeList) throws SQLException {
Connection demo = getConnection();
demo.setAutoCommit(false);
Savepoint savePoint = demo.setSavepoint("savePoint");
try {
PreparedStatement addDesig = demo.prepareStatement(
"INSERT INTO `designation`(`desig_id`,`dept_id`,`desig_name`,`desig_desc`) VALUES (?,?,?,?)");
PreparedStatement addSal = demo.prepareStatement("INSERT INTO `salary` "
+ "(`desig_id`, `basic`, `house_rent`, `conveyance`, `medical`, `dearness`,`others_allowances`,"
+ " `income_tax`, `pro_tax`, `emp_state_insu`, `absence_fine`, `others_deductions`, `month`)"
+ " VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)");
addDesig.setString(1 , nodeList.get(0).toString());
addDesig.setString(2, nodeList.get(1).toString());
addDesig.setString(3, nodeList.get(2).toString());
addDesig.setString(4, nodeList.get(3).toString());
addDesig.executeUpdate();
addSal.setString(1, nodeList.get(0).toString());
addSal.setInt(2, Integer.parseInt(nodeList.get(4).toString()));
addSal.setInt(3, Integer.parseInt(nodeList.get(5).toString()));
addSal.setInt(4, Integer.parseInt(nodeList.get(6).toString()));
addSal.setInt(5, Integer.parseInt(nodeList.get(7).toString()));
addSal.setInt(6,Integer.parseInt(nodeList.get(8).toString()));
addSal.setInt(7,Integer.parseInt(nodeList.get(9).toString()));
addSal.setInt(8, Integer.parseInt(nodeList.get(10).toString()));
addSal.setInt(9, Integer.parseInt(nodeList.get(11).toString()));
addSal.setInt(10, Integer.parseInt(nodeList.get(12).toString()));
addSal.setInt(11, Integer.parseInt(nodeList.get(13).toString()));
addSal.setInt(12, Integer.parseInt(nodeList.get(14).toString()));
addSal.setString(13, nodeList.get(15).toString());
addSal.executeUpdate();
demo.commit();
return true;
} catch (SQLException ex) {
demo.rollback(savePoint);
Logger.getLogger(DatabaseHandler.class.getName()).log(Level.SEVERE, null, ex);
}
return false;
}
these are two tables and im trying to add that data in my first attempt failed but not store due roll back
There are 2 INSERT statements in your code.
The 1st for designation table:
"INSERT INTO `designation`(`desig_id`,`dept_id`,`desig_name`,`desig_desc`) VALUES (?,?,?,?)"
here it looks like desig_id is the primary key (maybe autoincrement in which case you must not supply a value at all).
Are you sure the value that you supply for this column does not already exist in the table?
The 2nd for the salary table:
"INSERT INTO `salary` " + "(`desig_id`, `basic`, `house_rent`, `conveyance`, `medical`, `dearness`,`others_allowances`," + " `income_tax`, `pro_tax`, `emp_state_insu`, `absence_fine`, `others_deductions`, `month`)" + " VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)"
in this case it is not clear since you did not post the CREATE statement of the table, which is the primary key.
So you have to check, if the value (or values if it's a multi column key), violate the uniqueness of the key.
I am trying to make a simple program to fetch data from a table.
I am following http://www.avaje.org/ebean/getstarted_props.html#iud but am unable to get data. I have created new Entity Class from Database from Netbeans (which creates classes from relations). Here is what I am using:
ebean.properties
ebean.ddl.generate=true
ebean.ddl.run=true
ebean.debug.sql=true
ebean.debug.lazyload=false
ebean.logging=all
ebean.logging.logfilesharing=all
ebean.logging.directory=D:\\logs
ebean.logging.iud=sql
ebean.logging.query=sql
ebean.logging.sqlquery=sql
ebean.logging.txnCommit=none
datasource.default=h2
datasource.h2.username=sa
datasource.h2.password=
datasource.h2.databaseUrl=jdbc:h2:mem:tests;DB_CLOSE_DELAY=-1
datasource.h2.databaseDriver=org.h2.Driver
datasource.h2.minConnections=1
datasource.h2.maxConnections=25
datasource.h2.heartbeatsql=select 1
datasource.h2.isolationlevel=read_committed
datasource.mysql.username=root
datasource.mysql.password=kalsym#123
datasource.mysql.databaseUrl=jdbc:mysql://127.0.0.1:3306/wsp
datasource.mysql.databaseDriver=com.mysql.jdbc.Driver
datasource.mysql.minConnections=1
datasource.mysql.maxConnections=25
datasource.mysql.isolationlevel=read_committed
Table Data
Insert into routing_algo_type (name, description) values ('LCR', 'Least Cost Routing');
Code to fetch data
RoutingAlgoType routingObj = new RoutingAlgoType();
routingObj.setName("LCR");
RoutingAlgoType routingObj2 = Ebean.find(RoutingAlgoType.class, routingObj);
System.out.println("Got "+routingObj2.getDescription());
Now find returns null, which means it cant find the data?
I used following code to test connection
String sql = "select count(*) as count from dual";
SqlRow row = Ebean.createSqlQuery(sql).findUnique();
Integer i = row.getInteger("count");
System.out.println("Got " + i + " - DataSource good.");
Result from above code is
Got 1 - DataSource good.
Is there any way to check the connection?
I am trying to write this query in order to authenticate the username and password of my API but I am getting error column not found. Both username and passwords are strings and I am using MYSQL database. I think there is a error with quotations as username and password are strings. How can I rectify the below code or is there a better way to write the same.
P.S - I am using spring MVC and this is my first project.
#Override
public TypeInfo getRole(final TypeInfo typeinfo) {
String sql =
"select Role from registartion where UserName=\"" + typeinfo.getUserName() + "and Password=\"" + typeinfo.getPassword() + "/"";
return jdbcTemplate.query(sql, new ResultSetExtractor<TypeInfo>() {
#Override
public TypeInfo extractData(ResultSet rs)
throws SQLException, DataAccessException {
if (rs.next()) {
System.out.println("VALID USER");
TypeInfo typeinfo1 = new TypeInfo();
typeinfo1.setUserName(typeinfo.getUserName());
typeinfo1.setPassword(typeinfo.getPassword());
typeinfo1.setRole(rs.getString("Role"));
return typeinfo1;
}
System.out.println("Not A valid user");
return null;
}
});
}
I am getting a error that "select Role from registartion where UserName=******" column name ******* not found.
That's not the way you should write your query.
JdbcTemplate uses an Object[] array as parameters, to avoid SQL injection.
code it somewhere in the lines of this:
String user = "yourUser";
String password = "yourPassword";
final String sql = "SELECT * from FOO where username = ? and password = ?";
Object[] sqlParameters = new Object[]{user, password};
List<YourEntityClass> list = getJdbcTemplate.query(sql, new BeanPropertyRowMapper<Your Entity Class>(YourEntityClass.class), sqlParameters);
BeanPropertyRowMapper actually maps the values for you. just make sure your entity class has the same property names as the ones on your database
more info here:
jdbcTemplate examples
The proper solution would be to use a PreparedStatement, in order to avoid having to mess with quoting and enhance security.
If you really must construct the statement by string concatination, you should note that string literals in SQL are denoted by single quotes ('), not double quotes ("):
String sql =
"select Role from registartion where UserName='" + typeinfo.getUserName() + "' and Password='" + typeinfo.getPassword() + '";
Try this.
String sql = "select Role from registartion where UserName='" + typeinfo.getUserName() + "' and Password='" + typeinfo.getPassword() + "'";
Change the double quotes (including the escape characters) to single quotes.
Close the single quote enclosing the user name (typeinfo.getUserName()). You need to keep a space between the closing single quote and the subsequent string.
If it still does not work then check the table names and column names. Maybe it is 'registration' and not 'registartion'? Or may be it is 'user_name' and not 'username'?
Tips for beginners: Copy paste the sql string into any database browser, replace the variables with actual values and execute. Check for any errors. It is easier to fix errors this way.
And lastly, use parameterized sql queries to avoid sql injection. In my opinion parameterized queries reduces syntax errors too.
You have to use single qoutes around the column values:
"select Role from registartion where UserName='" + typeinfo.getUserName() + "' and Password='" + typeinfo.getPassword() + "'";
You should better use PreparedStatement. It is easier to read and safer (prevents sql injection).
I'm having an sql problem. I writing a java application on top of a Access database.
It's a search query for several fields and I know the error is in the part where I need to calculate the age of a person when he or she went missing. I'm returning a tablemodel in my method so i need to do the calculations in my query. My latest atempt to make it work is this:
public TableModel UpdateTable(String dossiernr, String naam, String voornaam,
String startleeftijd, String eindleeftijd, String dossierjaar, String geslacht)
{
TableModel tb = null;
String sql= "SELECT [Nr dossier],[Annee],[Nom],[Prenom],[Disparu le],[Ne le],[Sexe], DATEDIFF('yyyy',[Ne le],[Disparu le]) - iif(DATEADD('yyyy', DATEDIFF('yyyy',[Ne le],[Disparu le]),"
+ "[Ne le])>[Disparu le],1,0) AS Age FROM TotalTable "
+ "WHERE [Nr dossier] LIKE ? AND [Nom] LIKE ? AND [Prenom] LIKE ? AND [Annee] LIKE ? AND Age >= ? AND Age <= ? AND [Sexe] LIKE ?;";
try
{
PreparedStatement pstatement;
Connection connection = PersistentieController.getInstance().getConnection();
pstatement = initStatement(connection,sql);
pstatement.setString(1, "%" + dossiernr + "%");
pstatement.setString(2, "%" + naam + "%");
pstatement.setString(3, "%" + voornaam + "%");
pstatement.setString(4, "%" + dossierjaar + "%");
pstatement.setString(5, startleeftijd);
pstatement.setString(6, eindleeftijd);
pstatement.setString(7, "%" + geslacht + "%");
rs=pstatement.executeQuery();
tb = DbUtils.resultSetToTableModel(rs);
pstatement.close();
}//einde try
catch (SQLException e)
{
e.printStackTrace();
} //einde catch
return tb;
}
When i run it, i get following error:
java.sql.SQLException: [Microsoft][ODBC Microsoft Access Driver] Too few parameters. Expected 8.
I only work with 7 parameters and don't get why he's asking for 8.
Thanks
You count 7 parameters in your WHERE clause. Unfortunately, the Access db engine treats Age as another parameter in that situation, so it thinks you have 8 parameters instead of only 7.
To understand why, start with this query which runs without error with my Access database:
SELECT some_text AS foo
FROM tblFoo
WHERE some_text Is Not Null;
However, when attempting to use the alias instead of the field name in the WHERE clause, Access prompts me to supply a value for foo because it treats it as a parameter:
SELECT some_text AS foo
FROM tblFoo
WHERE foo Is Not Null;
Access limits your ability to re-use alias names later in a query. In certain cases, it will accept the alias, but yours is not one of those cases.
You could define the alias in a subquery. Then the db engine will recognize it correctly when you reference the subquery's alias in the parent query.
If possible, test your SQL statements directly in Access. If they fail, that effort will give you the best chance to determine why.
I tried to execute the following oracle query using JdbcTemplate in Java:
select RESOURCE_ID
from REPRO_PRINTING_JOB
where (USER_ID=? and PRINTING_CENTER_ID=?)
group by RESOURCE_ID
union all
select RESOURCE_ID
from REPRO_PRINTING_JOB_OLD
where (USER_ID=? and PRINTING_CENTER_ID=? and STATE='CM')
group by RESOURCE_ID
The query is working perfectly in oracle query browser but its not working during the execution in java. What could be the source of this problem? I´ve heard something about Jdbc cannot handle case sensitive. Is this true?
ADDED JAVA CODE(CORRECTED) :
I call the query using getStatement() which retrieves the query from external source(a properties file) as belows :
public List<PrintingJob> getPrintingJobsByCreatedUserId(String createdUserId, String userId) {
if(log.isDebugEnabled()) {
log.debug("getReportItemsByUserId(" + createdUserId + "," + userId + ")");
}
try {
System.out.println("getPrintingJobsByResourceId : createdUserId :"+createdUserId+",userId : "+userId);
return getJdbcTemplate().query(getStatement("gen.report.userid"),
new Object[]{createdUserId, userId, createdUserId, userId},
new PrintingJobMapper());
} catch (DataAccessException ex) {
log.error("Error executing query: " + ex.getClass() + ":" + ex.getMessage());
return null;
}
}
The reason you are getting this error is because it is an error from the JDBC driver or java.sql API, not from the database. Note the lack of ORA-XXXXX in the exception message. If it contained that, then it would be related to syntax, invalid name or something that would go wrong on the database server side.
SQLExceptions are thrown in java for anything related to the SQL api, not just from errors that occur when statements are sent over the connection... In this case, it is likely that the query in fact ran correctly but the result set API is giving you errors (rs.getLong("blah"), where column "blah" doesn't exist in your select) is causing problems.