I am reading data from excel table and using java trying to set those values into database. My excel table has 6 columns and 170 rows. I have made class ExcelDataModel and mathod in which I go through excell table, but now I am stuck on how to pass arguments to BatchPreparedStatement. This is my code:
#Override
public void getExcell2() {
final String PATH = "C:\\Workspace\\zaposlenici.xlsx";
try {
Workbook workbook = WorkbookFactory.create(new File(PATH));
Sheet sh = workbook.getSheetAt(0);
Iterator<Row> rowIterator = sh.iterator();
while (rowIterator.hasNext()) {
Row row = rowIterator.next();
Iterator<Cell> cellIterator = row.cellIterator();
while (cellIterator.hasNext()) {
Cell cell = cellIterator.next();
//how to pass arguments from one row to preparedStatement?
jdbcTemplate.batchUpdate("INSERT INTO INS_RAZNO.ZAPOSLENICI_TEST VALUES (?, ?, ?, ?, ?, ?)", new BatchPreparedStatementSetter() {
#Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
ExcelDataModel ex = new ExcelDataModel();
ps.setString(1, ex.getIme());
ps.setString(2, ex.getPrezime());
ps.setString(3, ex.getOdjel());
ps.setString(4, ex.getSlozenostPosla());
ps.setString(5, ex.getStarost());
ps.setString(6, ex.getMjesecniOD());
}
#Override
public int getBatchSize() {
return 0;
}
});
}}
} catch (EncryptedDocumentException | InvalidFormatException | IOException e) {
e.printStackTrace();
}
}
And here is my ExcelDataModel code:
public class ExcelDataModel {
private String ime;
private String prezime;
private String odjel;
private String slozenostPosla;
private String starost;
private String mjesecniOD;
public String getIme() {
return ime;
}
public void setIme(String ime) {
this.ime = ime;
}
public String getPrezime() {
return prezime;
}
public void setPrezime(String prezime) {
this.prezime = prezime;
}
public String getOdjel() {
return odjel;
}
public void setOdjel(String odjel) {
this.odjel = odjel;
}
public String getSlozenostPosla() {
return slozenostPosla;
}
public void setSlozenostPosla(String slozenostPosla) {
this.slozenostPosla = slozenostPosla;
}
public String getStarost() {
return starost;
}
public void setStarost(String starost) {
this.starost = starost;
}
public String getMjesecniOD() {
return mjesecniOD;
}
public void setMjesecniOD(String mjesecniOD) {
this.mjesecniOD = mjesecniOD;
}
}
I dont know how to pass those arguments into preparedStatement. Basicaly, how to form data to become arguments?
Any ideas? Thank you!
First of all lets understand the functioning of the BatchPreparedStatementSetter, it contains two methods:
getBatchSize(): Will define the quantity of records will be iterating over in the setValues method, the index will be passed as the second argument.
setValues(java.sql.PreparedStatement ps, int i): Will iterate the number of times defined in the getBatchSize() method.
So what is the point of this, you can access the elements of your collection using the index, like the example below:
jdbcTemplate.batchUpdate("INSERT INTO INS_RAZNO.ZAPOSLENICI_TEST VALUES (?, ?, ?, ?, ?, ?)", new BatchPreparedStatementSetter() {
#Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
ps.setString(1, sh.getCell(i,1)); // Iterating over row, getting the first cell
}
#Override
public int getBatchSize() {
return sheet.getPhysicalNumberOfRows(); // Total rows in the Excel for example
}
});
PS: I used the Apache POI Documentation to suggest the methods to use
BatchPreparedStatementSetter Documentation
You have to choose between two options:
Call update in cell iterate loop and use JdbcTemplate#update function instead of batchUpdate.
If you want batchUpdate then first you iterate Excel cells, collect data to List. And then outside of loop you can use JdbcTemplate#batchUpdate.
but not both.
Related
I'm developing this application to fetch data from a single table from an existing Oracle database.
Here we've got the entity:
public class OrdemDeServicoCount {
private Long ordensInternas;
private Long ordensAtrasadas;
// assume getters and setters
}
The mapper:
public class OrdemMapper implements RowMapper<OrdemDeServicoCount> {
#Override
public OrdemDeServicoCount mapRow(ResultSet rs, int rowNum) throws SQLException {
OrdemDeServicoCount ordens = new OrdemDeServicoCount();
ordens.setOrdensInternas(rs.getLong("ordensInternas"));
// ordens.setOrdensAtrasadas(rs.getLong("ordensAtrasadas"));
return ordens;
}
}
And finally, the DAO:
public class OrdemDAO {
private JdbcTemplate jdbcTemplate;
public OrdemDAO(JdbcTemplate jdbcTemplate) {
super();
this.jdbcTemplate = jdbcTemplate;
}
public List<OrdemDeServicoCount> countOrdensInternasSemEncerrar() {
String sql = "SELECT COUNT(a.nr_sequencia) AS ordensInternas FROM MAN_ORDEM_SERVICO a "
+ "WHERE a.IE_STATUS_ORDEM IN (1,2) AND a.NR_GRUPO_PLANEJ IN (21)";
List<OrdemDeServicoCount> ordens = jdbcTemplate.query(sql, new OrdemMapper());
return ordens;
}
By the way, you all must know that if I declare uncomment the line ordens.setOrdensInternas(rs.getLong("ordensInternas")); in the mapper, I would get an error, because in my DAO, I'm not using that field.
But what if I need to create another method that uses just the ordensInternas field? Then again, I'd get an error...
So, my doubt here is: if I need to use the ordensAtrasadas field from the entity, will I have to create another class just to implement another mapper? Or is there a way that I can do any conditional in my current OrdemMapper class?
Just put your assignments in individual try-catch statements.
public class OrdemMapper implements RowMapper<OrdemDeServicoCount> {
#Override
public OrdemDeServicoCount mapRow(ResultSet rs, int rowNum) throws SQLException {
OrdemDeServicoCount ordens = new OrdemDeServicoCount();
try {
ordens.setOrdensInternas(rs.getLong("ordensInternas"));
} catch (SQLException ex) {
// This will happen if the columnIndex is invalid among other things
}
try {
ordens.setOrdensAtrasadas(rs.getLong("ordensAtrasadas"));
} catch (SQLException ex) {
// This will happen if the columnIndex is invalid among other things
}
return ordens;
}
}
Just so I don't forget
Java 8 SE
Eclipse 2019-12
Spring Boot 2.2.4.RELEASE
I am trying to learn Spring Boot, and I am struggling to understand why a lambda doesn't compile. Here is the spring boot example (which compiles).
jdbcTemplate.query(
"SELECT id, first_name, last_name FROM customers WHERE first_name = ?", new Object[] { "Josh" },
(rs, rowNum) -> new Customer(rs.getLong("id"), rs.getString("first_name"), rs.getString("last_name"))
).forEach(customer -> log.info(customer.toString()));
And here is my attempt to modify this example to my own needs:
#RestController
public class SwitchController {
#Autowired
JdbcTemplate jdbcTemplate;
#GetMapping
public Rows getSwitchRows() {
Rows switches = new Rows();
jdbcTemplate.query(
"SELECT swityp, oldkey, newkey, delete FROM table",
(rs, rowNum) -> new Switch(rs.getString("swityp"), rs.getString("oldkey"), rs.getString("newKey"), rs.getString("delete"))
).forEach(switch -> switches.addRow(switch));
return switches;
}
}
The lambda in the forEach() gives an error on -> which says Syntax error on token "->", ( expected and also on switches.addRow(switch) which says Syntax error on token "switch", delete this token. It is almost as if the forEach() doesn't recognize that I typed a lambda. Maybe what I thought was a lambda, isn't. If that is the case, what makes it not a lambda?
Here are my Switch and Rows classses in case that helps:
Switch.java
public class Switch {
private final String switchType;
private final String oldKey;
private final String newKey;
private final String delete;
public Switch(String switchType, String oldKey, String newKey, String delete) {
this.switchType = switchType;
this.oldKey = oldKey;
this.newKey = newKey;
this.delete = delete;
}
public String getSwitchType() {
return switchType;
}
public String getOldKey() {
return oldKey;
}
public String getNewKey() {
return newKey;
}
public String getDelete() {
return delete;
}
}
Rows.java
public class Rows {
private Object[] rows;
public Rows () {
super();
}
public void addRow (Object row) {
rows[rows.length] = row;
}
}
im developing an application and i'm trying to insert a new row into jtable
i've followed this tutorial , the user can add/remove product information(row) through a form.the database & the table should be updated ,the remove function works well but i can't insert new row into the table .
Note:- when i close the app & run it again the table is updated
and here's my code
public class TableModel extends AbstractTableModel {
Object[] values;
String[] columnNames;
private ArrayList productInfoList;
public TableModel() {
super();
Session session = HibernateUtil.openSession();
Query q = session.createQuery("from Product");
productInfoList = new ArrayList(q.list());
session.close();
}
#Override
public int getRowCount() {
//return dataVec.size();
return productInfoList.size();
}
#Override
public int getColumnCount() {
return 9;
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
Product product = (Product) productInfoList.get(rowIndex);
values = new Object[]{product.getProdectId(),
product.getProductName(), product.getProductBuyingPrice(),
product.getProductSalesPrice(), product.getCategory(), product.getBrand(),
product.getProductQuantity(), product.getProductMinQuantity(), product.getProductDescription()};
return values[columnIndex];
}
#Override
public String getColumnName(int column)
{
columnNames=new String[]{"id","Product Name","Buy price","Sale price ","Category",
"Brand","Quantatity","Min Quantatity","Description"};
return columnNames[column];
}
public void removeRow(int rowIndex) {
productInfoList.remove(rowIndex);
fireTableRowsDeleted(rowIndex, rowIndex);
}
public void insertRow(int rowIndex,Product everyRow) {
productInfoList.add(rowIndex, everyRow);
fireTableRowsInserted(rowIndex, rowIndex);
}
}
this is the code that i try to insert row with
public void AddRow() {
int position = jTable1.getRowCount() - 1;
System.out.println(position); // test
Product product = new Product();
tablemodel.insertRow(position, product);
}
Please help me as i'm get tired of it :|
Your TableModel is storing a Product object in an ArrayList.
So, when you want to add a new row to the model you need to create a new Product object and add the Product to the ArrayList.
Also, you don't need to invoke table.repaint(), the insertRow(...) method is invoking the fireTableRowsInserted(...) method which will tell the table to repaint the row.
I am trying to create a "select from insert" within my Spring JdbcDaoSupport class and am having trouble figuring out how to get the data from the select statement and return it.
My EventJdbcTemplate (my DaoImpl):
#Service
public class EventJdbcTemplate extends JdbcDaoSupport implements EventDao {
private static final Logger LOGGER = Logger.getLogger(EventJdbcTemplate.class);
private static final String SQL_INSERT_EVENT = "SELECT EVENT_ID FROM FINAL TABLE " +
"(INSERT INTO EBT10DBB.SB0401T0 (EVENT_NAME, HOST_NAME, USER_ID) " +
"VALUES(?, ?, \'EMP0321\'))";
#Autowired
public EventJdbcTemplate(DataSource pDataSource) {
super.setDataSource(pDataSource);
}
#Override
public Integer createEvent(EventBean pEventBean) { //(Integer id, String eventName)
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Entering create(Event event) of EventJDBCTemplate.");
}
// This SQL works, but is for an INSERT only.
/*this.getJdbcTemplate().query(SQL_INSERT_EVENT, new Object[]{
pEventBean.getEventName(),
pEventBean.getHostName()
});*/
final List eventList = this.getJdbcTemplate().query(SQL_INSERT_EVENT, new Object[]{
pEventBean.getEventName(),
pEventBean.getHostName()
}, new EventRowMapper()
);
Event event = null;
for (int i = 0; i < eventList.size(); i++) {
event = (Event)eventList.get(i);
}
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Exiting create(Event event) of EventJDBCTemplate.");
}
//return statement -- should return either the entire "pEventBean", or
//just the unique key, "EVENT_ID".
return event.getId();
}
EventRowMapper class (Not sure is I'll need this for the select or not):
public class EventRowMapper implements RowMapper<Event> {
#Override
public Event mapRow(ResultSet rs, int rowNum) throws SQLException {
final EventBuilder event = new EventImpl.EventBuilder();
event.setId(rs.getInt("EVENT_ID"));
event.setEventName("EVENT_NAME");
event.setHostName("HOST_NAME");
return event.build();
}
}
So my goal is to return an Integer value that would be the unique key (EVENT_ID) that is created from the INSERT SQL.
You can use SimpleJdbcInsert provided by Spring to get back generated keys, see following documentation provided by Spring section
13.5.2 Retrieving auto-generated keys using SimpleJdbcInsert
Here is the Link
Can anyone give me short description about his spring class
org.springframework.jdbc.core.BatchPreparedStatementSetter
(JavaDoc API Link)
It's used for bulk insertion of many rows at once.
This code will illustrate how it's used.
Take a good look at importEmployees method, and everything should become clear.
batchUpdate can be done using JdbcTemplate batchUpdate method as follows..
public int[] batchUpdate(final List<Actor> actors) {
int[] updateCounts = jdbcTemplate.batchUpdate("update t_actor set first_name = ?, " +
"last_name = ? where id = ?",
new BatchPreparedStatementSetter() {
public void setValues(PreparedStatement ps, int i) throws SQLException {
ps.setString(1, actors.get(i).getFirstName());
ps.setString(2, actors.get(i).getLastName());
ps.setLong(3, actors.get(i).getId().longValue());
}
public int getBatchSize() {
return actors.size();
}
});
return updateCounts;
}