How can I insert a "null" timestamp with Spring JDBC Framework into a DB2 database - spring

I created a Java web application, in which I use the Spring JDBC Framework, in order to write my queries for the DB2 database. So far all the queries are working excellent.
I tried today to create an INSERT query for a table I have in my database. The query is really straight forword, it works as DB2 query and it looks like this:
INSERT INTO MYDB.USERSUBSCRIPTION (USERNAME, SUBSCRIPTIONDATETIME, UNSUBSCRIPTIONDATETIME)
VALUES('JamesTheBoss', '2017-07-07 07:07:07.007', null);
In my Java class I created the following methods:
private Timestamp getCurrentDateTimeInTimeStamp() {
LocalDateTime currentDateAndTime = LocalDateTime.now();
currentDateAndTime.format(DateTimeFormatter.ofPattern("yyy-MM-dd HH:MM:SS.mm")).replaceAll("T", " ");
Timestamp timestamp = Timestamp.valueOf(currentDateAndTime);
return timestamp;
}
public void insertNewUserToDatabase(String username){
Timestamp timestamp = getCurrentDateTimeInTimeStamp();
String SQL = "INSERT INTO MYDB.USERSUBSCRIPTION (USERNAME, SUBSCRIPTIONDATETIME, UNSUBSCRIPTIONDATETIME) " +
"VALUES(?, ?, ?)";
this.jdbcTemplateObject = new JdbcTemplate(dataSource);
jdbcTemplateObject.update(SQL,new Object[] { username, timestamp, null});
}
My first query was the following:
public List<UserSubscription> getAllUserSubscriptions() throws SQLException {
String SQL = "SELECT * FROM MYDB.USERSUBSCRIPTION";
this.jdbcTemplateObject = new JdbcTemplate(dataSource);
List<UserSubscription> userSubscription = jdbcTemplateObject.query(SQL, new UserSubscriptionMapper());
return userSubscription;
}
and it works fine, as all other queries I wrote also do.
When I try to insert "null" as a Timestamp Parameter in the query, I become an exception.
How can I insert a "null" value for a Timestamp by using the Spring JDBC Framework?
I would really appreciate having a feedback.

I have been debbuging for a while and I found out that I can hardcode a null in my query and then the query works fine.
With a hardcoded "null" the query looks like this:
public void insertNewUserToDatabase(String username){
Timestamp timestamp = getCurrentDateTimeInTimeStamp();
String SQL = "INSERT INTO MYDB.USERSUBSCRIPTION (USERNAME, SUBSCRIPTIONDATETIME, UNSUBSCRIPTIONDATETIME) " +
"VALUES(?, ?, null)"; // <--- Hard Coded "null"
this.jdbcTemplateObject = new JdbcTemplate(dataSource);
jdbcTemplateObject.update(SQL,new Object[] { username, timestamp});
}
When this query is executed, I become a new record in DB2 Database with a "null" value for column "UNSUBSCRIPTIONDATETIME".

Related

NamedParameterJdbcTemplate cannot execute insert into select

I'm using informix and I'm trying to execute a simple query from java using spring. This is the query.
INSERT INTO table1
SELECT val1, val2, val3
FROM table2
WHERE condition
I've verified the query syntax and if execute it using a client, runs perfectly. But when it runs using NamedParameterJdbcTemplate throws syntax error and I don't know why. Somebody could explain me the reasons and a good way to solve my problem.
This is my java code.
String LOG_INFO =
"INSERT INTO table1 SELECT val1, val2, (SYSDATE - 5 UNITS HOUR), val3 " +
" FROM table2 " +
" WHERE membership_nbr = :user_nbr_param";
String USER_NBR_PARAM = "user_nbr_param";
#Autowired
private NamedParameterJdbcTemplate jdbcTemplate;
public Integer logInfo(BigInteger userNbr) {
MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue(USER_NBR_PARAM, userNbr);
return jdbcTemplate.update(LOG_INFO, params);
}
Try this by taking Map instead of MapSqlParameterSource :
public Integer logInfo(BigInteger userNbr) {
Map<String, Object> params = new HashMap<>();
params.put(USER_NBR_PARAM, userNbr);
return jdbcTemplate.update(LOG_INFO, params);
}
Read this : why we use MapSqlParameterSource for more info.

how do I get spring to recognize the first capital letter using postgresql

