package org.simpleflatmapper.jdbc.test; import org.junit.Test; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.simpleflatmapper.jdbc.JdbcMapper; import org.simpleflatmapper.jdbc.JdbcMapperFactory; import org.simpleflatmapper.map.MappingContext; import org.simpleflatmapper.test.beans.Professor; import org.simpleflatmapper.test.jdbc.JoinTest; import org.simpleflatmapper.test.beans.ProfessorC; import org.simpleflatmapper.test.beans.ProfessorField; import org.simpleflatmapper.test.beans.ProfessorGS; import org.simpleflatmapper.util.ListCollector; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.UUID; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicInteger; //IFJAVA8_START import java.util.stream.Collectors; //IFJAVA8_END import static org.junit.Assert.*; import static org.mockito.Matchers.anyInt; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; public class JoinJdbcMapperTest { private JdbcMapperFactory asmJdbcMapperFactory = JdbcMapperFactoryHelper.asm().addKeys("id", "students_id"); private JdbcMapperFactory noAsmJdbcMapperFactory = JdbcMapperFactoryHelper.noAsm().addKeys("id", "students_id"); private JdbcMapperFactory userJdbcMapperFactory = JdbcMapperFactoryHelper.noAsm().addKeys("uuid"); @Test public void testJoinTableFields() throws Exception { validateMapper(asmJdbcMapperFactory.newMapper(ProfessorField.class)); } @Test public void testJoinTableGSNoAsm() throws Exception { validateMapper(noAsmJdbcMapperFactory.newMapper(ProfessorGS.class)); } @Test public void testJoinTableGS() throws Exception { validateMapper(asmJdbcMapperFactory.newMapper(ProfessorGS.class)); } @Test public void testJoinTableGS2Joins() throws Exception { validateMapper(asmJdbcMapperFactory.newMapper(ProfessorGS.class)); } @Test public void testJoinTableC() throws Exception { validateMapper(asmJdbcMapperFactory.newMapper(ProfessorC.class)); } @Test public void testJoinTableCNoAsm() throws Exception { final JdbcMapper<ProfessorC> mapper = noAsmJdbcMapperFactory.newMapper(ProfessorC.class); validateMapper(mapper); assertNotNull(mapper.toString()); } @Test public void testJoinTableCNoAsmMultiThread() throws Exception { ExecutorService executor = Executors.newFixedThreadPool(4); try { final JdbcMapper<ProfessorC> mapper = noAsmJdbcMapperFactory.newMapper(ProfessorC.class); List<Future<Object>> futures = new ArrayList<Future<Object>>(100); for (int i = 0; i <300; i++) { futures.add(executor.submit(new Callable<Object>() { @Override public Object call() throws Exception { validateMapper(mapper); return null; } })); } for(Future<Object> f : futures) { f.get(); } } finally { executor.shutdown(); } } @Test public void testJoinTableGSManualMapping() throws Exception { JdbcMapper<ProfessorGS> mapper = JdbcMapperFactoryHelper.asm() .newBuilder(ProfessorGS.class) .addKey("id") .addMapping("name") .addKey("students_id") .addMapping("students_name") .addMapping("students_phones_value") .mapper(); validateMapper(mapper); } private ResultSet setUpResultSetMock() throws SQLException { ResultSet rs = mock(ResultSet.class); ResultSetMetaData metaData = mock(ResultSetMetaData.class); final String[] columns = new String[] { "id", "name", "students_id", "students_name", "students_phones_value"}; when(metaData.getColumnCount()).thenReturn(columns.length); when(metaData.getColumnLabel(anyInt())).then(new Answer<String>() { @Override public String answer(InvocationOnMock invocationOnMock) throws Throwable { return columns[-1 + (Integer)invocationOnMock.getArguments()[0]]; } }); when(rs.getMetaData()).thenReturn(metaData); final AtomicInteger ai = new AtomicInteger(); when(rs.next()).then(new Answer<Boolean>() { @Override public Boolean answer(InvocationOnMock invocationOnMock) throws Throwable { return ai.getAndIncrement() < JoinTest.ROWS.length; } }); final Answer<Object> getValue = new Answer<Object>() { @Override public Object answer(InvocationOnMock invocationOnMock) throws Throwable { final Object[] row = JoinTest.ROWS[ai.get() - 1]; final Integer col = -1 + (Integer) invocationOnMock.getArguments()[0]; return (row[col]); } }; when(rs.getInt(anyInt())).then(getValue); when(rs.getString(anyInt())).then(getValue); when(rs.getObject(anyInt())).then(getValue); return rs; } private <T extends Professor<?>> void validateMapper(JdbcMapper<T> mapper) throws Exception { List<T> professors = mapper.forEach(setUpResultSetMock(), new ListCollector<T>()).getList(); JoinTest.validateProfessors(professors); //IFJAVA8_START JoinTest.validateProfessors(mapper.stream(setUpResultSetMock()).collect(Collectors.<T>toList())); JoinTest.validateProfessors(mapper.stream(setUpResultSetMock()).limit(3).collect(Collectors.<T>toList())); //IFJAVA8_END Iterator<T> iterator = mapper.iterator(setUpResultSetMock()); professors = new ArrayList<T>(); while(iterator.hasNext()) { professors.add(iterator.next()); } JoinTest.validateProfessors(professors); final ResultSet rs = setUpResultSetMock(); rs.next(); MappingContext<? super ResultSet> mappingContext = mapper.newMappingContext(rs); mappingContext.broke(rs); final T professor = mapper.map(rs, mappingContext); JoinTest.validateProfessorMap(professor); rs.next(); mappingContext.broke(rs); rs.next(); mappingContext.broke(rs); mapper.mapTo(rs, professor, mappingContext); JoinTest.validateProfessorMapTo(professor); } @Test public void testUser() throws SQLException { JdbcMapper<User> mapper = userJdbcMapperFactory.newBuilder(User.class).addKey("id").addMapping("name").addMapping("roles_name").mapper(); ResultSet rs = mock(ResultSet.class); when(rs.next()).thenReturn(true, true, false); when(rs.getInt(1)).thenReturn(1, 1); when(rs.getString(2)).thenReturn("n1", "n1"); when(rs.getString(3)).thenReturn("r1", "r2"); Iterator<User> iterator = mapper.iterator(rs); User u = iterator.next(); assertEquals(1, u.id); assertEquals("n1", u.name); assertEquals(2, u.roles.size()); } public static class User { public int id; public String name; public Set<Role> roles; } public static class Role { public String name; } }