View Javadoc

1   package org.springframework.batch.item.database;
2   
3   import static org.easymock.EasyMock.createMock;
4   import static org.easymock.EasyMock.createNiceMock;
5   import static org.easymock.EasyMock.expect;
6   import static org.easymock.EasyMock.replay;
7   import static org.easymock.EasyMock.verify;
8   
9   import java.sql.CallableStatement;
10  import java.sql.Connection;
11  import java.sql.DatabaseMetaData;
12  import java.sql.PreparedStatement;
13  import java.sql.ResultSet;
14  import java.sql.SQLException;
15  
16  import javax.sql.DataSource;
17  
18  import org.hsqldb.Types;
19  import org.junit.Test;
20  import org.junit.internal.runners.JUnit4ClassRunner;
21  import org.junit.runner.RunWith;
22  import org.springframework.batch.item.ExecutionContext;
23  import org.springframework.jdbc.core.PreparedStatementSetter;
24  import org.springframework.jdbc.core.SqlParameter;
25  import org.springframework.jdbc.datasource.DataSourceTransactionManager;
26  import org.springframework.transaction.PlatformTransactionManager;
27  import org.springframework.transaction.TransactionStatus;
28  import org.springframework.transaction.support.TransactionCallback;
29  import org.springframework.transaction.support.TransactionTemplate;
30  
31  @RunWith(JUnit4ClassRunner.class)
32  public class StoredprocedureItemReaderConfigTests {
33  
34  	/*
35  	 * Should fail if trying to call getConnection() twice
36  	 */
37  	@Test
38  	public void testUsesCurrentTransaction() throws Exception {
39  		DataSource ds = createMock(DataSource.class);
40  		DatabaseMetaData dmd = createNiceMock(DatabaseMetaData.class);
41  		expect(dmd.getDatabaseProductName()).andReturn("Oracle").times(2);
42  		Connection con = createMock(Connection.class);
43  		expect(con.getMetaData()).andReturn(dmd);
44  		expect(con.getMetaData()).andReturn(dmd);
45  		expect(con.getAutoCommit()).andReturn(false);
46  		CallableStatement cs = createNiceMock(CallableStatement.class);
47  		expect(con.prepareCall("{call foo_bar()}", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,
48  				ResultSet.HOLD_CURSORS_OVER_COMMIT)).andReturn(cs);
49  		expect(ds.getConnection()).andReturn(con);
50  		expect(ds.getConnection()).andReturn(con);
51  		con.commit();
52  		replay(con,dmd, ds, cs);
53  		PlatformTransactionManager tm = new DataSourceTransactionManager(ds);
54  		TransactionTemplate tt = new TransactionTemplate(tm);
55  		final StoredProcedureItemReader<String> reader = new StoredProcedureItemReader<String>();
56  		reader.setDataSource(new ExtendedConnectionDataSourceProxy(ds));
57  		reader.setUseSharedExtendedConnection(true);
58  		reader.setProcedureName("foo_bar");
59  		final ExecutionContext ec = new ExecutionContext();
60  		tt.execute(
61  				new TransactionCallback() {
62  					public Object doInTransaction(TransactionStatus status) {
63  						reader.open(ec);
64  						reader.close();
65  						return null;
66  					}
67  				});
68  		verify(ds);
69  	}
70  	
71  	/*
72  	 * Should fail if trying to call getConnection() twice
73  	 */
74  	@Test
75  	public void testUsesItsOwnTransaction() throws Exception {
76  		
77  		DataSource ds = createMock(DataSource.class);
78  		DatabaseMetaData dmd = createNiceMock(DatabaseMetaData.class);
79  		expect(dmd.getDatabaseProductName()).andReturn("Oracle").times(2);
80  		Connection con = createMock(Connection.class);
81  		expect(con.getMetaData()).andReturn(dmd);
82  		expect(con.getMetaData()).andReturn(dmd);
83  		expect(con.getAutoCommit()).andReturn(false);
84  		CallableStatement cs = createNiceMock(CallableStatement.class);
85  		expect(con.prepareCall("{call foo_bar()}", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)).andReturn(cs);
86  		expect(ds.getConnection()).andReturn(con);
87  		expect(ds.getConnection()).andReturn(con);
88  		con.commit();
89  		replay(con,dmd, ds, cs);
90  		PlatformTransactionManager tm = new DataSourceTransactionManager(ds);
91  		TransactionTemplate tt = new TransactionTemplate(tm);
92  		final StoredProcedureItemReader<String> reader = new StoredProcedureItemReader<String>();
93  		reader.setDataSource(ds);
94  		reader.setProcedureName("foo_bar");
95  		final ExecutionContext ec = new ExecutionContext();
96  		tt.execute(
97  				new TransactionCallback() {
98  					public Object doInTransaction(TransactionStatus status) {
99  						reader.open(ec);
100 						reader.close();
101 						return null;
102 					}
103 				});
104 		verify(ds);
105 	}
106 
107 	/*
108 	 * Should fail if trying to call getConnection() twice
109 	 */
110 	@Test
111 	public void testHandlesRefCursorPosition() throws Exception {
112 		
113 		DataSource ds = createMock(DataSource.class);
114 		DatabaseMetaData dmd = createNiceMock(DatabaseMetaData.class);
115 		expect(dmd.getDatabaseProductName()).andReturn("Oracle").times(2);
116 		Connection con = createMock(Connection.class);
117 		expect(con.getMetaData()).andReturn(dmd);
118 		expect(con.getMetaData()).andReturn(dmd);
119 		expect(con.getAutoCommit()).andReturn(false);
120 		CallableStatement cs = createNiceMock(CallableStatement.class);
121 		expect(con.prepareCall("{call foo_bar(?, ?)}", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)).andReturn(cs);
122 		expect(ds.getConnection()).andReturn(con);
123 		expect(ds.getConnection()).andReturn(con);
124 		con.commit();
125 		replay(con,dmd, ds, cs);
126 		PlatformTransactionManager tm = new DataSourceTransactionManager(ds);
127 		TransactionTemplate tt = new TransactionTemplate(tm);
128 		final StoredProcedureItemReader<String> reader = new StoredProcedureItemReader<String>();
129 		reader.setDataSource(ds);
130 		reader.setProcedureName("foo_bar");
131 		reader.setParameters(new SqlParameter[] {
132 				new SqlParameter("foo", Types.VARCHAR),
133 				new SqlParameter("bar", Types.OTHER)});
134 		reader.setPreparedStatementSetter(
135 				new PreparedStatementSetter() {
136 					public void setValues(PreparedStatement ps)
137 							throws SQLException {
138 					}
139 				});
140 		reader.setRefCursorPosition(3);
141 		final ExecutionContext ec = new ExecutionContext();
142 		tt.execute(
143 				new TransactionCallback() {
144 					public Object doInTransaction(TransactionStatus status) {
145 						reader.open(ec);
146 						reader.close();
147 						return null;
148 					}
149 				});
150 		verify(ds);
151 	}
152 }