I have a question how I can do so that in spring my table is recognized with the first capital letter, is made in postgresql
#Entity
#Table(name="System_user")
public class Dashboard {
#Id
#Column(name = "username")
String username;
get..
set...
}
it generates an error and I change it as shown below
#Table("\"System_user\"")
but he still doesn't recognize me
As we discussed in the comments, the issue was in dialect.
Latest dialect for now - org.hibernate.dialect.PostgreSQL95Dialect
The issue solved this dialect:
<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
Answer to your HQL-code:
I would suggest using TypedQuery as it returns not just a list, but list of your object.
Furthermore, u are using the same session to transfer data. This is bad for the program. Always do like Open session - transfer data - close session.
Try this code:
public List<Vw_dh_assay> listAssayReport(double year, String project_id, String hole_id) {
List<Vw_dh_assay> list = new ArrayList<>();
Session session;
try {
session = this.sessionFactory.openSeesion();
TypedQuery<Vw_dh_assay> query = session.createQuery("from Vw_dh_assay where year = :year AND project_id = :project_id AND hole_id = :hole_id", Player.class);
query.setParameter("year", year);
query.setParameter("project_id", project_id);
query.setParameter("hole_id", hole_id);
list = query.getResultList();
System.out.println(list);
session.clear();
session.close();
} catch (Exception e) {
e.printStackTrace();
}
return list;
}
this is my code DAO #Antonio112009
#Override
public List<Vw_dh_assay> listAssayReport(double year, String project_id, String hole_id) {
Session session = this.sessionFactory.getCurrentSession();
String query = ("SELECT DISTINCT year,project_id,hole_id from "
+ "Vw_dh_assay where year = :year AND project_id = :project_id AND hole_id = :hole_id");
List result = session.createQuery(query).setParameter("year", year).setParameter("project_id", project_id)
.setParameter("hole_id", hole_id).list();
System.out.println(result);
return result;
}

Insert byte[] into blob field with spring's jdbcTemplate and stored procedure

