Repository: cayenne Updated Branches: refs/heads/master 5e037fc73 -> 8b54c052d
http://git-wip-us.apache.org/repos/asf/cayenne/blob/8b54c052/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextIT.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextIT.java index dbf985e..88bf277 100644 --- a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextIT.java +++ b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextIT.java @@ -19,6 +19,29 @@ package org.apache.cayenne.access; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; +import static org.mockito.Matchers.isNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.math.BigDecimal; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import org.apache.cayenne.Cayenne; import org.apache.cayenne.DataObject; import org.apache.cayenne.DataRow; @@ -28,7 +51,6 @@ import org.apache.cayenne.PersistenceState; import org.apache.cayenne.ResultBatchIterator; import org.apache.cayenne.ResultIterator; import org.apache.cayenne.ResultIteratorCallback; -import org.apache.cayenne.conn.PoolManager; import org.apache.cayenne.di.Inject; import org.apache.cayenne.exp.Expression; import org.apache.cayenne.exp.ExpressionFactory; @@ -59,575 +81,552 @@ import org.apache.cayenne.unit.di.server.UseServerRuntime; import org.junit.Before; import org.junit.Test; -import java.math.BigDecimal; -import java.sql.Timestamp; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.eq; -import static org.mockito.Matchers.isNull; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - @UseServerRuntime(CayenneProjects.TESTMAP_PROJECT) public class DataContextIT extends ServerCase { - @Inject - protected DataContext context; - - @Inject - protected DBHelper dbHelper; - - @Inject - protected UnitDbAdapter accessStackAdapter; - - @Inject - protected DataChannelInterceptor queryInterceptor; - - @Inject - protected ServerCaseDataSourceFactory dataSourceFactory; - - protected TableHelper tArtist; - protected TableHelper tExhibit; - protected TableHelper tGallery; - protected TableHelper tPainting; - - @Before - public void setUp() throws Exception { - tArtist = new TableHelper(dbHelper, "ARTIST"); - tArtist.setColumns("ARTIST_ID", "ARTIST_NAME"); - - tExhibit = new TableHelper(dbHelper, "EXHIBIT"); - tExhibit.setColumns("EXHIBIT_ID", "GALLERY_ID", "OPENING_DATE", "CLOSING_DATE"); - - tGallery = new TableHelper(dbHelper, "GALLERY"); - tGallery.setColumns("GALLERY_ID", "GALLERY_NAME"); - - tPainting = new TableHelper(dbHelper, "PAINTING"); - tPainting.setColumns("PAINTING_ID", "PAINTING_TITLE", "ARTIST_ID", "ESTIMATED_PRICE"); - } - - protected void createSingleArtistDataSet() throws Exception { - tArtist.insert(33001, "artist1"); - } - - protected void createFiveArtistDataSet_MixedCaseName() throws Exception { - tArtist.insert(33001, "artist1"); - tArtist.insert(33002, "Artist3"); - tArtist.insert(33003, "aRtist5"); - tArtist.insert(33004, "arTist2"); - tArtist.insert(33005, "artISt4"); - } - - protected void createGalleriesAndExhibitsDataSet() throws Exception { - - tGallery.insert(33001, "gallery1"); - tGallery.insert(33002, "gallery2"); - tGallery.insert(33003, "gallery3"); - tGallery.insert(33004, "gallery4"); - - Timestamp now = new Timestamp(System.currentTimeMillis()); - - tExhibit.insert(1, 33001, now, now); - tExhibit.insert(2, 33002, now, now); - } - - protected void createArtistsDataSet() throws Exception { - tArtist.insert(33001, "artist1"); - tArtist.insert(33002, "artist2"); - tArtist.insert(33003, "artist3"); - tArtist.insert(33004, "artist4"); - tArtist.insert(33005, "artist5"); - tArtist.insert(33006, "artist11"); - tArtist.insert(33007, "artist21"); - } - - protected void createLargeArtistsDataSet() throws Exception { - for (int i = 1; i <= 20; i++) { - tArtist.insert(i, "artist" + i); - } - } - - protected void createArtistsAndPaintingsDataSet() throws Exception { - createArtistsDataSet(); - - tPainting.insert(33001, "P_artist1", 33001, 1000); - tPainting.insert(33002, "P_artist2", 33002, 2000); - tPainting.insert(33003, "P_artist3", 33003, 3000); - tPainting.insert(33004, "P_artist4", 33004, 4000); - tPainting.insert(33005, "P_artist5", 33005, 5000); - tPainting.insert(33006, "P_artist11", 33006, 11000); - tPainting.insert(33007, "P_artist21", 33007, 21000); - } - - @Test - public void testCurrentSnapshot1() throws Exception { - createSingleArtistDataSet(); - - SelectQuery query = new SelectQuery(Artist.class, ExpressionFactory.matchExp(Artist.ARTIST_NAME_PROPERTY, - "artist1")); - Artist artist = (Artist) context.performQuery(query).get(0); - - DataRow snapshot = context.currentSnapshot(artist); - assertEquals(artist.getArtistName(), snapshot.get("ARTIST_NAME")); - assertEquals(artist.getDateOfBirth(), snapshot.get("DATE_OF_BIRTH")); - } - - @Test - public void testCurrentSnapshot2() throws Exception { - createSingleArtistDataSet(); - - // test null values - SelectQuery query = new SelectQuery(Artist.class, ExpressionFactory.matchExp(Artist.ARTIST_NAME_PROPERTY, - "artist1")); - Artist artist = (Artist) context.performQuery(query).get(0); - - artist.setArtistName(null); - artist.setDateOfBirth(null); - - DataRow snapshot = context.currentSnapshot(artist); - assertTrue(snapshot.containsKey("ARTIST_NAME")); - assertNull(snapshot.get("ARTIST_NAME")); - - assertTrue(snapshot.containsKey("DATE_OF_BIRTH")); - assertNull(snapshot.get("DATE_OF_BIRTH")); - } - - @Test - public void testCurrentSnapshot3() throws Exception { - createSingleArtistDataSet(); - - // test null values - SelectQuery query = new SelectQuery(Artist.class, ExpressionFactory.matchExp(Artist.ARTIST_NAME_PROPERTY, - "artist1")); - Artist artist = (Artist) context.performQuery(query).get(0); - - // test FK relationship snapshotting - Painting p1 = new Painting(); - context.registerNewObject(p1); - p1.setToArtist(artist); - - DataRow s1 = context.currentSnapshot(p1); - Map<String, Object> idMap = artist.getObjectId().getIdSnapshot(); - assertEquals(idMap.get("ARTIST_ID"), s1.get("ARTIST_ID")); - } - - /** - * Testing snapshot with to-one fault. This was a bug CAY-96. - */ - @Test - public void testCurrentSnapshotWithToOneFault() throws Exception { - - createGalleriesAndExhibitsDataSet(); - - // Exhibit with Gallery as Fault must still include Gallery - // Artist and Exhibit (Exhibit has unresolved to-one to gallery as in - // the - // CAY-96 bug report) - - ObjectId eId = new ObjectId("Exhibit", Exhibit.EXHIBIT_ID_PK_COLUMN, 2); - Exhibit e = (Exhibit) context.performQuery(new ObjectIdQuery(eId)).get(0); - - assertTrue(e.readPropertyDirectly(Exhibit.TO_GALLERY_PROPERTY) instanceof Fault); - - DataRow snapshot = context.currentSnapshot(e); - - // assert that after taking a snapshot, we have FK in, but the - // relationship - // is still a Fault - assertTrue(e.readPropertyDirectly(Exhibit.TO_GALLERY_PROPERTY) instanceof Fault); - assertEquals(new Integer(33002), snapshot.get("GALLERY_ID")); - } - - /** - * Tests how CHAR field is handled during fetch. Some databases (Oracle...) - * would pad a CHAR column with extra spaces, returned to the client. - * Cayenne should trim it. - */ - @Test - public void testCharFetch() throws Exception { - createSingleArtistDataSet(); - - SelectQuery query = new SelectQuery(Artist.class); - Artist a = (Artist) context.performQuery(query).get(0); - assertEquals(a.getArtistName().trim(), a.getArtistName()); - } - - /** - * Tests how CHAR field is handled during fetch in the WHERE clause. Some - * databases (Oracle...) would pad a CHAR column with extra spaces, returned - * to the client. Cayenne should trim it. - */ - @Test - public void testCharInQualifier() throws Exception { - createArtistsDataSet(); - - Expression e = ExpressionFactory.matchExp("artistName", "artist1"); - SelectQuery q = new SelectQuery(Artist.class, e); - List<Artist> artists = context.performQuery(q); - assertEquals(1, artists.size()); - } - - /** - * Test fetching query with multiple relationship paths between the same 2 - * entities used in qualifier. - */ - @Test - public void testMultiObjRelFetch() throws Exception { - createArtistsAndPaintingsDataSet(); - - SelectQuery q = new SelectQuery(Painting.class); - q.andQualifier(ExpressionFactory.matchExp("toArtist.artistName", "artist2")); - q.orQualifier(ExpressionFactory.matchExp("toArtist.artistName", "artist4")); - List<Painting> results = context.performQuery(q); - - assertEquals(2, results.size()); - } - - /** - * Test fetching query with multiple relationship paths between the same 2 - * entities used in qualifier. - */ - @Test - public void testMultiDbRelFetch() throws Exception { - createArtistsAndPaintingsDataSet(); - - SelectQuery q = new SelectQuery("Painting"); - q.andQualifier(ExpressionFactory.matchDbExp("toArtist.ARTIST_NAME", "artist2")); - q.orQualifier(ExpressionFactory.matchDbExp("toArtist.ARTIST_NAME", "artist4")); - List<?> results = context.performQuery(q); - - assertEquals(2, results.size()); - } - - @Test - public void testSelectDate() throws Exception { - createGalleriesAndExhibitsDataSet(); - - List<Exhibit> objects = context.performQuery(new SelectQuery(Exhibit.class)); - assertFalse(objects.isEmpty()); - - Exhibit e1 = objects.get(0); - assertEquals(java.util.Date.class, e1.getClosingDate().getClass()); - } - - @Test - public void testCaseInsensitiveOrdering() throws Exception { - if (!accessStackAdapter.supportsCaseInsensitiveOrder()) { - return; - } - - createFiveArtistDataSet_MixedCaseName(); - - // case insensitive ordering appends extra columns - // to the query when query is using DISTINCT... - // verify that the result is not messed up - - SelectQuery query = new SelectQuery(Artist.class); - Ordering ordering = new Ordering(Artist.ARTIST_NAME_PROPERTY, SortOrder.ASCENDING_INSENSITIVE); - query.addOrdering(ordering); - query.setDistinct(true); - - List<Artist> objects = context.performQuery(query); - assertEquals(5, objects.size()); - - Artist artist = objects.get(0); - DataRow snapshot = context.getObjectStore().getSnapshot(artist.getObjectId()); - assertEquals(3, snapshot.size()); - - // assert the ordering - assertEquals("artist1", objects.get(0).getArtistName()); - assertEquals("arTist2", objects.get(1).getArtistName()); - assertEquals("Artist3", objects.get(2).getArtistName()); - assertEquals("artISt4", objects.get(3).getArtistName()); - assertEquals("aRtist5", objects.get(4).getArtistName()); - } - - @Test - public void testSelect_DataRows() throws Exception { - createArtistsAndPaintingsDataSet(); - - SelectQuery<DataRow> query = SelectQuery.dataRowQuery(Artist.class, null); - List<DataRow> objects = context.select(query); - - assertNotNull(objects); - assertEquals(7, objects.size()); - assertTrue("DataRow expected, got " + objects.get(0).getClass(), objects.get(0) instanceof DataRow); - } - - @Test - public void testPerformSelectQuery1() throws Exception { - createArtistsAndPaintingsDataSet(); - - SelectQuery query = new SelectQuery(Artist.class); - List<?> objects = context.performQuery(query); - - assertNotNull(objects); - assertEquals(7, objects.size()); - assertTrue("Artist expected, got " + objects.get(0).getClass(), objects.get(0) instanceof Artist); - } - - @Test - public void testPerformSelectQuery2() throws Exception { - createArtistsAndPaintingsDataSet(); - - // do a query with complex qualifier - List<Expression> expressions = new ArrayList<Expression>(); - expressions.add(ExpressionFactory.matchExp("artistName", "artist3")); - expressions.add(ExpressionFactory.matchExp("artistName", "artist5")); - expressions.add(ExpressionFactory.matchExp("artistName", "artist21")); - - SelectQuery query = new SelectQuery(Artist.class, ExpressionFactory.joinExp(Expression.OR, expressions)); - - List<?> objects = context.performQuery(query); - - assertNotNull(objects); - assertEquals(3, objects.size()); - assertTrue("Artist expected, got " + objects.get(0).getClass(), objects.get(0) instanceof Artist); - } - - @Test - public void testPerformQuery_Routing() { - Query query = mock(Query.class); - QueryMetadata md = mock(QueryMetadata.class); - when(query.getMetaData(any(EntityResolver.class))).thenReturn(md); - context.performGenericQuery(query); - verify(query).route(any(QueryRouter.class), eq(context.getEntityResolver()), (Query) isNull()); - } - - @Test - public void testPerformNonSelectingQuery() throws Exception { - - createSingleArtistDataSet(); - - SelectQuery select = new SelectQuery(Painting.class, Expression.fromString("db:PAINTING_ID = 1")); - - assertEquals(0, context.performQuery(select).size()); - - SQLTemplate query = new SQLTemplate(Painting.class, - "INSERT INTO PAINTING (PAINTING_ID, PAINTING_TITLE, ARTIST_ID, ESTIMATED_PRICE) " - + "VALUES (1, 'PX', 33001, 1)"); - context.performNonSelectingQuery(query); - assertEquals(1, context.performQuery(select).size()); - } - - @Test - public void testPerformNonSelectingQueryCounts1() throws Exception { - createArtistsDataSet(); - - SQLTemplate query = new SQLTemplate(Painting.class, - "INSERT INTO PAINTING (PAINTING_ID, PAINTING_TITLE, ARTIST_ID, ESTIMATED_PRICE) " - + "VALUES ($pid, '$pt', $aid, $price)"); - - Map<String, Object> map = new HashMap<String, Object>(); - map.put("pid", new Integer(1)); - map.put("pt", "P1"); - map.put("aid", new Integer(33002)); - map.put("price", new Double(1.1)); - - // single batch of parameters - query.setParameters(map); - - int[] counts = context.performNonSelectingQuery(query); - assertNotNull(counts); - assertEquals(1, counts.length); - assertEquals(1, counts[0]); - } - - @Test - public void testPerformNonSelectingQueryCounts2() throws Exception { - - createArtistsDataSet(); - - SQLTemplate query = new SQLTemplate(Painting.class, - "INSERT INTO PAINTING (PAINTING_ID, PAINTING_TITLE, ARTIST_ID, ESTIMATED_PRICE) " - + "VALUES ($pid, '$pt', $aid, #bind($price 'DECIMAL' 2))"); - - Map<String, Object>[] maps = new Map[3]; - for (int i = 0; i < maps.length; i++) { - maps[i] = new HashMap<String, Object>(); - maps[i].put("pid", new Integer(1 + i)); - maps[i].put("pt", "P-" + i); - maps[i].put("aid", new Integer(33002)); - maps[i].put("price", new BigDecimal("1." + i)); - } - - // single batch of parameters - query.setParameters(maps); - - int[] counts = context.performNonSelectingQuery(query); - assertNotNull(counts); - assertEquals(maps.length, counts.length); - for (int i = 0; i < maps.length; i++) { - assertEquals(1, counts[i]); - } - - SQLTemplate delete = new SQLTemplate(Painting.class, "delete from PAINTING"); - counts = context.performNonSelectingQuery(delete); - assertNotNull(counts); - assertEquals(1, counts.length); - assertEquals(3, counts[0]); - } - - @Test - public void testPerformPaginatedQuery() throws Exception { - createArtistsDataSet(); - - SelectQuery<Artist> query = SelectQuery.query(Artist.class); - query.setPageSize(5); - List<Artist> objects = context.select(query); - assertNotNull(objects); - assertTrue(objects instanceof IncrementalFaultList<?>); - assertTrue(((IncrementalFaultList<Artist>) objects).elements.get(0) instanceof Long); - assertTrue(((IncrementalFaultList<Artist>) objects).elements.get(6) instanceof Long); - - assertTrue(objects.get(0) instanceof Artist); - } - - @Test - public void testPerformPaginatedQuery1() throws Exception { - createArtistsDataSet(); - - EJBQLQuery query = new EJBQLQuery("select a FROM Artist a"); - query.setPageSize(5); - List<?> objects = context.performQuery(query); - assertNotNull(objects); - assertTrue(objects instanceof IncrementalFaultList<?>); - assertTrue(((IncrementalFaultList<?>) objects).elements.get(0) instanceof Long); - assertTrue(((IncrementalFaultList<?>) objects).elements.get(6) instanceof Long); - - assertTrue(objects.get(0) instanceof Artist); - } - - @Test - public void testPerformPaginatedQueryBigPage() throws Exception { - createArtistsDataSet(); - - SelectQuery query = new SelectQuery(Artist.class); - query.setPageSize(5); - final List<?> objects = context.performQuery(query); - assertNotNull(objects); - assertTrue(objects instanceof IncrementalFaultList<?>); - - queryInterceptor.runWithQueriesBlocked(new UnitTestClosure() { - - public void execute() { - assertEquals(7, objects.size()); - } - }); - } - - @Test - public void testPerformDataRowQuery() throws Exception { - - createArtistsDataSet(); - - SelectQuery query = new SelectQuery(Artist.class); - query.setFetchingDataRows(true); - List<?> objects = context.performQuery(query); - - assertNotNull(objects); - assertEquals(7, objects.size()); - assertTrue("Map expected, got " + objects.get(0).getClass(), objects.get(0) instanceof Map<?, ?>); - } - - @Test - public void testCommitChangesRO1() throws Exception { - - ROArtist a1 = (ROArtist) context.newObject("ROArtist"); - a1.writePropertyDirectly("artistName", "abc"); - a1.setPersistenceState(PersistenceState.MODIFIED); - - try { - context.commitChanges(); - fail("Inserting a 'read-only' object must fail."); - } catch (Exception ex) { - // exception is expected, - // must blow on saving new "read-only" object. - } - } - - @Test - public void testCommitChangesRO2() throws Exception { - createArtistsDataSet(); - - SelectQuery query = new SelectQuery(ROArtist.class, ExpressionFactory.matchExp(Artist.ARTIST_NAME_PROPERTY, - "artist1")); - ROArtist a1 = (ROArtist) context.performQuery(query).get(0); - a1.writeProperty(ROArtist.ARTIST_NAME_PROPERTY, "abc"); - - try { - context.commitChanges(); - fail("Updating a 'read-only' object must fail."); - } catch (Exception ex) { - // exception is expected, - // must blow on saving new "read-only" object. - } - } - - @Test - public void testCommitChangesRO3() throws Exception { - - createArtistsDataSet(); - - SelectQuery query = new SelectQuery(ROArtist.class, ExpressionFactory.matchExp(Artist.ARTIST_NAME_PROPERTY, - "artist1")); - ROArtist a1 = (ROArtist) context.performQuery(query).get(0); - context.deleteObjects(a1); - - try { - context.commitChanges(); - fail("Deleting a 'read-only' object must fail."); - } catch (Exception ex) { - // exception is expected, - // must blow on saving new "read-only" object. - } - } - - @Test - public void testCommitChangesRO4() throws Exception { - createArtistsDataSet(); - - SelectQuery query = new SelectQuery(ROArtist.class, ExpressionFactory.matchExp(Artist.ARTIST_NAME_PROPERTY, - "artist1")); - ROArtist a1 = (ROArtist) context.performQuery(query).get(0); - - Painting painting = context.newObject(Painting.class); - painting.setPaintingTitle("paint"); - a1.addToPaintingArray(painting); - - assertEquals(PersistenceState.MODIFIED, a1.getPersistenceState()); - try { - context.commitChanges(); - } catch (Exception ex) { - fail("Updating 'read-only' object's to-many must succeed, instead an exception was thrown: " + ex); - } - - assertEquals(PersistenceState.COMMITTED, a1.getPersistenceState()); - } - - @Test + @Inject + protected DataContext context; + + @Inject + protected DBHelper dbHelper; + + @Inject + protected UnitDbAdapter accessStackAdapter; + + @Inject + protected DataChannelInterceptor queryInterceptor; + + @Inject + protected ServerCaseDataSourceFactory dataSourceFactory; + + protected TableHelper tArtist; + protected TableHelper tExhibit; + protected TableHelper tGallery; + protected TableHelper tPainting; + + @Before + public void setUp() throws Exception { + tArtist = new TableHelper(dbHelper, "ARTIST"); + tArtist.setColumns("ARTIST_ID", "ARTIST_NAME"); + + tExhibit = new TableHelper(dbHelper, "EXHIBIT"); + tExhibit.setColumns("EXHIBIT_ID", "GALLERY_ID", "OPENING_DATE", "CLOSING_DATE"); + + tGallery = new TableHelper(dbHelper, "GALLERY"); + tGallery.setColumns("GALLERY_ID", "GALLERY_NAME"); + + tPainting = new TableHelper(dbHelper, "PAINTING"); + tPainting.setColumns("PAINTING_ID", "PAINTING_TITLE", "ARTIST_ID", "ESTIMATED_PRICE"); + } + + protected void createSingleArtistDataSet() throws Exception { + tArtist.insert(33001, "artist1"); + } + + protected void createFiveArtistDataSet_MixedCaseName() throws Exception { + tArtist.insert(33001, "artist1"); + tArtist.insert(33002, "Artist3"); + tArtist.insert(33003, "aRtist5"); + tArtist.insert(33004, "arTist2"); + tArtist.insert(33005, "artISt4"); + } + + protected void createGalleriesAndExhibitsDataSet() throws Exception { + + tGallery.insert(33001, "gallery1"); + tGallery.insert(33002, "gallery2"); + tGallery.insert(33003, "gallery3"); + tGallery.insert(33004, "gallery4"); + + Timestamp now = new Timestamp(System.currentTimeMillis()); + + tExhibit.insert(1, 33001, now, now); + tExhibit.insert(2, 33002, now, now); + } + + protected void createArtistsDataSet() throws Exception { + tArtist.insert(33001, "artist1"); + tArtist.insert(33002, "artist2"); + tArtist.insert(33003, "artist3"); + tArtist.insert(33004, "artist4"); + tArtist.insert(33005, "artist5"); + tArtist.insert(33006, "artist11"); + tArtist.insert(33007, "artist21"); + } + + protected void createLargeArtistsDataSet() throws Exception { + for (int i = 1; i <= 20; i++) { + tArtist.insert(i, "artist" + i); + } + } + + protected void createArtistsAndPaintingsDataSet() throws Exception { + createArtistsDataSet(); + + tPainting.insert(33001, "P_artist1", 33001, 1000); + tPainting.insert(33002, "P_artist2", 33002, 2000); + tPainting.insert(33003, "P_artist3", 33003, 3000); + tPainting.insert(33004, "P_artist4", 33004, 4000); + tPainting.insert(33005, "P_artist5", 33005, 5000); + tPainting.insert(33006, "P_artist11", 33006, 11000); + tPainting.insert(33007, "P_artist21", 33007, 21000); + } + + @Test + public void testCurrentSnapshot1() throws Exception { + createSingleArtistDataSet(); + + SelectQuery query = new SelectQuery(Artist.class, ExpressionFactory.matchExp(Artist.ARTIST_NAME_PROPERTY, + "artist1")); + Artist artist = (Artist) context.performQuery(query).get(0); + + DataRow snapshot = context.currentSnapshot(artist); + assertEquals(artist.getArtistName(), snapshot.get("ARTIST_NAME")); + assertEquals(artist.getDateOfBirth(), snapshot.get("DATE_OF_BIRTH")); + } + + @Test + public void testCurrentSnapshot2() throws Exception { + createSingleArtistDataSet(); + + // test null values + SelectQuery query = new SelectQuery(Artist.class, ExpressionFactory.matchExp(Artist.ARTIST_NAME_PROPERTY, + "artist1")); + Artist artist = (Artist) context.performQuery(query).get(0); + + artist.setArtistName(null); + artist.setDateOfBirth(null); + + DataRow snapshot = context.currentSnapshot(artist); + assertTrue(snapshot.containsKey("ARTIST_NAME")); + assertNull(snapshot.get("ARTIST_NAME")); + + assertTrue(snapshot.containsKey("DATE_OF_BIRTH")); + assertNull(snapshot.get("DATE_OF_BIRTH")); + } + + @Test + public void testCurrentSnapshot3() throws Exception { + createSingleArtistDataSet(); + + // test null values + SelectQuery query = new SelectQuery(Artist.class, ExpressionFactory.matchExp(Artist.ARTIST_NAME_PROPERTY, + "artist1")); + Artist artist = (Artist) context.performQuery(query).get(0); + + // test FK relationship snapshotting + Painting p1 = new Painting(); + context.registerNewObject(p1); + p1.setToArtist(artist); + + DataRow s1 = context.currentSnapshot(p1); + Map<String, Object> idMap = artist.getObjectId().getIdSnapshot(); + assertEquals(idMap.get("ARTIST_ID"), s1.get("ARTIST_ID")); + } + + /** + * Testing snapshot with to-one fault. This was a bug CAY-96. + */ + @Test + public void testCurrentSnapshotWithToOneFault() throws Exception { + + createGalleriesAndExhibitsDataSet(); + + // Exhibit with Gallery as Fault must still include Gallery + // Artist and Exhibit (Exhibit has unresolved to-one to gallery as in + // the + // CAY-96 bug report) + + ObjectId eId = new ObjectId("Exhibit", Exhibit.EXHIBIT_ID_PK_COLUMN, 2); + Exhibit e = (Exhibit) context.performQuery(new ObjectIdQuery(eId)).get(0); + + assertTrue(e.readPropertyDirectly(Exhibit.TO_GALLERY_PROPERTY) instanceof Fault); + + DataRow snapshot = context.currentSnapshot(e); + + // assert that after taking a snapshot, we have FK in, but the + // relationship + // is still a Fault + assertTrue(e.readPropertyDirectly(Exhibit.TO_GALLERY_PROPERTY) instanceof Fault); + assertEquals(new Integer(33002), snapshot.get("GALLERY_ID")); + } + + /** + * Tests how CHAR field is handled during fetch. Some databases (Oracle...) + * would pad a CHAR column with extra spaces, returned to the client. + * Cayenne should trim it. + */ + @Test + public void testCharFetch() throws Exception { + createSingleArtistDataSet(); + + SelectQuery query = new SelectQuery(Artist.class); + Artist a = (Artist) context.performQuery(query).get(0); + assertEquals(a.getArtistName().trim(), a.getArtistName()); + } + + /** + * Tests how CHAR field is handled during fetch in the WHERE clause. Some + * databases (Oracle...) would pad a CHAR column with extra spaces, returned + * to the client. Cayenne should trim it. + */ + @Test + public void testCharInQualifier() throws Exception { + createArtistsDataSet(); + + Expression e = ExpressionFactory.matchExp("artistName", "artist1"); + SelectQuery q = new SelectQuery(Artist.class, e); + List<Artist> artists = context.performQuery(q); + assertEquals(1, artists.size()); + } + + /** + * Test fetching query with multiple relationship paths between the same 2 + * entities used in qualifier. + */ + @Test + public void testMultiObjRelFetch() throws Exception { + createArtistsAndPaintingsDataSet(); + + SelectQuery q = new SelectQuery(Painting.class); + q.andQualifier(ExpressionFactory.matchExp("toArtist.artistName", "artist2")); + q.orQualifier(ExpressionFactory.matchExp("toArtist.artistName", "artist4")); + List<Painting> results = context.performQuery(q); + + assertEquals(2, results.size()); + } + + /** + * Test fetching query with multiple relationship paths between the same 2 + * entities used in qualifier. + */ + @Test + public void testMultiDbRelFetch() throws Exception { + createArtistsAndPaintingsDataSet(); + + SelectQuery q = new SelectQuery("Painting"); + q.andQualifier(ExpressionFactory.matchDbExp("toArtist.ARTIST_NAME", "artist2")); + q.orQualifier(ExpressionFactory.matchDbExp("toArtist.ARTIST_NAME", "artist4")); + List<?> results = context.performQuery(q); + + assertEquals(2, results.size()); + } + + @Test + public void testSelectDate() throws Exception { + createGalleriesAndExhibitsDataSet(); + + List<Exhibit> objects = context.performQuery(new SelectQuery(Exhibit.class)); + assertFalse(objects.isEmpty()); + + Exhibit e1 = objects.get(0); + assertEquals(java.util.Date.class, e1.getClosingDate().getClass()); + } + + @Test + public void testCaseInsensitiveOrdering() throws Exception { + if (!accessStackAdapter.supportsCaseInsensitiveOrder()) { + return; + } + + createFiveArtistDataSet_MixedCaseName(); + + // case insensitive ordering appends extra columns + // to the query when query is using DISTINCT... + // verify that the result is not messed up + + SelectQuery query = new SelectQuery(Artist.class); + Ordering ordering = new Ordering(Artist.ARTIST_NAME_PROPERTY, SortOrder.ASCENDING_INSENSITIVE); + query.addOrdering(ordering); + query.setDistinct(true); + + List<Artist> objects = context.performQuery(query); + assertEquals(5, objects.size()); + + Artist artist = objects.get(0); + DataRow snapshot = context.getObjectStore().getSnapshot(artist.getObjectId()); + assertEquals(3, snapshot.size()); + + // assert the ordering + assertEquals("artist1", objects.get(0).getArtistName()); + assertEquals("arTist2", objects.get(1).getArtistName()); + assertEquals("Artist3", objects.get(2).getArtistName()); + assertEquals("artISt4", objects.get(3).getArtistName()); + assertEquals("aRtist5", objects.get(4).getArtistName()); + } + + @Test + public void testSelect_DataRows() throws Exception { + createArtistsAndPaintingsDataSet(); + + SelectQuery<DataRow> query = SelectQuery.dataRowQuery(Artist.class, null); + List<DataRow> objects = context.select(query); + + assertNotNull(objects); + assertEquals(7, objects.size()); + assertTrue("DataRow expected, got " + objects.get(0).getClass(), objects.get(0) instanceof DataRow); + } + + @Test + public void testPerformSelectQuery1() throws Exception { + createArtistsAndPaintingsDataSet(); + + SelectQuery query = new SelectQuery(Artist.class); + List<?> objects = context.performQuery(query); + + assertNotNull(objects); + assertEquals(7, objects.size()); + assertTrue("Artist expected, got " + objects.get(0).getClass(), objects.get(0) instanceof Artist); + } + + @Test + public void testPerformSelectQuery2() throws Exception { + createArtistsAndPaintingsDataSet(); + + // do a query with complex qualifier + List<Expression> expressions = new ArrayList<Expression>(); + expressions.add(ExpressionFactory.matchExp("artistName", "artist3")); + expressions.add(ExpressionFactory.matchExp("artistName", "artist5")); + expressions.add(ExpressionFactory.matchExp("artistName", "artist21")); + + SelectQuery query = new SelectQuery(Artist.class, ExpressionFactory.joinExp(Expression.OR, expressions)); + + List<?> objects = context.performQuery(query); + + assertNotNull(objects); + assertEquals(3, objects.size()); + assertTrue("Artist expected, got " + objects.get(0).getClass(), objects.get(0) instanceof Artist); + } + + @Test + public void testPerformQuery_Routing() { + Query query = mock(Query.class); + QueryMetadata md = mock(QueryMetadata.class); + when(query.getMetaData(any(EntityResolver.class))).thenReturn(md); + context.performGenericQuery(query); + verify(query).route(any(QueryRouter.class), eq(context.getEntityResolver()), (Query) isNull()); + } + + @Test + public void testPerformNonSelectingQuery() throws Exception { + + createSingleArtistDataSet(); + + SelectQuery select = new SelectQuery(Painting.class, Expression.fromString("db:PAINTING_ID = 1")); + + assertEquals(0, context.performQuery(select).size()); + + SQLTemplate query = new SQLTemplate(Painting.class, + "INSERT INTO PAINTING (PAINTING_ID, PAINTING_TITLE, ARTIST_ID, ESTIMATED_PRICE) " + + "VALUES (1, 'PX', 33001, 1)"); + context.performNonSelectingQuery(query); + assertEquals(1, context.performQuery(select).size()); + } + + @Test + public void testPerformNonSelectingQueryCounts1() throws Exception { + createArtistsDataSet(); + + SQLTemplate query = new SQLTemplate(Painting.class, + "INSERT INTO PAINTING (PAINTING_ID, PAINTING_TITLE, ARTIST_ID, ESTIMATED_PRICE) " + + "VALUES ($pid, '$pt', $aid, $price)"); + + Map<String, Object> map = new HashMap<String, Object>(); + map.put("pid", new Integer(1)); + map.put("pt", "P1"); + map.put("aid", new Integer(33002)); + map.put("price", new Double(1.1)); + + // single batch of parameters + query.setParameters(map); + + int[] counts = context.performNonSelectingQuery(query); + assertNotNull(counts); + assertEquals(1, counts.length); + assertEquals(1, counts[0]); + } + + @Test + public void testPerformNonSelectingQueryCounts2() throws Exception { + + createArtistsDataSet(); + + SQLTemplate query = new SQLTemplate(Painting.class, + "INSERT INTO PAINTING (PAINTING_ID, PAINTING_TITLE, ARTIST_ID, ESTIMATED_PRICE) " + + "VALUES ($pid, '$pt', $aid, #bind($price 'DECIMAL' 2))"); + + Map<String, Object>[] maps = new Map[3]; + for (int i = 0; i < maps.length; i++) { + maps[i] = new HashMap<String, Object>(); + maps[i].put("pid", new Integer(1 + i)); + maps[i].put("pt", "P-" + i); + maps[i].put("aid", new Integer(33002)); + maps[i].put("price", new BigDecimal("1." + i)); + } + + // single batch of parameters + query.setParameters(maps); + + int[] counts = context.performNonSelectingQuery(query); + assertNotNull(counts); + assertEquals(maps.length, counts.length); + for (int i = 0; i < maps.length; i++) { + assertEquals(1, counts[i]); + } + + SQLTemplate delete = new SQLTemplate(Painting.class, "delete from PAINTING"); + counts = context.performNonSelectingQuery(delete); + assertNotNull(counts); + assertEquals(1, counts.length); + assertEquals(3, counts[0]); + } + + @Test + public void testPerformPaginatedQuery() throws Exception { + createArtistsDataSet(); + + SelectQuery<Artist> query = SelectQuery.query(Artist.class); + query.setPageSize(5); + List<Artist> objects = context.select(query); + assertNotNull(objects); + assertTrue(objects instanceof IncrementalFaultList<?>); + assertTrue(((IncrementalFaultList<Artist>) objects).elements.get(0) instanceof Long); + assertTrue(((IncrementalFaultList<Artist>) objects).elements.get(6) instanceof Long); + + assertTrue(objects.get(0) instanceof Artist); + } + + @Test + public void testPerformPaginatedQuery1() throws Exception { + createArtistsDataSet(); + + EJBQLQuery query = new EJBQLQuery("select a FROM Artist a"); + query.setPageSize(5); + List<?> objects = context.performQuery(query); + assertNotNull(objects); + assertTrue(objects instanceof IncrementalFaultList<?>); + assertTrue(((IncrementalFaultList<?>) objects).elements.get(0) instanceof Long); + assertTrue(((IncrementalFaultList<?>) objects).elements.get(6) instanceof Long); + + assertTrue(objects.get(0) instanceof Artist); + } + + @Test + public void testPerformPaginatedQueryBigPage() throws Exception { + createArtistsDataSet(); + + SelectQuery query = new SelectQuery(Artist.class); + query.setPageSize(5); + final List<?> objects = context.performQuery(query); + assertNotNull(objects); + assertTrue(objects instanceof IncrementalFaultList<?>); + + queryInterceptor.runWithQueriesBlocked(new UnitTestClosure() { + + public void execute() { + assertEquals(7, objects.size()); + } + }); + } + + @Test + public void testPerformDataRowQuery() throws Exception { + + createArtistsDataSet(); + + SelectQuery query = new SelectQuery(Artist.class); + query.setFetchingDataRows(true); + List<?> objects = context.performQuery(query); + + assertNotNull(objects); + assertEquals(7, objects.size()); + assertTrue("Map expected, got " + objects.get(0).getClass(), objects.get(0) instanceof Map<?, ?>); + } + + @Test + public void testCommitChangesRO1() throws Exception { + + ROArtist a1 = (ROArtist) context.newObject("ROArtist"); + a1.writePropertyDirectly("artistName", "abc"); + a1.setPersistenceState(PersistenceState.MODIFIED); + + try { + context.commitChanges(); + fail("Inserting a 'read-only' object must fail."); + } catch (Exception ex) { + // exception is expected, + // must blow on saving new "read-only" object. + } + } + + @Test + public void testCommitChangesRO2() throws Exception { + createArtistsDataSet(); + + SelectQuery query = new SelectQuery(ROArtist.class, ExpressionFactory.matchExp(Artist.ARTIST_NAME_PROPERTY, + "artist1")); + ROArtist a1 = (ROArtist) context.performQuery(query).get(0); + a1.writeProperty(ROArtist.ARTIST_NAME_PROPERTY, "abc"); + + try { + context.commitChanges(); + fail("Updating a 'read-only' object must fail."); + } catch (Exception ex) { + // exception is expected, + // must blow on saving new "read-only" object. + } + } + + @Test + public void testCommitChangesRO3() throws Exception { + + createArtistsDataSet(); + + SelectQuery query = new SelectQuery(ROArtist.class, ExpressionFactory.matchExp(Artist.ARTIST_NAME_PROPERTY, + "artist1")); + ROArtist a1 = (ROArtist) context.performQuery(query).get(0); + context.deleteObjects(a1); + + try { + context.commitChanges(); + fail("Deleting a 'read-only' object must fail."); + } catch (Exception ex) { + // exception is expected, + // must blow on saving new "read-only" object. + } + } + + @Test + public void testCommitChangesRO4() throws Exception { + createArtistsDataSet(); + + SelectQuery query = new SelectQuery(ROArtist.class, ExpressionFactory.matchExp(Artist.ARTIST_NAME_PROPERTY, + "artist1")); + ROArtist a1 = (ROArtist) context.performQuery(query).get(0); + + Painting painting = context.newObject(Painting.class); + painting.setPaintingTitle("paint"); + a1.addToPaintingArray(painting); + + assertEquals(PersistenceState.MODIFIED, a1.getPersistenceState()); + try { + context.commitChanges(); + } catch (Exception ex) { + fail("Updating 'read-only' object's to-many must succeed, instead an exception was thrown: " + ex); + } + + assertEquals(PersistenceState.COMMITTED, a1.getPersistenceState()); + } + + @Test public void testIterate() throws Exception { createArtistsDataSet(); SelectQuery<Artist> q1 = new SelectQuery<Artist>(Artist.class); - + final int[] count = new int[1]; - + context.iterate(q1, new ResultIteratorCallback<Artist>() { @Override @@ -636,235 +635,225 @@ public class DataContextIT extends ServerCase { count[0]++; } }); - - assertEquals(7, count[0]); + + assertEquals(7, count[0]); + } + + @Test + public void testIterateDataRows() throws Exception { + + createArtistsDataSet(); + + SelectQuery<DataRow> q1 = SelectQuery.dataRowQuery(Artist.class, null); + final int[] count = new int[1]; + + context.iterate(q1, new ResultIteratorCallback<DataRow>() { + + @Override + public void next(DataRow object) { + assertNotNull(object.get("ARTIST_ID")); + count[0]++; + } + }); + + assertEquals(7, count[0]); + } + + @Test + public void testIterator() throws Exception { + + createArtistsDataSet(); + + SelectQuery<Artist> q1 = new SelectQuery<Artist>(Artist.class); + + ResultIterator<Artist> it = context.iterator(q1); + try { + int count = 0; + + for (Artist a : it) { + count++; + } + + assertEquals(7, count); + } finally { + it.close(); + } + } + + @Test + public void testBatchIterator() throws Exception { + createLargeArtistsDataSet(); + + SelectQuery<Artist> q1 = new SelectQuery<Artist>(Artist.class); + ResultBatchIterator<Artist> it = context.batchIterator(q1, 5); + + try { + int count = 0; + + for (List<Artist> artistList : it) { + count++; + assertEquals(5, artistList.size()); + } + + assertEquals(4, count); + } finally { + it.close(); + } + } + + @Test + public void testPerformIteratedQuery1() throws Exception { + + createArtistsDataSet(); + + SelectQuery<Artist> q1 = new SelectQuery<Artist>(Artist.class); + ResultIterator<?> it = context.performIteratedQuery(q1); + + try { + int count = 0; + while (it.hasNextRow()) { + it.nextRow(); + count++; + } + + assertEquals(7, count); + } finally { + it.close(); + } + } + + @Test + public void testPerformIteratedQuery2() throws Exception { + createArtistsAndPaintingsDataSet(); + + ResultIterator<?> it = context.performIteratedQuery(SelectQuery.query(Artist.class)); + + try { + while (it.hasNextRow()) { + DataRow row = (DataRow) it.nextRow(); + + // try instantiating an object and fetching its relationships + Artist artist = context.objectFromDataRow(Artist.class, row); + List<?> paintings = artist.getPaintingArray(); + assertNotNull(paintings); + assertEquals("Expected one painting for artist: " + artist, 1, paintings.size()); + } + } finally { + it.close(); + } + } + + /** + * Tests that hasChanges performs correctly when an object is "modified" and + * the property is simply set to the same value (an unreal modification) + */ + @Test + public void testHasChangesPhantom() { + + String artistName = "ArtistName"; + Artist artist = (Artist) context.newObject("Artist"); + artist.setArtistName(artistName); + context.commitChanges(); + + // Set again to *exactly* the same value + artist.setArtistName(artistName); + + // note that since 1.2 the polciy is for hasChanges to return true for + // phantom + // modifications, as there is no way to detect some more subtle + // modifications like + // a change of the master related object, until we actually create the + // PKs + assertTrue(context.hasChanges()); + } + + /** + * Tests that hasChanges performs correctly when an object is "modified" and + * the property is simply set to the same value (an unreal modification) + */ + @Test + public void testHasChangesRealModify() { + Artist artist = (Artist) context.newObject("Artist"); + artist.setArtistName("ArtistName"); + context.commitChanges(); + + artist.setArtistName("Something different"); + assertTrue(context.hasChanges()); + } + + @Test + public void testInvalidateObjects_Vararg() throws Exception { + + DataRow row = new DataRow(10); + row.put("ARTIST_ID", new Integer(1)); + row.put("ARTIST_NAME", "ArtistXYZ"); + row.put("DATE_OF_BIRTH", new Date()); + DataObject object = context.objectFromDataRow(Artist.class, row); + ObjectId oid = object.getObjectId(); + + // insert object into the ObjectStore + context.getObjectStore().registerNode(oid, object); + + assertSame(object, context.getObjectStore().getNode(oid)); + assertNotNull(context.getObjectStore().getCachedSnapshot(oid)); + + context.invalidateObjects(object); + + assertSame(oid, object.getObjectId()); + assertNull(context.getObjectStore().getCachedSnapshot(oid)); + assertSame(object, context.getObjectStore().getNode(oid)); + } + + @Test + public void testInvalidateObjects() throws Exception { + + DataRow row = new DataRow(10); + row.put("ARTIST_ID", new Integer(1)); + row.put("ARTIST_NAME", "ArtistXYZ"); + row.put("DATE_OF_BIRTH", new Date()); + DataObject object = context.objectFromDataRow(Artist.class, row); + ObjectId oid = object.getObjectId(); + + // insert object into the ObjectStore + context.getObjectStore().registerNode(oid, object); + + assertSame(object, context.getObjectStore().getNode(oid)); + assertNotNull(context.getObjectStore().getCachedSnapshot(oid)); + + context.invalidateObjects(Collections.singleton(object)); + + assertSame(oid, object.getObjectId()); + assertNull(context.getObjectStore().getCachedSnapshot(oid)); + assertSame(object, context.getObjectStore().getNode(oid)); + } + + @Test + public void testBeforeHollowDeleteShouldChangeStateToCommited() throws Exception { + createSingleArtistDataSet(); + + Artist hollow = Cayenne.objectForPK(context, Artist.class, 33001); + context.invalidateObjects(hollow); + assertEquals(PersistenceState.HOLLOW, hollow.getPersistenceState()); + + // testing this... + context.deleteObjects(hollow); + assertSame(hollow, context.getGraphManager().getNode(new ObjectId("Artist", "ARTIST_ID", 33001))); + assertEquals("artist1", hollow.getArtistName()); + + assertEquals(PersistenceState.DELETED, hollow.getPersistenceState()); + } + + @Test + public void testCommitUnchangedInsert() throws Exception { + + // see CAY-1444 - reproducible on DB's that support auto incremented PK + + NullTestEntity newObject = context.newObject(NullTestEntity.class); + + assertTrue(context.hasChanges()); + context.commitChanges(); + assertFalse(context.hasChanges()); + + assertEquals(PersistenceState.COMMITTED, newObject.getPersistenceState()); } - - @Test - public void testIterateDataRows() throws Exception { - - createArtistsDataSet(); - - SelectQuery<DataRow> q1 = SelectQuery.dataRowQuery(Artist.class, null); - final int[] count = new int[1]; - - context.iterate(q1, new ResultIteratorCallback<DataRow>() { - - @Override - public void next(DataRow object) { - assertNotNull(object.get("ARTIST_ID")); - count[0]++; - } - }); - - assertEquals(7, count[0]); - } - - @Test - public void testIterator() throws Exception { - - createArtistsDataSet(); - - SelectQuery<Artist> q1 = new SelectQuery<Artist>(Artist.class); - - ResultIterator<Artist> it = context.iterator(q1); - try { - int count = 0; - - for (Artist a : it) { - count++; - } - - assertEquals(7, count); - } finally { - it.close(); - } - } - - @Test - public void testBatchIterator() throws Exception { - createLargeArtistsDataSet(); - - SelectQuery<Artist> q1 = new SelectQuery<Artist>(Artist.class); - ResultBatchIterator<Artist> it = context.batchIterator(q1, 5); - - try { - int count = 0; - - for (List<Artist> artistList : it) { - count++; - assertEquals(5, artistList.size()); - } - - assertEquals(4, count); - } finally { - it.close(); - } - } - - @Test - public void testPerformIteratedQuery1() throws Exception { - - createArtistsDataSet(); - - SelectQuery<Artist> q1 = new SelectQuery<Artist>(Artist.class); - ResultIterator<?> it = context.performIteratedQuery(q1); - - try { - int count = 0; - while (it.hasNextRow()) { - it.nextRow(); - count++; - } - - assertEquals(7, count); - } finally { - it.close(); - } - } - - @Test - public void testPerformIteratedQuery2() throws Exception { - createArtistsAndPaintingsDataSet(); - - ResultIterator it = context.performIteratedQuery(new SelectQuery(Artist.class)); - - // just for this test increase pool size - changeMaxConnections(1); - - try { - while (it.hasNextRow()) { - DataRow row = (DataRow) it.nextRow(); - - // try instantiating an object and fetching its relationships - Artist artist = context.objectFromDataRow(Artist.class, row); - List<?> paintings = artist.getPaintingArray(); - assertNotNull(paintings); - assertEquals("Expected one painting for artist: " + artist, 1, paintings.size()); - } - } finally { - // change allowed connections back - changeMaxConnections(-1); - it.close(); - } - } - - /** - * Tests that hasChanges performs correctly when an object is "modified" and - * the property is simply set to the same value (an unreal modification) - */ - @Test - public void testHasChangesPhantom() { - - String artistName = "ArtistName"; - Artist artist = (Artist) context.newObject("Artist"); - artist.setArtistName(artistName); - context.commitChanges(); - - // Set again to *exactly* the same value - artist.setArtistName(artistName); - - // note that since 1.2 the polciy is for hasChanges to return true for - // phantom - // modifications, as there is no way to detect some more subtle - // modifications like - // a change of the master related object, until we actually create the - // PKs - assertTrue(context.hasChanges()); - } - - /** - * Tests that hasChanges performs correctly when an object is "modified" and - * the property is simply set to the same value (an unreal modification) - */ - @Test - public void testHasChangesRealModify() { - Artist artist = (Artist) context.newObject("Artist"); - artist.setArtistName("ArtistName"); - context.commitChanges(); - - artist.setArtistName("Something different"); - assertTrue(context.hasChanges()); - } - - @Test - public void testInvalidateObjects_Vararg() throws Exception { - - DataRow row = new DataRow(10); - row.put("ARTIST_ID", new Integer(1)); - row.put("ARTIST_NAME", "ArtistXYZ"); - row.put("DATE_OF_BIRTH", new Date()); - DataObject object = context.objectFromDataRow(Artist.class, row); - ObjectId oid = object.getObjectId(); - - // insert object into the ObjectStore - context.getObjectStore().registerNode(oid, object); - - assertSame(object, context.getObjectStore().getNode(oid)); - assertNotNull(context.getObjectStore().getCachedSnapshot(oid)); - - context.invalidateObjects(object); - - assertSame(oid, object.getObjectId()); - assertNull(context.getObjectStore().getCachedSnapshot(oid)); - assertSame(object, context.getObjectStore().getNode(oid)); - } - - @Test - public void testInvalidateObjects() throws Exception { - - DataRow row = new DataRow(10); - row.put("ARTIST_ID", new Integer(1)); - row.put("ARTIST_NAME", "ArtistXYZ"); - row.put("DATE_OF_BIRTH", new Date()); - DataObject object = context.objectFromDataRow(Artist.class, row); - ObjectId oid = object.getObjectId(); - - // insert object into the ObjectStore - context.getObjectStore().registerNode(oid, object); - - assertSame(object, context.getObjectStore().getNode(oid)); - assertNotNull(context.getObjectStore().getCachedSnapshot(oid)); - - context.invalidateObjects(Collections.singleton(object)); - - assertSame(oid, object.getObjectId()); - assertNull(context.getObjectStore().getCachedSnapshot(oid)); - assertSame(object, context.getObjectStore().getNode(oid)); - } - - @Test - public void testBeforeHollowDeleteShouldChangeStateToCommited() throws Exception { - createSingleArtistDataSet(); - - Artist hollow = Cayenne.objectForPK(context, Artist.class, 33001); - context.invalidateObjects(hollow); - assertEquals(PersistenceState.HOLLOW, hollow.getPersistenceState()); - - // testing this... - context.deleteObjects(hollow); - assertSame(hollow, context.getGraphManager().getNode(new ObjectId("Artist", "ARTIST_ID", 33001))); - assertEquals("artist1", hollow.getArtistName()); - - assertEquals(PersistenceState.DELETED, hollow.getPersistenceState()); - } - - @Test - public void testCommitUnchangedInsert() throws Exception { - - // see CAY-1444 - reproducible on DB's that support auto incremented PK - - NullTestEntity newObject = context.newObject(NullTestEntity.class); - - assertTrue(context.hasChanges()); - context.commitChanges(); - assertFalse(context.hasChanges()); - - assertEquals(PersistenceState.COMMITTED, newObject.getPersistenceState()); - } - - private void changeMaxConnections(int delta) { - PoolManager manager = (PoolManager) dataSourceFactory.getSharedDataSource(); - manager.setMaxConnections(manager.getMaxConnections() + delta); - } } http://git-wip-us.apache.org/repos/asf/cayenne/blob/8b54c052/cayenne-server/src/test/java/org/apache/cayenne/conn/BasePoolingDataSourceIT.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/test/java/org/apache/cayenne/conn/BasePoolingDataSourceIT.java b/cayenne-server/src/test/java/org/apache/cayenne/conn/BasePoolingDataSourceIT.java new file mode 100644 index 0000000..ef81d1a --- /dev/null +++ b/cayenne-server/src/test/java/org/apache/cayenne/conn/BasePoolingDataSourceIT.java @@ -0,0 +1,74 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ +package org.apache.cayenne.conn; + +import java.sql.Driver; +import java.sql.SQLException; + +import org.apache.cayenne.di.AdhocObjectFactory; +import org.apache.cayenne.di.Inject; +import org.apache.cayenne.log.JdbcEventLogger; +import org.apache.cayenne.unit.di.server.CayenneProjects; +import org.apache.cayenne.unit.di.server.ServerCase; +import org.apache.cayenne.unit.di.server.UseServerRuntime; +import org.junit.After; +import org.junit.Before; + +@UseServerRuntime(CayenneProjects.TESTMAP_PROJECT) +public class BasePoolingDataSourceIT extends ServerCase { + + @Inject + private DataSourceInfo dataSourceInfo; + + @Inject + private AdhocObjectFactory objectFactory; + + @Inject + private JdbcEventLogger logger; + + protected PoolingDataSource dataSource; + + @Before + public void before() throws SQLException { + + Driver driver = objectFactory.newInstance(Driver.class, dataSourceInfo.getJdbcDriver()); + DriverDataSource nonPooling = new DriverDataSource(driver, dataSourceInfo.getDataSourceUrl(), + dataSourceInfo.getUserName(), dataSourceInfo.getPassword()); + nonPooling.setLogger(logger); + + PoolingDataSourceParameters poolParameters = createParameters(); + this.dataSource = new PoolingDataSource(new PooledConnectionFactory(nonPooling), poolParameters); + } + + @After + public void after() throws SQLException { + if (dataSource != null) { + dataSource.beforeScopeEnd(); + } + } + + protected PoolingDataSourceParameters createParameters() { + PoolingDataSourceParameters poolParameters = new PoolingDataSourceParameters(); + poolParameters.setMinConnections(2); + poolParameters.setMaxConnections(3); + poolParameters.setMaxQueueWaitTime(1000); + return poolParameters; + } + +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/8b54c052/cayenne-server/src/test/java/org/apache/cayenne/conn/PoolManagerIT.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/test/java/org/apache/cayenne/conn/PoolManagerIT.java b/cayenne-server/src/test/java/org/apache/cayenne/conn/PoolManagerIT.java deleted file mode 100644 index 832470b..0000000 --- a/cayenne-server/src/test/java/org/apache/cayenne/conn/PoolManagerIT.java +++ /dev/null @@ -1,128 +0,0 @@ -/***************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - ****************************************************************/ - -package org.apache.cayenne.conn; - -import org.apache.cayenne.di.Inject; -import org.apache.cayenne.unit.di.server.CayenneProjects; -import org.apache.cayenne.unit.di.server.ServerCase; -import org.apache.cayenne.unit.di.server.UseServerRuntime; -import org.junit.Test; - -import java.sql.Connection; - -import static org.junit.Assert.assertEquals; - -@UseServerRuntime(CayenneProjects.TESTMAP_PROJECT) -public class PoolManagerIT extends ServerCase { - - @Inject - private DataSourceInfo dataSourceInfo; - - @Test - public void testDataSourceUrl() throws Exception { - String driverName = dataSourceInfo.getJdbcDriver(); - String url = dataSourceInfo.getDataSourceUrl(); - - PoolManager pm = new PoolManager(driverName, url, 0, 3, "", "") { - - @Override - protected void startMaintenanceThread() { - } - }; - assertEquals(url, pm.getDataSourceUrl()); - assertEquals(driverName, pm.getJdbcDriver()); - } - - @Test - public void testPassword() throws Exception { - PoolManager pm = new PoolManager(null, 0, 3, "", "b") { - - @Override - protected void startMaintenanceThread() { - } - }; - assertEquals("b", pm.getPassword()); - } - - @Test - public void testUserName() throws Exception { - PoolManager pm = new PoolManager(null, 0, 3, "a", "") { - - @Override - protected void startMaintenanceThread() { - } - }; - assertEquals("a", pm.getUserName()); - } - - @Test - public void testMinConnections() throws Exception { - PoolManager pm = new PoolManager(null, 0, 3, "", "") { - - @Override - protected void startMaintenanceThread() { - } - }; - assertEquals(0, pm.getMinConnections()); - } - - @Test - public void testMaxConnections() throws Exception { - PoolManager pm = new PoolManager(null, 0, 3, "", "") { - - @Override - protected void startMaintenanceThread() { - } - }; - assertEquals(3, pm.getMaxConnections()); - } - - @Test - public void testPooling() throws Exception { - - PoolManager pm = new PoolManager(dataSourceInfo.getJdbcDriver(), dataSourceInfo - .getDataSourceUrl(), 2, 3, dataSourceInfo.getUserName(), dataSourceInfo - .getPassword()); - - try { - assertEquals(0, pm.getCurrentlyInUse()); - assertEquals(2, pm.getCurrentlyUnused()); - - Connection c1 = pm.getConnection(); - assertEquals(1, pm.getCurrentlyInUse()); - assertEquals(1, pm.getCurrentlyUnused()); - - Connection c2 = pm.getConnection(); - assertEquals(2, pm.getCurrentlyInUse()); - assertEquals(0, pm.getCurrentlyUnused()); - - c1.close(); - assertEquals(1, pm.getCurrentlyInUse()); - assertEquals(1, pm.getCurrentlyUnused()); - - c2.close(); - assertEquals(0, pm.getCurrentlyInUse()); - assertEquals(2, pm.getCurrentlyUnused()); - } - finally { - pm.shutdown(); - } - } -} http://git-wip-us.apache.org/repos/asf/cayenne/blob/8b54c052/cayenne-server/src/test/java/org/apache/cayenne/conn/PooledConnectionImplTest.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/test/java/org/apache/cayenne/conn/PooledConnectionImplTest.java b/cayenne-server/src/test/java/org/apache/cayenne/conn/PooledConnectionImplTest.java index e829372..829ceb6 100644 --- a/cayenne-server/src/test/java/org/apache/cayenne/conn/PooledConnectionImplTest.java +++ b/cayenne-server/src/test/java/org/apache/cayenne/conn/PooledConnectionImplTest.java @@ -19,35 +19,49 @@ package org.apache.cayenne.conn; +import static org.mockito.Mockito.mock; + +import java.sql.SQLException; + +import javax.sql.ConnectionPoolDataSource; +import javax.sql.DataSource; + +import org.junit.Before; import org.junit.Test; public class PooledConnectionImplTest { - @Test - public void testConnectionErrorNotificationConcurrency() throws Exception { - // test a case when error notification is sent to connection - // that has been removed from the pool, but when pool is still a - // listener for its events. - PoolManager pm = new PoolManager(null, 0, 3, "", "") { - @Override - protected void startMaintenanceThread() {} - }; - PooledConnectionImpl con = new PooledConnectionImpl(); - con.addConnectionEventListener(pm); - con.connectionErrorNotification(new java.sql.SQLException("Bad SQL Exception..")); - } - - @Test - public void testConnectionClosedNotificationConcurrency() throws Exception { - // test a case when closed notification is sent to connection - // that has been removed from the pool, but when pool is still a - // listener for its events. - PoolManager pm = new PoolManager(null, 0, 3, "", "") { - @Override - protected void startMaintenanceThread() {} - }; - PooledConnectionImpl con = new PooledConnectionImpl(); - con.addConnectionEventListener(pm); - con.connectionClosedNotification(); - } + private PoolingDataSource dataSource; + + @Before + public void before() throws SQLException { + PoolingDataSourceParameters poolParameters = new PoolingDataSourceParameters(); + poolParameters.setMinConnections(0); + poolParameters.setMaxConnections(0); + poolParameters.setMaxQueueWaitTime(1000); + + this.dataSource = new PoolingDataSource(mock(ConnectionPoolDataSource.class), poolParameters); + } + + @Test + public void testConnectionErrorNotificationConcurrency() throws Exception { + // test a case when error notification is sent to connection + // that has been removed from the pool, but when pool is still a + // listener for its events. + + PooledConnectionImpl con = new PooledConnectionImpl(mock(DataSource.class), "un", "password"); + con.addConnectionEventListener(dataSource); + con.connectionErrorNotification(new java.sql.SQLException("Bad SQL Exception..")); + } + + @Test + public void testConnectionClosedNotificationConcurrency() throws Exception { + // test a case when closed notification is sent to connection + // that has been removed from the pool, but when pool is still a + // listener for its events. + PooledConnectionImpl con = new PooledConnectionImpl(mock(DataSource.class), "un", "password"); + con.addConnectionEventListener(dataSource); + con.connectionClosedNotification(); + } + } http://git-wip-us.apache.org/repos/asf/cayenne/blob/8b54c052/cayenne-server/src/test/java/org/apache/cayenne/conn/PoolingDataSourceIT.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/test/java/org/apache/cayenne/conn/PoolingDataSourceIT.java b/cayenne-server/src/test/java/org/apache/cayenne/conn/PoolingDataSourceIT.java new file mode 100644 index 0000000..d2814d9 --- /dev/null +++ b/cayenne-server/src/test/java/org/apache/cayenne/conn/PoolingDataSourceIT.java @@ -0,0 +1,72 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ + +package org.apache.cayenne.conn; + +import static org.junit.Assert.assertEquals; + +import java.sql.Connection; + +import org.apache.cayenne.unit.di.server.CayenneProjects; +import org.apache.cayenne.unit.di.server.UseServerRuntime; +import org.junit.Test; + +@UseServerRuntime(CayenneProjects.TESTMAP_PROJECT) +public class PoolingDataSourceIT extends BasePoolingDataSourceIT { + + @Test(expected = UnsupportedOperationException.class) + public void testGetConnectionWithUserName() throws Exception { + dataSource.getConnection("user", "password"); + } + + @Test + public void testGetConnection() throws Exception { + + assertEquals(0, dataSource.getCurrentlyInUse()); + assertEquals(2, dataSource.getCurrentlyUnused()); + + Connection c1 = dataSource.getConnection(); + assertEquals(1, dataSource.getCurrentlyInUse()); + assertEquals(1, dataSource.getCurrentlyUnused()); + + Connection c2 = dataSource.getConnection(); + assertEquals(2, dataSource.getCurrentlyInUse()); + assertEquals(0, dataSource.getCurrentlyUnused()); + + c1.close(); + assertEquals(1, dataSource.getCurrentlyInUse()); + assertEquals(1, dataSource.getCurrentlyUnused()); + + c2.close(); + assertEquals(0, dataSource.getCurrentlyInUse()); + assertEquals(2, dataSource.getCurrentlyUnused()); + } + + @Test + public void testGetConnection_BeforeScopeEnd() throws Exception { + + assertEquals(0, dataSource.getCurrentlyInUse()); + assertEquals(2, dataSource.getCurrentlyUnused()); + + dataSource.beforeScopeEnd(); + + assertEquals(0, dataSource.getCurrentlyInUse()); + assertEquals(0, dataSource.getCurrentlyUnused()); + } +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/8b54c052/cayenne-server/src/test/java/org/apache/cayenne/conn/PoolingDataSource_FailingValidationQueryIT.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/test/java/org/apache/cayenne/conn/PoolingDataSource_FailingValidationQueryIT.java b/cayenne-server/src/test/java/org/apache/cayenne/conn/PoolingDataSource_FailingValidationQueryIT.java new file mode 100644 index 0000000..d832ae5 --- /dev/null +++ b/cayenne-server/src/test/java/org/apache/cayenne/conn/PoolingDataSource_FailingValidationQueryIT.java @@ -0,0 +1,43 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ +package org.apache.cayenne.conn; + +import java.sql.Connection; +import java.sql.SQLException; + +import org.apache.cayenne.unit.di.server.CayenneProjects; +import org.apache.cayenne.unit.di.server.UseServerRuntime; +import org.junit.Test; + +@UseServerRuntime(CayenneProjects.TESTMAP_PROJECT) +public class PoolingDataSource_FailingValidationQueryIT extends BasePoolingDataSourceIT { + + @Override + protected PoolingDataSourceParameters createParameters() { + PoolingDataSourceParameters params = super.createParameters(); + params.setValidationQuery("SELECT count(1) FROM NO_SUCH_TABLE"); + return params; + } + + @Test(expected = SQLException.class) + public void testGetConnection_ValidationQuery() throws Exception { + Connection c1 = dataSource.getConnection(); + c1.close(); + } +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/8b54c052/cayenne-server/src/test/java/org/apache/cayenne/conn/PoolingDataSource_ValidationQueryIT.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/test/java/org/apache/cayenne/conn/PoolingDataSource_ValidationQueryIT.java b/cayenne-server/src/test/java/org/apache/cayenne/conn/PoolingDataSource_ValidationQueryIT.java new file mode 100644 index 0000000..45a5689 --- /dev/null +++ b/cayenne-server/src/test/java/org/apache/cayenne/conn/PoolingDataSource_ValidationQueryIT.java @@ -0,0 +1,55 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ +package org.apache.cayenne.conn; + +import static org.junit.Assert.assertEquals; + +import java.sql.Connection; + +import org.apache.cayenne.unit.di.server.CayenneProjects; +import org.apache.cayenne.unit.di.server.UseServerRuntime; +import org.junit.Test; + +@UseServerRuntime(CayenneProjects.TESTMAP_PROJECT) +public class PoolingDataSource_ValidationQueryIT extends BasePoolingDataSourceIT { + + @Override + protected PoolingDataSourceParameters createParameters() { + PoolingDataSourceParameters params = super.createParameters(); + params.setValidationQuery("SELECT count(1) FROM ARTIST"); + return params; + } + + @Test + public void testGetConnection_ValidationQuery() throws Exception { + + assertEquals(0, dataSource.getCurrentlyInUse()); + assertEquals(2, dataSource.getCurrentlyUnused()); + + // TODO: we are not testing much here... we really need to mock + // validation query execution somehow and verify that it is taken into + // account + + Connection c1 = dataSource.getConnection(); + assertEquals(1, dataSource.getCurrentlyInUse()); + assertEquals(1, dataSource.getCurrentlyUnused()); + + c1.close(); + } +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/8b54c052/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseDataSourceFactory.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseDataSourceFactory.java b/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseDataSourceFactory.java index 6859f2f..43ef5f3 100644 --- a/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseDataSourceFactory.java +++ b/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseDataSourceFactory.java @@ -18,7 +18,6 @@ ****************************************************************/ package org.apache.cayenne.unit.di.server; -import java.sql.SQLException; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; @@ -27,70 +26,54 @@ import java.util.Set; import javax.sql.DataSource; +import org.apache.cayenne.conn.DataSourceBuilder; import org.apache.cayenne.conn.DataSourceInfo; -import org.apache.cayenne.conn.PoolDataSource; -import org.apache.cayenne.conn.PoolManager; +import org.apache.cayenne.di.AdhocObjectFactory; import org.apache.cayenne.di.Inject; +import org.apache.cayenne.log.JdbcEventLogger; -public class ServerCaseDataSourceFactory { +public class ServerCaseDataSourceFactory { - private DataSource sharedDataSource; - private DataSourceInfo dataSourceInfo; - private Map<String, DataSource> dataSources; - private Set<String> mapsWithDedicatedDataSource; + private DataSource sharedDataSource; + private DataSourceInfo dataSourceInfo; + private Map<String, DataSource> dataSources; + private Set<String> mapsWithDedicatedDataSource; + private AdhocObjectFactory objectFactory; + private JdbcEventLogger logger; - public ServerCaseDataSourceFactory(@Inject DataSourceInfo dataSourceInfo) { + public ServerCaseDataSourceFactory(@Inject DataSourceInfo dataSourceInfo, @Inject AdhocObjectFactory objectFactory, + @Inject JdbcEventLogger logger) { - this.dataSourceInfo = dataSourceInfo; - this.dataSources = new HashMap<String, DataSource>(); - this.mapsWithDedicatedDataSource = new HashSet<String>(Arrays.asList( - "map-db1", - "map-db2")); + this.logger = logger; + this.objectFactory = objectFactory; + this.dataSourceInfo = dataSourceInfo; + this.dataSources = new HashMap<String, DataSource>(); + this.mapsWithDedicatedDataSource = new HashSet<String>(Arrays.asList("map-db1", "map-db2")); - this.sharedDataSource = createDataSource(); - } + this.sharedDataSource = createDataSource(); + } - public DataSource getSharedDataSource() { - return sharedDataSource; - } + public DataSource getSharedDataSource() { + return sharedDataSource; + } - public DataSource getDataSource(String dataMapName) { - DataSource ds = dataSources.get(dataMapName); - if (ds == null) { + public DataSource getDataSource(String dataMapName) { + DataSource ds = dataSources.get(dataMapName); + if (ds == null) { - ds = mapsWithDedicatedDataSource.contains(dataMapName) - ? createDataSource() - : sharedDataSource; + ds = mapsWithDedicatedDataSource.contains(dataMapName) ? createDataSource() : sharedDataSource; - dataSources.put(dataMapName, ds); - } + dataSources.put(dataMapName, ds); + } - return ds; - } + return ds; + } - private DataSource createDataSource() { - try { - PoolDataSource poolDS = new PoolDataSource( - dataSourceInfo.getJdbcDriver(), - dataSourceInfo.getDataSourceUrl()); - return new PoolManager( - poolDS, - dataSourceInfo.getMinConnections(), - dataSourceInfo.getMaxConnections(), - dataSourceInfo.getUserName(), - dataSourceInfo.getPassword(), PoolManager.MAX_QUEUE_WAIT_DEFAULT) { - - @Override - public void shutdown() throws SQLException { - // noop - make sure we are not shutdown by the test scope, but at the - // same time PoolManager methods are exposed (so we can't wrap - // PoolManager) - } - }; - } - catch (Exception ex) { - throw new RuntimeException("Can not create shared data source.", ex); - } - } + private DataSource createDataSource() { + return DataSourceBuilder.builder(objectFactory, logger).driver(dataSourceInfo.getJdbcDriver()) + .url(dataSourceInfo.getDataSourceUrl()).userName(dataSourceInfo.getUserName()) + .password(dataSourceInfo.getPassword()).minConnections(dataSourceInfo.getMinConnections()) + .maxConnections(dataSourceInfo.getMaxConnections()).build(); + } } http://git-wip-us.apache.org/repos/asf/cayenne/blob/8b54c052/docs/doc/src/main/resources/RELEASE-NOTES.txt ---------------------------------------------------------------------- diff --git a/docs/doc/src/main/resources/RELEASE-NOTES.txt b/docs/doc/src/main/resources/RELEASE-NOTES.txt index 2d270aa..fb1d0a8 100644 --- a/docs/doc/src/main/resources/RELEASE-NOTES.txt +++ b/docs/doc/src/main/resources/RELEASE-NOTES.txt @@ -21,6 +21,7 @@ CAY-2001 Saving a display state of Project CAY-2004 EJBQL: Support for ordering on aggregate expressions CAY-2005 Improving generated DISTINCT performance on PostgreSQL CAY-2007 Refactoring SelectTranslator for better extensibility +CAY-2008 Connection pool refactoring and validation query support in Cayenne DataSource Bug Fixes: