At line 13 changed 1 line. |
* [5] [[DAO Stuff] Setting up Unit Tests and DAO classes for basic CRUD |
* [5] [[DAO Layer] Setting up Unit Tests and DAO classes for basic CRUD |
At line 41 changed 1 line. |
;:''Rather than fill up this tutorial with large blocks of Java code, the necessary files are attached and linked to. Small code snippets are used where appropriate.'' |
;:''Rather than fill up this tutorial with large blocks of Java code, the necessary files are attached and linked to. Small code snippets are used where appropriate. You should be able to easily download the files by right-clicking on them and selecting "Save Target As...".'' |
At line 51 changed 1 line. |
The ''many-to-one'' relationship between __Entry__ and __Category__ can be established using XDoclet tags. Hibernate relationships can be established on either side of the relationship or bi-directionally. For this tutorial, this relationship will be maintained by an extra property and collection held by __Entry__. The list of possible categories for a weblog entry will eventually be represented as a drop-down on the UI. |
The ''many-to-one'' relationship between __Entry__ and __Category__ can be established using XDoclet tags. Hibernate relationships can be established on either side of the relationship or bi-directionally. For this tutorial, this relationship will be maintained by an extra property and collection held by __Entry__. The list of possible categories for a weblog entry will eventually be represented as a drop-down on the UI. Add the following code to your __Entry.java__ class. |
At line 84 changed 1 line. |
Modify the Weblog object and Entry object to represent the multiplicity of a weblog that can have many entries. This relationship is set on the Weblog class using a list. XDoclet tags are used to establish this relationship using a __bag__ as the Hibernate collection type. |
Now you'll the __Weblog__ object and __Entry__ object to represent the multiplicity of a weblog that can have many entries. This relationship is set on the Weblog class using a java.util.List. XDoclet tags are used to establish this relationship using a __bag__ as the Hibernate collection type. Add the following code to your __Weblog.java__ class. |
At line 106 changed 1 line. |
The Entry class is modified slightly to provide a placeholder for the relationships between Weblog and Entry. |
Modify the Entry class is so it contains a foreign key to it's parent __Weblog__ class. |
At line 126 changed 1 line. |
The Weblog system that we are developing allows one additional bit of functionality. A particular Weblog can have many Users. Basically the idea is of a shared weblog that is a place where many users can express themselves about a particular topic of interest. For this bit of functionality the User object will be modified to have a many-to-many relationship with Weblog. |
The Weblog system in this tutorial allows one additional bit of functionality. A particular Weblog can have many Users. Basically the idea is of a shared weblog that is a place where many users can express themselves about a particular topic of interest. For this bit of functionality the User object will be modified to have a many-to-many relationship with Weblog. |
At line 128 changed 1 line. |
Add the following ''users'' property and accessor methods to ''Weblog.java''. |
Add the following ''users'' property and accessor methods to __Weblog.java__. |
At line 169 changed 1 line. |
!![[DAO Stuff] [#5] |
!![[DAO Layer] [#5] |
At line 171 changed 1 line. |
In order to test that all of this works, you need to create some test classes, add some sample data, develop some DAO interfaces, and create hibernate DAO classes. |
In order to test that all of this works, you need to create some test classes, add some sample data, develop some DAO interfaces, and create Hibernate DAO classes. |
At line 175 changed 1 line. |
!WeblogDaoTest |
There are a number of ways to construct the DAO layer for this application. You could have a WeblogDAO that handles CRUD for all entities, or you could have separate DAOs for each entity. This tutorial uses the separate DAO approach because this seems to be the most common method used by AppFuse users. Personally, I tend to group my logical features into a single DAO with many methods. Download the following three test classes and put them in your ''test/dao/**/dao'' directory. |
At line 177 changed 1 line. |
Let's start with ''WeblogDaoTest.java'' class. Create this class in ''test/dao/**/dao'' and fill it with the following code. |
* [Download WeblogDaoTest.java|WeblogDAOTest.java] |
* [Download EntryDaoTest.java|EntryDAOTest.java] |
* [Download CategoryDaoTest.java|CategoryDAOTest.java] |
At line 179 removed 241 lines. |
[{Java2HtmlPlugin |
|
package org.appfuse.dao; |
|
import java.util.Date; |
import java.util.List; |
|
import org.appfuse.model.Weblog; |
import org.appfuse.model.User; |
import org.springframework.dao.DataAccessException; |
|
public class WeblogDaoTest extends BaseDaoTestCase { |
|
private WeblogDAO wldao = null; |
private Weblog weblog = null; |
private UserDAO udao = null; |
private User user = null; |
|
protected void setUp() throws Exception { |
super.setUp(); |
wldao = (WeblogDAO) ctx.getBean("weblogDAO"); |
udao = (UserDAO) ctx.getBean("userDAO"); |
|
} |
|
protected void tearDown() throws Exception { |
super.tearDown(); |
wldao = null; |
} |
|
public void testGetWeblog() throws Exception { |
weblog = wldao.getWeblog(new Long(1)); |
|
assertNotNull(weblog); |
assertEquals(2, weblog.getUsers().size()); |
} |
|
public void testUpdateWeblog() throws Exception { |
weblog = wldao.getWeblog(new Long(2)); |
weblog.setBlogTitle("Testing Update Weblog"); |
wldao.saveWeblog(weblog); |
assertEquals("Testing Update Weblog", weblog.getBlogTitle()); |
} |
|
public void testAddWeblogUser() throws Exception { |
weblog = wldao.getWeblog(new Long(2)); |
|
assertEquals(1, weblog.getUsers().size()); |
|
user = udao.getUser("tomcat"); |
weblog.addUser(user); |
wldao.saveWeblog(weblog); |
|
assertEquals(2, weblog.getUsers().size()); |
|
// add the same user twice - should result in no additional user |
weblog.addUser(user); |
wldao.saveWeblog(weblog); |
|
assertEquals("more than 2 of the same users", 2, weblog.getUsers().size()); |
|
weblog.getUsers().remove(user); |
wldao.saveWeblog(weblog); |
|
assertEquals(1, weblog.getUsers().size()); |
} |
|
public void testAddAndRemoveWeblog() throws Exception { |
weblog = new Weblog(); |
weblog.setBlogTitle("A new test for adding and then deleting a weblog"); |
weblog.setDateCreated(new Date(2005-04-17)); |
weblog.setUsername("Cartman"); |
|
wldao.saveWeblog(weblog); |
|
assertNotNull(weblog.getBlogTitle()); |
assertEquals("Cartman", weblog.getUsername()); |
|
wldao.removeWeblog(weblog.getWeblogId()); |
|
try { |
weblog = wldao.getWeblog(weblog.getWeblogId()); |
fail("saveWeblog didn't throw DataAccessException"); |
} catch (DataAccessException d) { |
assertNotNull(d); |
} |
} |
|
public void testGetEntries() throws Exception { |
List list = wldao.getEntries(new Long(1)); |
assertTrue(list.size() > 0); |
|
} |
|
|
|
|
|
|
} |
}] |
|
!EntryDaoTest |
|
Now, create an ''EntryDaoTest.java'' class. Again, create this class in ''test/dao/**/dao'' and fill it with the following code. |
|
[{Java2HtmlPlugin |
|
package org.appfuse.dao; |
|
import java.sql.Timestamp; |
|
import org.appfuse.model.Entry; |
import org.springframework.dao.DataAccessException; |
|
public class EntryDaoTest extends BaseDaoTestCase { |
|
private EntryDAO edao = null; |
private Entry entry = null; |
|
protected void setUp() throws Exception { |
super.setUp(); |
edao = (EntryDAO) ctx.getBean("entryDAO"); |
} |
|
protected void tearDown() throws Exception { |
super.tearDown(); |
edao = null; |
} |
|
public void testGetEntry() throws Exception { |
entry = edao.getEntry(new Long(1)); |
|
assertNotNull(entry); |
assertEquals("Testing", entry.getText()); |
} |
|
public void testUpdateEntry() throws Exception { |
entry = edao.getEntry(new Long(2)); |
entry.setText("Testing update entry"); |
entry.setCategoryId(new Long(2)); |
edao.saveEntry(entry); |
|
assertEquals("Testing update entry", entry.getText()); |
} |
|
public void testAddAndRemoveEntry() throws Exception { |
entry = new Entry(); |
entry.setText("Testing add a new entry"); |
entry.setTimeCreated(new Timestamp(2004-04-02)); |
entry.setCategoryId(new Long(3)); |
entry.setWeblogId(new Long(1)); |
|
|
edao.saveEntry(entry); |
|
assertNotNull(entry.getText()); |
assertEquals("Testing add a new entry", entry.getText()); |
|
edao.removeEntry(entry.getEntryId()); |
|
try { |
entry = edao.getEntry(entry.getEntryId()); |
fail("saveEntry didn't throw DataAccessException"); |
} catch (DataAccessException d) { |
assertNotNull(d); |
} |
|
} |
|
} |
|
}] |
|
!CategoryDaoTest |
|
Next, create an ''CategoryDaoTest.java'' class in ''test/dao/**/dao''. |
|
[{Java2HtmlPlugin |
|
package org.appfuse.dao; |
|
import org.appfuse.model.Category; |
import org.springframework.dao.DataAccessException; |
|
public class CategoryDaoTest extends BaseDaoTestCase { |
|
private CategoryDAO catdao = null; |
private Category category = null; |
|
protected void setUp() throws Exception { |
super.setUp(); |
catdao = (CategoryDAO) ctx.getBean("categoryDAO"); |
} |
|
protected void tearDown() throws Exception { |
super.tearDown(); |
catdao = null; |
} |
|
public void testGetCategory() throws Exception { |
category = catdao.getCategory(new Long(1)); |
|
assertNotNull(category); |
assertEquals("Struts v. Spring MVC", category.getCategoryName()); |
} |
|
public void testUpdateCategory() throws Exception { |
category = catdao.getCategory(new Long(2)); |
category.setCategoryName("Testing update category"); |
catdao.saveCategory(category); |
|
assertEquals("Testing update category", category.getCategoryName()); |
} |
|
public void testAddAndRemoveCategory() throws Exception { |
category = new Category(); |
category.setCategoryName("Spaceman Biff"); |
category.setCategoryDescription("Paying homage to Calvin's alter ego!"); |
|
catdao.saveCategory(category); |
|
assertNotNull(category.getCategoryDescription()); |
assertEquals("Spaceman Biff", category.getCategoryName()); |
|
catdao.removeCategory(category.getCategoryId()); |
|
try { |
category = catdao.getCategory(category.getCategoryId()); |
fail("saveCategory didn't throw DataAccessException"); |
} catch (DataAccessException d) { |
assertNotNull(d); |
|
} |
|
} |
|
} |
|
}] |
|
At line 424 changed 82 lines. |
<table name='weblog'> |
<column>weblog_id</column> |
<column>blog_title</column> |
<column>date_created</column> |
<column>username</column> |
<row> |
<value>1</value> |
<value><![CDATA[Sponge Bob is Cool]]></value> |
<value>2004-03-31</value> |
<value>tomcat</value> |
</row> |
<row> |
<value>2</value> |
<value><![CDATA[Java Development = Fun]]></value> |
<value>2005-01-05</value> |
<value>mraible</value> |
</row> |
</table> |
<table name='weblog_user'> |
<column>weblog_id</column> |
<column>username</column> |
<row> |
<value>1</value> |
<value>tomcat</value> |
</row> |
<row> |
<value>1</value> |
<value>mraible</value> |
</row> |
<row> |
<value>2</value> |
<value>mraible</value> |
</row> |
</table> |
<table name='category'> |
<column>category_id</column> |
<column>category_name</column> |
<column>category_description</column> |
<row> |
<value>1</value> |
<value><![CDATA[Struts v. Spring MVC]]></value> |
<value><![CDATA[Comparing implementations of the MVC Design Pattern]]></value> |
</row> |
<row> |
<value>2</value> |
<value><![CDATA[Cycling Notes]]></value> |
<value><![CDATA[All about cycling in the US.]]></value> |
</row> |
<row> |
<value>3</value> |
<value><![CDATA[Cyclocross]]></value> |
<value><![CDATA[Bog Trotters Unite!]]></value> |
</row> |
</table> |
<table name='entry'> |
<column>entry_id</column> |
<column>entry_text</column> |
<column>time_created</column> |
<column>weblog_id</column> |
<column>category_id</column> |
<row> |
<value>1</value> |
<value><![CDATA[Testing]]></value> |
<value>2005-04-11</value> |
<value>1</value> |
<value>1</value> |
</row> |
<row> |
<value>2</value> |
<value><![CDATA[Test Value]]></value> |
<value>2005-04-12</value> |
<value>1</value> |
<value>1</value> |
</row> |
<row> |
<value>3</value> |
<value><![CDATA[Test Value 3]]></value> |
<value>2005-04-12</value> |
<value>2</value> |
<value>3</value> |
</row> |
</table> |
<table name='weblog'> |
<column>weblog_id</column> |
<column>blog_title</column> |
<column>date_created</column> |
<column>username</column> |
<row> |
<value>1</value> |
<value><![CDATA[Sponge Bob is Cool]]></value> |
<value>2004-03-31</value> |
<value>tomcat</value> |
</row> |
<row> |
<value>2</value> |
<value><![CDATA[Java Development = Fun]]></value> |
<value>2005-01-05</value> |
<value>mraible</value> |
</row> |
</table> |
<table name='weblog_user'> |
<column>weblog_id</column> |
<column>username</column> |
<row> |
<value>1</value> |
<value>tomcat</value> |
</row> |
<row> |
<value>1</value> |
<value>mraible</value> |
</row> |
<row> |
<value>2</value> |
<value>mraible</value> |
</row> |
</table> |
<table name='category'> |
<column>category_id</column> |
<column>category_name</column> |
<column>category_description</column> |
<row> |
<value>1</value> |
<value><![CDATA[Struts v. Spring MVC]]></value> |
<value><![CDATA[Comparing implementations of the MVC Design Pattern]]></value> |
</row> |
<row> |
<value>2</value> |
<value><![CDATA[Cycling Notes]]></value> |
<value><![CDATA[All about cycling in the US.]]></value> |
</row> |
<row> |
<value>3</value> |
<value><![CDATA[Cyclocross]]></value> |
<value><![CDATA[Bog Trotters Unite!]]></value> |
</row> |
</table> |
<table name='entry'> |
<column>entry_id</column> |
<column>entry_text</column> |
<column>time_created</column> |
<column>weblog_id</column> |
<column>category_id</column> |
<row> |
<value>1</value> |
<value><![CDATA[Testing]]></value> |
<value>2005-04-11</value> |
<value>1</value> |
<value>1</value> |
</row> |
<row> |
<value>2</value> |
<value><![CDATA[Test Value]]></value> |
<value>2005-04-12</value> |
<value>1</value> |
<value>1</value> |
</row> |
<row> |
<value>3</value> |
<value><![CDATA[Test Value 3]]></value> |
<value>2005-04-12</value> |
<value>2</value> |
<value>3</value> |
</row> |
</table> |
At line 511 changed 1 line. |
Before any of these tests will compile, you need to create the DAO interfaces and then implementations. |
Before any of these tests will compile, you need to create the DAO interfaces and their implementations. |
At line 539 removed 1 line. |
|
At line 543 changed 6 lines. |
|
public Entry getEntry(Long entryId); |
public List getEntries(Entry entry); |
public void saveEntry(Entry entry); |
public void removeEntry(Long entryId); |
|
public Entry getEntry(Long entryId); |
public List getEntries(Entry entry); |
public void saveEntry(Entry entry); |
public void removeEntry(Long entryId); |
At line 550 removed 2 lines. |
|
|
At line 561 removed 1 line. |
|
At line 565 changed 5 lines. |
public Category getCategory(Long categoryId); |
public List getCategories(Category category); |
public void saveCategory(Category category); |
public void removeCategory(Long categoryId); |
|
public Category getCategory(Long categoryId); |
public List getCategories(Category category); |
public void saveCategory(Category category); |
public void removeCategory(Long categoryId); |
At line 592 changed 3 lines. |
public Weblog getWeblog(Long weblogId) { |
Weblog weblog = (Weblog) getHibernateTemplate().get(Weblog.class, |
weblogId); |
public Weblog getWeblog(Long weblogId) { |
Weblog weblog = (Weblog) getHibernateTemplate().get(Weblog.class, |
weblogId); |
At line 596 changed 4 lines. |
if (weblog == null) { |
log.warn("uh oh, weblog '" + weblogId + "' not found..."); |
throw new ObjectRetrievalFailureException(Weblog.class, weblogId); |
} |
if (weblog == null) { |
log.warn("uh oh, weblog '" + weblogId + "' not found..."); |
throw new ObjectRetrievalFailureException(Weblog.class, weblogId); |
} |
At line 601 changed 2 lines. |
return weblog; |
} |
return weblog; |
} |
At line 604 changed 3 lines. |
public List getWeblogs(Weblog weblog) { |
return getHibernateTemplate().find( |
"from Weblog wl order by upper(wl.blogTitle)"); |
public List getWeblogs(Weblog weblog) { |
return getHibernateTemplate().find( |
"from Weblog wl order by upper(wl.blogTitle)"); |
} |
At line 608 changed 1 line. |
} |
public void saveWeblog(final Weblog weblog) { |
getHibernateTemplate().saveOrUpdate(weblog); |
} |
At line 610 changed 3 lines. |
public void saveWeblog(final Weblog weblog) { |
getHibernateTemplate().saveOrUpdate(weblog); |
} |
public void removeWeblog(Long weblogId) { |
getHibernateTemplate().delete(getWeblog(weblogId)); |
} |
At line 614 changed 9 lines. |
public void removeWeblog(Long weblogId) { |
getHibernateTemplate().delete(getWeblog(weblogId)); |
} |
|
public List getEntries(Long weblogId) { |
return getHibernateTemplate().find("from Entry e where e.weblogId=?", |
weblogId); |
} |
|
public List getEntries(Long weblogId) { |
return getHibernateTemplate().find("from Entry e where e.weblogId=?", |
weblogId); |
} |
At line 624 removed 2 lines. |
|
|
At line 641 changed 3 lines. |
|
public Entry getEntry(Long entryId) { |
Entry entry = (Entry) getHibernateTemplate().get(Entry.class, entryId); |
|
public Entry getEntry(Long entryId) { |
Entry entry = (Entry) getHibernateTemplate().get(Entry.class, entryId); |
At line 664 removed 1 line. |
|
At line 682 changed 3 lines. |
|
public Category getCategory(Long categoryId) { |
Category category = (Category) getHibernateTemplate().get(Category.class, categoryId); |
|
public Category getCategory(Long categoryId) { |
Category category = (Category) getHibernateTemplate().get(Category.class, categoryId); |
At line 705 removed 1 line. |
|
At line 707 removed 1 line. |
|
At line 712 changed 1 line. |
Modifications need to be made in applicationContext-hibernate.xml for the 3 new entities you created in this tutorial. |
Modifications need to be made in __src/org/appfuse/dao/hibernate/applicationContext-hibernate.xml__ for the 3 new entities you created in this tutorial. |
At line 728 removed 1 line. |
|
At line 750 changed 1 line. |
After making these changes, you should be able to run __ant test-dao -Dtestcase=WeblogDAO__ for example. All of the tests should pass successfully. |
After making these changes, you should be able to run __ant test-dao -Dtestcase=WeblogDAO__. All of the tests should pass successfully. |