I'm try to insert byte[] into blob field with stored procedure, and get an Exception :
Request processing failed; nested exception is org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [SELECT ID FROM sp_NEWFILE(?,?,?)]; nested exception is org.firebirdsql.jdbc.field.TypeConversionException: Error converting to object.
Model:
public class fileBody {
private int ID;
private byte[] BODY;
private String FILENAME; //getters an setters}
Insert it to database
public class FileBodyDaoImpl implements FileBodyDao {
public int insertData(final FileBody fileBody) throws IOException {
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
LobHandler lobHandler = new DefaultLobHandler();
final InputStream in = new ByteArrayInputStream(fileBody.getBODY());
final int fileSize = in.available();
Map<String, Object> out = jdbcTemplate.queryForMap("SELECT ID FROM sp_NEWFILE(?,?,?)",
new AbstractLobCreatingPreparedStatementCallback(lobHandler) {
protected void setValues(PreparedStatement ps, LobCreator lobCreator) throws SQLException,
DataAccessException {
ps.setString(1, fileBody.getFILENAME());
lobCreator.setBlobAsBinaryStream(ps, 2, in, fileSize);
ps.setNull(3, java.sql.Types.INTEGER);
}
});
int last_inserted = Integer.parseInt(String.valueOf(out.get("ID")));
return last_inserted;
}
And my stored procedure
create or alter procedure sp_NEWFILE (
FILENAME varchar(255),
BODY blob sub_type 0 segment size 80,
USEID integer)
returns (
ID integer)
as
begin
if (useid is not null) then ID=USEID;
else ID=GEN_ID(gen_filebody_id,1);
if ((FILENAME is NULL) or (FILENAME='')) then FILENAME='UNDEFINED';
INSERT INTO t_filebody(ID,BODY,FILENAME) VALUES(:ID,:BODY,:FILENAME);
suspend;
end^
and i get an Exception:
Request processing failed; nested exception is org.springframework.jdbc.BadSqlGrammarException:
PreparedStatementCallback;
bad SQL grammar [SELECT ID FROM sp_NEWFILE(?,?,?)]; nested exception is org.firebirdsql.jdbc.field.TypeConversionException: Error converting to object.
Versions:
jaybird-jdk17-2.2.5;
Source: firebird2.5 Version: 2.5.1.26351.ds4-2ubuntu0.1;
The problem is that queryForMap does not support a PreparedStatementCallback (contrary to for example execute), instead your anonymous object is considered a normal parameter for the query to execute, and Jaybird does not support this object type. And if Jaybird had supported it, you would have received an error for missing parameters 2 and 3.
Your code can be greatly simplified by passing the byte array:
Map<String, Object> out = jdbcTemplate.queryForMap("SELECT ID FROM sp_NEWFILE(?,?,?)",
fileBody.getFILENAME(), fileBody.getBODY(), null);
This works as Jaybird considers a BLOB SUB_TYPE 0 as a java.sql.Types.LONGVARBINARY and JDBC 4.2 appendix B declares that byte[] is the default type for that (although you can also use it as a java.sql.Types.BLOB).
As a side note, your stored procedure does not need to be selectable (removing SUSPEND makes it executable), and the procedure could also be replaced by using a TRIGGER to generate the primary key and retrieving the value either by using INSERT .. RETURNING .. or through the JDBC generated keys facility (which in turn is implemented in Jaybird through INSERT .. RETURNING ..).
For those seeking non-Jaybird solution to insert BLOB using spring jdbctemplate, the following syntax worked for me to use stored procedures which is different compared to insert via queries.
Insert via Queries
ByteArrayInputStream inputStream = new ByteArrayInputStream(file.getBytes());
ps.setBlob(1, inputStream);
Insert via Stored Procedure Call
Map<String, Object> inParams = new HashMap<>();
inParams.put("pi_some_id", id);
inParams.put("pi_file_blob", new SqlLobValue(file.getBytes()));
SqlParameterSource sqlParameterSource = new MapSqlParameterSource(inParams);
SqlParameter[] sqlParameters = {
new SqlParameter("pi_some_id", Types.VARCHAR),
new SqlParameter("pi_file_blob", Types.BLOB),
new SqlOutParameter("po_error_flag", Types.VARCHAR),
new SqlOutParameter("po_message", Types.VARCHAR)};
SimpleJdbcCall simpleJdbcCall = new SimpleJdbcCall(jdbcTemplate).withoutProcedureColumnMetaDataAccess().
withProcedureName(storedProcName).withCatalogName(packageName).
declareParameters(sqlParameters);
Map<String, Object> storedProcResult = simpleJdbcCall.execute(sqlParameterSource);

Spring JdbcTemplate and oracle arrayofnumber

I'm using Spring and Oracle database in my solution and i need to execute script
select count(1) from ELEMENTS, table(cast(? as arrayofnumbers)) session_ids
where root_session_id in session_ids.VALUE
but i have a problem with passing input parameter.
i try to pass List or array of BigInteger into
JdbcTemplate.queryForObject("select count(1) from ELEMENTS, table(cast(? as arrayofnumbers)) session_ids
where root_session_id in session_ids.VALUE", Integer.class, INPUT_PARAMS)
but has an Exception:
java.sql.SQLException: Invalid column type
at oracle.jdbc.driver.OraclePreparedStatement.setObjectCritical(OraclePreparedStatement.java:8861)
at oracle.jdbc.driver.OraclePreparedStatement.setObjectInternal(OraclePreparedStatement.java:8338)
at oracle.jdbc.driver.OraclePreparedStatement.setObjectInternal(OraclePreparedStatement.java:9116)
at oracle.jdbc.driver.OraclePreparedStatement.setObject(OraclePreparedStatement.java:9093)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.setObject(OraclePreparedStatementWrapper.java:234)
at weblogic.jdbc.wrapper.PreparedStatement.setObject(PreparedStatement.java:357)
Does anyone have the same problem?
EDIT:
Forget to describe arrayofnumber. It's custom type:
TYPE arrayofnumbers as table of number(20)
Found the solution:
final BigInteger[] ids = new BigInteger[]{BigInteger.valueOf(9137797712513092132L)};
int count = jdbc.query("select count(1) from NC_DATAFLOW_ELEMENTS\n" +
" where root_session_id in (select /*+ cardinality(t 10) */ * from table(cast (? as arrayofnumbers)) t)"
, new PreparedStatementSetter() {
public void setValues(PreparedStatement preparedStatement) throws SQLException {
Connection conn = preparedStatement.getConnection();
OracleConnection oraConn = conn.unwrap(OracleConnection.class);
oracle.sql.ARRAY widgets = oraConn.createARRAY("ARRAYOFNUMBERS", ids);
preparedStatement.setArray(1, widgets);
}
}, new ResultSetExtractor<Integer>() {
public Integer extractData(ResultSet resultSet) throws SQLException, DataAccessException {
resultSet.next();
return resultSet.getInt(1);
}
});
out.println(count);
should note that type of array (ARRAYOFNUMBER) should be in upper case

Retrieve values fom database using JDBC Template in hashmap

i am using JDBC template for getting data from database in Spring MVC.
my query is:
SELECT count(A.MEETING_ID),ITEM_TBL.REG_EMAIL FROM ITEM_TBL,MEETINGS_TBL WHERE ITEM_TBL.MEETING_ID=MEETINGS_TBL.MEETING_ID
GROUP BY ITEM_TBL.REG_EMAIL
this is returning rows like:
11 nishant#gmail.com
12 abhilasha#yahoo.com
13 shiwani#in.com
i want to store these value into Hash MAP. Can you please help how can i do this using JDBC TEMPLATE?
Thanks
You need ResultExtractor.
You can achieve that using below code.
String sql = "SELECT count(A.MEETING_ID),ITEM_TBL.REG_EMAIL FROM ITEM_TBL,MEETINGS_TBL WHERE ITEM_TBL.MEETING_ID=MEETINGS_TBL.MEETING_ID
GROUP BY ITEM_TBL.REG_EMAIL";
ResultExtractor mapExtractor = new ResultSetExtractor() {
public Object extractData(ResultSet rs) throws SQLException {
Map<String, String> mapOfKeys = new HashMap<String, String>();
while (rs.next()) {
String key = rs.getString("MEETING_ID");
String obj = rs.getString("REG_EMAIL");
/* set the business object from the resultset */
mapOfKeys.put(key, obj);
}
return mapOfKeys;
}
};
Map map = (HashMap) jdbcTemplate.query(sql.toString(), mapExtractor);

Resources