Results 1 to 4 of 4

Thread: How To: Write a List of Items with a ItemWriter

  1. #1
    Join Date
    Aug 2006
    Location
    Arequipa-Peru / South America
    Posts
    2,796

    Question How To: Write a List of Items with a ItemWriter

    Hello Guys

    I have the follow code, trying to make a solution for this case
    How To: Read Once and Write 3 times in parallel

    First, the step is

    Code:
    <batch:step id="clienteCuentaCabeceraStep" >
    	<batch:tasklet transaction-manager="transactionManager">
    		<batch:chunk reader="clienteJdbcPagingItemReader" 
    				   processor="clienteCuentaCabeceraListItemProcessor"
    				   writer="clienteCuentaCabeceraJdbcBatchWriter"
    				   commit-interval="50"
    					/>								
    	</batch:tasklet>
    </batch:step>
    The processor is

    Code:
    public class ClienteCuentaCabeceraListItemProcessor implements ItemProcessor<Cliente,List<ClienteCuentaCabecera>>{
    	
    	....	
    	
    	@Override
    	public List<ClienteCuentaCabecera> process(Cliente cliente) throws Exception {
    		
    		List<ClienteCuentaCabecera> clientesCuentaCabecera = new ArrayList<ClienteCuentaCabecera>();
    		
    		for(int i=0;i<3;i++){
    		     ....
    		}
    				
    		return clientesCuentaCabecera;
    	}
    }
    Each List contains three items

    The writer is

    Code:
    <bean id="clienteCuentaCabeceraJdbcBatchWriter"
    	      class="org.springframework.batch.item.database.JdbcBatchItemWriter">
    	      <property name="dataSource" ref="dataSource"/>
    		  <property name="sql" 
    		            value="INSERT INTO clientecuentacabecera(idClienteCuentaCabecera, fechaCreacionClienteCuentaCabecera, totalDisponibleClienteCuentaCabecera, estadoClienteCuentaCabecera, idCliente, idMoneda) 
    		                   VALUES(?,?,?,?,?,?)" />
    		  <property name="itemPreparedStatementSetter" >
    		  	<bean class="com.manuel.jordan.batch.writer.ClienteCuentaCabeceraItemPreparedStatementSetter"/>
    		  </property>
    	</bean>
    Where ClienteCuentaCabeceraItemPreparedStatementSetter is

    Code:
    public class ClienteCuentaCabeceraItemPreparedStatementSetter implements ItemPreparedStatementSetter<ClienteCuentaCabecera>{
    
    	@Override
    	public void setValues(ClienteCuentaCabecera clienteCuentaCabecera, PreparedStatement ps) throws SQLException {
    
    		ps.setString(1,clienteCuentaCabecera.getIdClienteCuentaCabecera() );
                    ...
    		
    		
    	}
    }
    When I execute the code I get

    Code:
    2012-10-29 13:42:46,421 DEBUG [org.springframework.batch.core.repository.dao.JdbcStepExecutionDao] - 
    <Truncating long message before update of StepExecution, original message is: java.lang.ClassCastException: 
    java.util.ArrayList cannot be cast to com.manuel.jordan.domain.ClienteCuentaCabecera
    	at 
    com.manuel.jordan.batch.writer.ClienteCuentaCabeceraItemPreparedStatementSetter.setValues(ClienteCuentaCabeceraItemPreparedStatementSetter.java:1)
    Well even when the JdbcBatchItemWriter can write a List of items, the SQL statement arise the exception because it expect a list of Items, not a List of List of items.

    Even when like playing I did the follow variation shown below

    Code:
    public class ClienteCuentaCabeceraListItemPreparedStatementSetter implements ItemPreparedStatementSetter<List<ClienteCuentaCabecera>>{
    
    	@Override
    	public void setValues(List<ClienteCuentaCabecera> clientesCuentaCabecera, PreparedStatement ps) throws SQLException {
    				
    		for(ClienteCuentaCabecera clienteCuentaCabecera : clientesCuentaCabecera){
    			
    		
    			ps.setString(1,clienteCuentaCabecera.getIdClienteCuentaCabecera() );
     		        ...
    		}
    	}
    }
    Always write the last item of each collection, the third

    Has sense because it just iterates, and the first and second are overrided by the third and this last value assignation is really the only what is write it in the DB.

    How I could handle this?

    I am thinking in use a ItemWriteAdapter to call a customized service where the repository work with the jdbcTemplate with the method batchUpdate method.

    Exists other way to handle this situation with Spring Batch itself?

    Thanks in advanced
    - Manuel Jordan

    Kill Your Pride, Share Your Knowledge With All
    The Fear Of The LORD Is The Beginning Of Knowledge, But Fools Despise Wisdom And Discipline. Proverbs 1:7

    Blog


    Technical Reviewer of Apress

    • Pro SpringSource dm Server
    • Spring Enterprise Recipes: A Problem-Solution Approach
    • Spring Recipes: A Problem-Solution Approach, 2nd Edition
    • Pro Spring Integration
    • Pro Spring Batch
    • Pro Spring 3
    • Pro Spring MVC: With Web Flow
    • Pro Spring Security

  2. #2
    Join Date
    Sep 2008
    Location
    Chicagoland, IL
    Posts
    351

    Default

    Be careful here. Returning a list from the process method of the ItemProcessor means that you are going to get a List<List< ClienteCuentaCabecera>> in the ItemWriter.write method. This means that each call to the ClienteCuentaCabeceraListItemPreparedStatementSett er will expect you to map List<ClienteCuentaCabecera> to a single insert.
    Michael Minella
    Spring Batch Lead
    Author - Pro Spring Batch
    http://www.michaelminella.com
    Twitter: @MichaelMinella

  3. #3
    Join Date
    Aug 2006
    Location
    Arequipa-Peru / South America
    Posts
    2,796

    Default

    Hello Michael

    Thanks for the reply.

    Returning a list from the process method of the ItemProcessor means that you are going to get a List<List< ClienteCuentaCabecera>> in the ItemWriter.write method.
    Yes, each List<ClienteCuentaCabecera> element of the List<List< ClienteCuentaCabecera>> master list has three items.

    This means that each call to the ClienteCuentaCabeceraListItemPreparedStatementSett er will expect you to map List<ClienteCuentaCabecera> to a single insert.
    Yes and ...

    I did the follow for the writer

    Code:
    <bean id="clienteCuentaCabeceraItemWriterAdapter"
    	       class="org.springframework.batch.item.adapter.ItemWriterAdapter">
    	       <property name="targetObject" ref="clienteCuentaCabeceraBoImpl"/>
    	       <property name="targetMethod" value="insertarClientesCuentaCabecera" />
    	 </bean>
    And finally in my DAO method has

    Code:
    @Override
     public void insertarClientesCuentaCabecera(List<ClienteCuentaCabecera> clientesCuentaCabecera){
    	
    		 String sql = "INSERT INTO clientecuentacabecera(" +
    		 			  "idClienteCuentaCabecera, " +
    		 			  "fechaCreacionClienteCuentaCabecera, " +
    		 			  "totalDisponibleClienteCuentaCabecera, " +
    		 			  "estadoClienteCuentaCabecera, " +
    		 			  "idCliente, " +
    		 			  "idMoneda" +
    		 			  ")VALUES(?,?,?,?,?,?)" ;
    		 		 		 
    		 List<Object[]> batch = new ArrayList<Object[]>(); 
    		 				 
    		 for (ClienteCuentaCabecera clienteCuentaCabecera : clientesCuentaCabecera) {
    	            Object[] values = new Object[] {
    	            		clienteCuentaCabecera.getIdClienteCuentaCabecera(),
    	            		clienteCuentaCabecera.getFechaCreacionClienteCuentaCabecera().toDate(),
    	            		clienteCuentaCabecera.getTotalDisponibleClienteCuentaCabecera(),
    	            		clienteCuentaCabecera.getEstadoClienteCuentaCabecera(),
    	            		clienteCuentaCabecera.getCliente().getIdCliente(),
    	            		clienteCuentaCabecera.getMoneda().getIdMoneda()
    	            };
    	            batch.add(values);
    	    }
    		 
    		 jdbcTemplate.batchUpdate(sql, batch);
    				 
     }
    And work. For my it has sense, but look weird for me that Spring Batch be working with jdbcTemplate.batchUpdate

    Pls let me know If you have a better suggestion.

    Remember that this solution is a way to work around for this thread
    How To: Read Once and Write 3 times in parallel

    Thank you
    - Manuel Jordan

    Kill Your Pride, Share Your Knowledge With All
    The Fear Of The LORD Is The Beginning Of Knowledge, But Fools Despise Wisdom And Discipline. Proverbs 1:7

    Blog


    Technical Reviewer of Apress

    • Pro SpringSource dm Server
    • Spring Enterprise Recipes: A Problem-Solution Approach
    • Spring Recipes: A Problem-Solution Approach, 2nd Edition
    • Pro Spring Integration
    • Pro Spring Batch
    • Pro Spring 3
    • Pro Spring MVC: With Web Flow
    • Pro Spring Security

  4. #4
    Join Date
    Sep 2008
    Location
    Chicagoland, IL
    Posts
    351

    Default

    I stand by my comments in the other thread. This will cause your counts to be off at a minimum.
    Michael Minella
    Spring Batch Lead
    Author - Pro Spring Batch
    http://www.michaelminella.com
    Twitter: @MichaelMinella

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •