I'm trying to use ResultSetExtractor to send a SQL statement to the database, but the method is getting stuck at the line l.setId(resultSet.getInt("Id"));.
This is my error message:
"message": "PreparedStatementCallback; uncategorized SQLException for
SQL [SELECT Cities.Name FROM cities INNER JOIN Notes on Cities.Id = Notes.CitiesId WHERE Notes.CitiesId = ? AND Notes.id = ?]; SQL state [S0022]; error code [0]; Column 'Id' not
found.; nested exception is java.sql.SQLException: Column 'Id' not
found.",
The Cities table has 3 columns named Id, Name, and Code. I checked my SQL statement in Workbench and it is correct. What's wrong with my code?
public List<Cities> GetCity(String CityId, String NoteId) {
final String sql = "SELECT Cities.Name FROM cities INNER JOIN Notes on Cities.Id = Notes.CitiesId WHERE Notes.CitiesId = ? AND Notes.id = ?";
final List<Cities> cityList = jdbcTemplate.query(sql, new ResultSetExtractor<List<Cities>>() {
#Override
public List<Cities> extractData(ResultSet resultSet) throws SQLException, DataAccessException {
List<Cities> list = new ArrayList<Cities>();
while (resultSet.next()) {
Cities l = new Cities();
l.setId(resultSet.getInt("Id"));
l.setName(resultSet.getString("Name"));
l.setCode(resultSet.getString("Code"));
list.add(l);
}
System.out.println(list);
return list;
}
}, CityId, NoteId);
return cityList;
}
Related
I am trying to run a SQL Server 2014 stored procedure from Java (Spring) code and get some xml results.
When I run this in a SQL client e.g. RazorSQL I get a bunch of xmls (which is expected because the there are multiple stored procedures within it, that returns those xml).
Here is the Exec call from my SQL client:
EXEC [dbo].[sp_GetType]
#TRAN_ID = 42
#QUAL_ID = 0
GetType does a RETURN 0 at the end (so basically if all steps succeed, it returns 0)
This opens multiple tabs in my client with the xmls.
And one example stored procedure within GetType has these lines:
SELECT TOP 1 ModifiedBy = CASE WHEN #IS_ID = 1 FROM TABLE23.dbo.TRX
TrxId WITH (NOLOCK) WHERE #DD_ID = #TRAN_ID
FOR XML AUTO, ELEMENTS
My goal is to capture all the xmls returned by GetType into a List of objects.
Here is my dao:
private final JdbcTemplate jdbcTemplate;
#Autowired
public TransactionDao(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
#Transactional(readOnly = true)
public List<Object> getTransaction(Integer tranId, Integer qualId) {
Object dt = new Object();
List<Object> resultList = (List<Object>) jdbcTemplate.execute(
new CallableStatementCreator() {
public CallableStatement createCallableStatement(Connection con) throws SQLException {
String storedProc = "{call sp_GetType(?,?)}";
CallableStatement cs = con.prepareCall(storedProc);
cs.setInt(1, tranId);
cs.setInt(2, qualId);
return cs;
}
}, new CallableStatementCallback() {
public Object doInCallableStatement(CallableStatement > cs) throws SQLException,
DataAccessException {
List<Object> results = new ArrayList<Object>();
cs.execute();
if(cs.getMoreResults())
{
ResultSet rs = cs.getResultSet();
while(rs.next()) //rs has only one record
{
InputStream in = null;
Clob clob = rs.getClob(1);
in = clob.getAsciiStream();
}
rs.close();
}
return results;
}
});
return resultList;
}
I'm using the jtds 1.3.1 driver (I tried connecting using mssql-jdbc but no luck).
Any help is much appreciated.
Using the following code to get the list of data from table but getting invalid column error.
String sql = "select * from employees WHERE emp_status = :statusCode";
Map parameters = new HashMap();
parameters.put("statusCode", "Active");
MapSqlParameterSource parametersSourceMap = new MapSqlParameterSource(parameters );
List<Employee> employees rowSet = jdbcTemplate.queryForList(sql, parametersSourceMap);
Exception
Exception in thread "main" org.springframework.jdbc.UncategorizedSQLException: PreparedStatementCallback; uncategorized SQLException for SQL [select * from employees WHERE emp_status = :statusCode SQL state [null]; error code [17004]; Invalid column type; nested exception is java.sql.SQLException: Invalid column type
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:83)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:603)
at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:812)
at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:868)
at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:876)
at com.spring.EmployeeDAOImpl.addEmployee(EmployeeDAOImpl.java:46)
at com.spring.MainApp.main(MainApp.java:33)
Caused by: java.sql.SQLException: Invalid column type
Table have column as Varchar2
Anyone have idea why we can't get data based on String column?
I recently faced the same issue. In my case, I was using JdbcTemplate instead of NamedParameterJdbcTemplate. I am not sure if the issue is same for you.
You can define a bean of type NamedParameterJdbcTemplate and then autowire it in your repository class.
Configuration class :
#Bean
public NamedParameterJdbcTemplate yourNamedParameterJdbcTemplate(DataSource yourDataSource) {
return new NamedParameterJdbcTemplate(yourDataSource);
}
Repository class :
#Repository
public class YourRepositoryImpl implements YourRepository {
#Autowired
NamedParameterJdbcTemplate jdbcTemplate;
Try to pass parameters like this :
String sql = "SELECT * FROM employees WHERE emp_status = ?";
List<Employee> employees = jdbcTemplate.queryForList(
sql,
new Object[]{"Active"},
new BeanPropertyRowMapper<Employee>(Employee.class)
);
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.
New to Java and MySQL.
Am using a DAO object to query a table, running via Eclipse. MySQL edited via Workbench. table exists and Getting the following exceptions:
SELECT movie_name, release_dd, release_mm, release_yyyy, duration, language, director, genre, actor_1, actor_2 FROM movie_details_table WHERE movie_name = 'Piku'
java.sql.SQLException: Before start of result set
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:998)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:937)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:926)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:872)
at com.mysql.jdbc.ResultSetImpl.checkRowPos(ResultSetImpl.java:787)
at com.mysql.jdbc.ResultSetImpl.getStringInternal(ResultSetImpl.java:5244)
at com.mysql.jdbc.ResultSetImpl.getString(ResultSetImpl.java:5167)
at com.mysql.jdbc.ResultSetImpl.getString(ResultSetImpl.java:5206)
at com.library.model.MovieDAO.getMovieDetails(MovieDAO.java:41)
at com.library.model.MovieDetTest.main(MovieDetTest.java:18)
MovieDAO class:
package com.library.model;
import java.util.*;
import java.sql.*;
import java.io.*;
import com.library.model.beans.*;
public class MovieDAO {
private static final String DB_URL =
"jdbc:mysql://localhost/planner";
// Database credentials
private static final String USER = "Sudipto";
private static final String PASS = "sudi85";
public MovieDetails getMovieDetails(String inputMov) throws
SQLException {
MovieDetails movieDetails = new MovieDetails();
try {
//Open a connection
Connection conn = DriverManager.getConnection
(DB_URL,USER,PASS);
//Create and execute query
String queryString = "SELECT movie_name, release_dd, release_mm, release_yyyy, duration, language, director, genre, actor_1, actor_2 FROM movie_details_table WHERE movie_name = '" + inputMov + "'";
System.out.println(queryString);
PreparedStatement statement = conn.prepareStatement
(queryString);
ResultSet rsMovieDetails = statement.executeQuery();
movieDetails.setMovieName(rsMovieDetails.getString
("movie_name"));
movieDetails.setReleaseDate
(rsMovieDetails.getInt ("release_dd"), rsMovieDetails.getInt ("release_mm"), rsMovieDetails.getInt ("release_yyyy"));
movieDetails.setDuration(rsMovieDetails.getInt
("duration"));
movieDetails.setLanguage(rsMovieDetails.getString
("language"));
movieDetails.setDirector(rsMovieDetails.getString
("director"));
movieDetails.setGenre(rsMovieDetails.getString
("genre"));
movieDetails.setActor1(rsMovieDetails.getString
("actor_1"));
movieDetails.setActor2(rsMovieDetails.getString
("actor_2"));
}
catch (SQLException e) {
e.printStackTrace();
}
return movieDetails;
}
}
Have the following error log in MySQL workbench:
2015-05-31T15:04:36, 27, Note, Aborted connection 27 to db: 'planner' user: 'Sudipto' host: 'localhost' (Got an error reading communication packets)
Can anyone please suggest how and what I need to fix?
Use rsMovieDetails.next() to retrive details. Like rs.next() is used in https://docs.oracle.com/javase/tutorial/jdbc/basics/retrieving.html.
rs.next() shifts the cursor to the next row of the result set from the database and returns true if there is any row, otherwise returns false. If row is present then u should retrieve the data
I am having trouble getting data from a database I know exists and I know the format of.
In the code snippet below the "if conn != null" is just a test to verify the database name, table name, etc are all correct, and they DO verify.
The last line below is what generates the exception
public static HashMap<Integer, String> getNetworkMapFromRemote(DSLContext dslRemote, Connection conn, Logger logger) {
HashMap<Integer,String> remoteMap = new HashMap<Integer, String>();
// conn is only used for test purposes
if (conn != null) {
// test to be sure database is ok
try
{
ResultSet rs = conn.createStatement().executeQuery("SELECT networkid, name FROM network");
while (rs.next()) {
System.out.println("TEST: nwid " + rs.getString(1) + " name " + rs.getString(2));
}
rs.close();
}
catch ( SQLException se )
{
logger.trace("getNetworksForDevices SqlException: " + se.toString());
}
}
// ----------- JOOQ problem section ------------------------
Network nR = Network.NETWORK.as("network");
// THE FOLLOWING LINE GENERATES THE UNKNOWN TABLE
Result<Record2<Integer, String>> result = dslRemote.select( nR.NETWORKID, nR.NAME ).fetch();
This is the output
TEST: nwid 1 name Network 1
org.jooq.exception.DataAccessException: SQL [select `network`.`NetworkId`, `network`.`Name` from dual]; Unknown table 'network' in field list
at org.jooq.impl.Utils.translate(Utils.java:1288)
at org.jooq.impl.DefaultExecuteContext.sqlException(DefaultExecuteContext.java:495)
at org.jooq.impl.AbstractQuery.execute(AbstractQuery.java:327)
at org.jooq.impl.AbstractResultQuery.fetch(AbstractResultQuery.java:330)
at org.jooq.impl.SelectImpl.fetch(SelectImpl.java:2256)
at com.nvi.kpiserver.remote.KpiCollectorUtil.getNetworkMapFromRemote(KpiCollectorUtil.java:328)
at com.nvi.kpiserver.remote.KpiCollectorUtilTest.testUpdateKpiNetworksForRemoteIntravue(KpiCollectorUtilTest.java:61)
.................
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown table 'network' in field list
.................
For the sake of completness here is part of the JOOQ generated class file for Network
package com.wbcnvi.intravue.generated.tables;
#javax.annotation.Generated(value = { "http://www.jooq.org", "3.3.1" },
comments = "This class is generated by jOOQ")
#java.lang.SuppressWarnings({ "all", "unchecked", "rawtypes" })
public class Network extends org.jooq.impl.TableImpl<com.wbcnvi.intravue.generated.tables.records.NetworkRecord> {
private static final long serialVersionUID = 1729023198;
public static final com.wbcnvi.intravue.generated.tables.Network NETWORK = new com.wbcnvi.intravue.generated.tables.Network();
#Override
public java.lang.Class<com.wbcnvi.intravue.generated.tables.records.NetworkRecord> getRecordType() {
return com.wbcnvi.intravue.generated.tables.records.NetworkRecord.class;
}
public final org.jooq.TableField<com.wbcnvi.intravue.generated.tables.records.NetworkRecord, java.lang.Integer> NWID = createField("NwId", org.jooq.impl.SQLDataType.INTEGER.nullable(false), this, "");
public final org.jooq.TableField<com.wbcnvi.intravue.generated.tables.records.NetworkRecord, java.lang.Integer> NETWORKID = createField("NetworkId", org.jooq.impl.SQLDataType.INTEGER.nullable(false).defaulted(true), this, "");
public final org.jooq.TableField<com.wbcnvi.intravue.generated.tables.records.NetworkRecord, java.lang.String> NAME = createField("Name", org.jooq.impl.SQLDataType.CHAR.length(40).nullable(false).defaulted(true), this, "");
public final org.jooq.TableField<com.wbcnvi.intravue.generated.tables.records.NetworkRecord, java.lang.Integer> USECOUNT = createField("UseCount", org.jooq.impl.SQLDataType.INTEGER.nullable(false).defaulted(true), this, "");
public final org.jooq.TableField<com.wbcnvi.intravue.generated.tables.records.NetworkRecord, java.lang.Integer> NETGROUP = createField("NetGroup", org.jooq.impl.SQLDataType.INTEGER.nullable(false).defaulted(true), this, "");
public final org.jooq.TableField<com.wbcnvi.intravue.generated.tables.records.NetworkRecord, java.lang.String> AGENT = createField("Agent", org.jooq.impl.SQLDataType.CHAR.length(16), this, "");
public Network() {
this("network", null);
}
public Network(java.lang.String alias) {
this(alias, com.wbcnvi.intravue.generated.tables.Network.NETWORK);
}
..........
Based on the "unknown table" exception I thought there was a problem connected to the wrong database or wrong server, but the console output is correct for a JDBC query.
Any thoughts are appreciated, perhaps something else can be the root cause or the DSLContext is not valid (but I would think that would generate a different exception).
The answer ends up being simple, I did not include the .from() method
Result<Record2<Integer, String>> result = dslRemote.select( nR.NETWORKID, nR.NAME )
.from(nR)
.fetch();
That is why the table was unknown, I never put the from method in.