At line 2 changed 1 line. |
This is a tutorial to show how to create and manage Hibernate relationships within [AppFuse]. This tutorial was written for AppFuse 1.8 and the AppGen pieces may not work with previous versions. |
This is a tutorial to show how to create and manage Hibernate relationships within [AppFuse]. This tutorial was written using AppFuse 1.8.2. All of the code for this tutorial is downloadable at [http://static.appfuse.org/downloads/appfuse-hr.zip]. |
At line 4 changed 1 line. |
;:''For further details about the specifics regarding creating entities, XDoclet tags for Hibernate, DAO development, etc., please refer to [Creating new DAOs and Objects in AppFuse|CreateDAO].'' |
;:''For further details about the specifics regarding creating objects, XDoclet tags for Hibernate, DAO development, etc., please refer to [Creating new DAOs and Objects in AppFuse|CreateDAO].'' |
At line 6 added 2 lines. |
%%note __NOTE:__ Copying the Java code in this tutorials [doesn't work in Firefox|http://raibledesigns.com/page/rd?anchor=java2html_plugin_for_jspwiki_causes]. A workaround is to CTRL+Click (Command+Click on OS X) the code block and then copy it.%% |
|
At line 7 changed 2 lines. |
* [1] Create Weblog.java, Entry.java and add XDoclet tags |
* [2] [[Many-to-One] Create a new Category object and modify Entry.java to use it |
* [1] Create Weblog.java, Entry.java and Category.java domain objects |
* [2] [[Many-to-Many] A Weblogs can have many Users, a User can have many Weblogs |
At line 10 changed 3 lines. |
* [4] [[Many-to-Many] Shared Weblogs are possible for multiple Users |
* [5] Lazy-Loading Issues |
* [6] Managing relationships and indexed properties in the UI |
* [4] [[Many-to-One] A Category object can be assigned to many entries |
At line 15 removed 2 lines. |
For our purposes, the Weblog entity is a list of available weblogs. A Weblog object has the following properties an id, a username (for the user who created the blog), a dateCreated, and a blogTitle. Every Entry object has an id, a text, and a timeCreated property. |
The first thing to do is create some objects to persist. Let's create both a "Weblog" object and an Entry object (in the src/dao/**/model directory). Basic XDoclet tags for these entities are show as well. |
At line 18 changed 1 line. |
[{Java2HtmlPlugin |
The ''Weblog'' object is used to indentify a person's blog. This class has the following properties: |
At line 20 changed 1 line. |
package org.appfuse.model; |
* weblogId |
* blogTitle |
* dateCreated |
At line 22 changed 1 line. |
import java.util.Date; |
The ''Entry'' object is used to contain a listing of a person's blog entries in their Weblog. This class contains the following properties: |
At line 24 changed 4 lines. |
import org.apache.commons.lang.builder.EqualsBuilder; |
import org.apache.commons.lang.builder.HashCodeBuilder; |
import org.apache.commons.lang.builder.ToStringBuilder; |
import org.apache.commons.lang.builder.ToStringStyle; |
* entryId |
* text |
* timeCreated |
At line 29 changed 4 lines. |
/** |
* @hibernate.class table="weblog" |
*/ |
public class Weblog extends BaseObject { |
%%note __NOTE:__ The primary keys are prefixed with their entity name to avoid confusion. I generally recommend using "id" for your entities, but wanted to make thing clearer in this tutorial.%% |
At line 34 changed 5 lines. |
private Long weblogId; |
private String username; |
private Date dateCreated; |
private String blogTitle; |
private Integer version; |
Below is a class diagram of these two objects, as well as the others you'll create in this tutorial. |
At line 40 changed 8 lines. |
/** |
* @return Returns the blogTitle. |
* |
* @hibernate.property column="blog_title" |
*/ |
public String getBlogTitle() { |
return blogTitle; |
} |
[ER-Diagram.jpg] |
At line 49 changed 7 lines. |
/** |
* @param blogTitle |
* The blogTitle to set. |
*/ |
public void setBlogTitle(String blogTitle) { |
this.blogTitle = blogTitle; |
} |
The first thing you need to do in this tutorial is these two object to persist. Create a __Weblog.java__ class and an __Entry.java__ class (in the src/dao/**/model directory). The necessary XDoclet tags for these entities is included on the ''getter'' method's javadoc. You can download these files using the links below. Note that javadocs have been eliminated for brevity. |
At line 57 changed 8 lines. |
/** |
* @return Returns the dateCreated. |
* |
* @hibernate.property column="date_created" |
*/ |
public Date getDateCreated() { |
return dateCreated; |
} |
* [Download Weblog.java|Weblog.java] |
* [Download Entry.java|Entry.java] |
At line 66 changed 7 lines. |
/** |
* @param dateCreated |
* The dateCreated to set. |
*/ |
public void setDateCreated(Date dateCreated) { |
this.dateCreated = dateCreated; |
} |
;:''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 74 changed 9 lines. |
/** |
* @return Returns the id. |
* |
* @hibernate.id column="weblog_id" generator-class="native" |
* unsaved-value="null" |
*/ |
public Long getWeblogId() { |
return weblogId; |
} |
Create a __Category.java__ object to act as an entity for persisting category information about weblog entries. Each category can have many entries. This class contains the following properties: |
At line 84 changed 7 lines. |
/** |
* @param id |
* The id to set. |
*/ |
public void setWeblogId(Long weblogId) { |
this.weblogId = weblogId; |
} |
* categoryId |
* name |
* description |
At line 92 changed 8 lines. |
/** |
* @return Returns the username. |
* |
* @hibernate.property column="username" |
*/ |
public String getUsername() { |
return username; |
} |
* [Download Category.java|Category.java] |
At line 101 changed 7 lines. |
/** |
* @param username |
* The username to set. |
*/ |
public void setUsername(String username) { |
this.username = username; |
} |
!Configure Spring |
At line 109 changed 8 lines. |
/** |
* @return Returns the version. |
* |
* @hibernate.version |
*/ |
public Integer getVersion() { |
return version; |
} |
Add the 3 new mapping files (that will be generated) to the "sessionFactory" bean's ''mappingResources'' property in __src/org/appfuse/dao/hibernate/applicationContext-hibernate.xml__. |
At line 118 removed 45 lines. |
/** |
* @param version |
* The version to set. |
*/ |
public void setVersion(Integer version) { |
this.version = version; |
} |
|
/** |
* @see java.lang.Object#equals(Object) |
*/ |
public boolean equals(Object object) { |
if (!(object instanceof Weblog)) { |
return false; |
} |
Weblog rhs = (Weblog) object; |
return new EqualsBuilder().append(this.blogTitle, rhs.blogTitle) |
.append(this.username, rhs.username).append(this.dateCreated, |
rhs.dateCreated).append(this.weblogId, rhs.weblogId).append( |
this.version, rhs.version).isEquals(); |
} |
|
/** |
* @see java.lang.Object#hashCode() |
*/ |
public int hashCode() { |
return new HashCodeBuilder(2066507029, -390167195).append( |
this.blogTitle).append(this.username).append(this.dateCreated) |
.append(this.weblogId).append(this.version).toHashCode(); |
} |
|
/** |
* @see java.lang.Object#toString() |
*/ |
public String toString() { |
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) |
.append("id", this.weblogId).append("version", this.version).append( |
"username", this.username).append("blogTitle", |
this.blogTitle).append("dateCreated", this.dateCreated) |
.toString(); |
} |
} |
|
}] |
|
At line 165 changed 129 lines. |
package org.appfuse.model; |
|
import java.util.Date; |
|
import org.apache.commons.lang.builder.EqualsBuilder; |
import org.apache.commons.lang.builder.HashCodeBuilder; |
import org.apache.commons.lang.builder.ToStringBuilder; |
import org.apache.commons.lang.builder.ToStringStyle; |
|
/** |
* @hibernate.class table="entry" |
*/ |
|
|
|
public class Entry extends BaseObject { |
|
private Long id; |
private String text; |
private Date timeCreated; |
private Integer version; |
|
/* |
* Generate your getters and setters using your favorite IDE: In Eclipse: |
* Right-click -> Source -> Generate Getters and Setters |
*/ |
|
/** |
* @return Returns the id. |
* |
* @hibernate.id column="entry_id" generator-class="native" |
* unsaved-value="null" |
*/ |
public Long getEntryId() { |
return entryId; |
} |
|
/** |
* @param id |
* The id to set. |
*/ |
public void setEntryId(Long entryId) { |
this.entryId = entryId; |
} |
|
/** |
* @return Returns the text. |
* |
* @hibernate.property column="entry_text" |
*/ |
public String getText() { |
return text; |
} |
|
/** |
* @param text |
* The text to set. |
*/ |
public void setText(String text) { |
this.text = text; |
} |
|
/** |
* @return Returns the timeCreated. |
* |
* @hibernate.property column="time_created" |
*/ |
public Date getTimeCreated() { |
return timeCreated; |
} |
|
/** |
* @param timeCreated |
* The timeCreated to set. |
*/ |
public void setTimeCreated(Date timeCreated) { |
this.timeCreated = timeCreated; |
} |
|
/** |
* @return Returns the version. |
* |
* @hibernate.version |
*/ |
public Integer getVersion() { |
|
return version; |
} |
|
/** |
* @param version |
* The version to set. |
*/ |
public void setVersion(Integer version) { |
this.version = version; |
} |
|
/** |
* @see java.lang.Object#equals(Object) |
*/ |
public boolean equals(Object object) { |
if (!(object instanceof Entry)) { |
return false; |
} |
Entry rhs = (Entry) object; |
return new EqualsBuilder().append(this.text, rhs.text).append( |
this.timeCreated, rhs.timeCreated).append(this.id, rhs.id) |
.append(this.version, rhs.version).isEquals(); |
} |
|
/** |
* @see java.lang.Object#hashCode() |
*/ |
public int hashCode() { |
return new HashCodeBuilder(-880342185, -1668369001).append(this.text) |
.append(this.timeCreated).append(this.id).append(this.version) |
.toHashCode(); |
} |
|
/** |
* @see java.lang.Object#toString() |
*/ |
public String toString() { |
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) |
.append("text", this.text).append("id", this.id).append( |
"version", this.version).append("timeCreated", |
this.timeCreated).toString(); |
} |
} |
<property name="mappingResources"> |
<list> |
<value>org/appfuse/model/Role.hbm.xml</value> |
<value>org/appfuse/model/User.hbm.xml</value> |
<value>org/appfuse/model/Weblog.hbm.xml</value> |
<value>org/appfuse/model/Entry.hbm.xml</value> |
<value>org/appfuse/model/Category.hbm.xml</value> |
</list> |
</property> |
At line 66 added 1 line. |
!![[Many-to-Many] A Weblogs can have many Users, a User can have many Weblogs [#2] |
At line 68 added 1 line. |
A 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 70 added 1 line. |
Add the following ''users'' property and accessor methods to __Weblog.java__. |
At line 299 removed 4 lines. |
!![[Many-to-One] Create a new Category object and modify Entry.java to use it [#2] |
|
A category object will act as an entity for persisting category information about weblog entries. A category object will consist of an id (primary key), category name, and a description. Each category can have many entries. |
|
At line 305 changed 1 line. |
package org.appfuse.model; |
private List users = new ArrayList(); |
|
/** |
* @hibernate.bag table="weblog_user" cascade="save-update" lazy="true" |
* @hibernate.collection-key column="weblog_id" |
* @hibernate.collection-many-to-many class="org.appfuse.model.User" column="username" |
*/ |
public List getUsers() { |
return users; |
} |
At line 307 changed 4 lines. |
import org.apache.commons.lang.builder.EqualsBuilder; |
import org.apache.commons.lang.builder.HashCodeBuilder; |
import org.apache.commons.lang.builder.ToStringBuilder; |
import org.apache.commons.lang.builder.ToStringStyle; |
public void addUser(User user) { |
getUsers().add(user); |
} |
At line 312 changed 117 lines. |
/** |
* @hibernate.class table="category" |
*/ |
public class Category extends BaseObject { |
|
private Long id; |
private String categoryName; |
private String categoryDescription; |
private Integer version; |
|
/** |
* @return Returns the categoryDescription. |
* |
* @hibernate.property column="category_description" |
*/ |
public String getCategoryDescription() { |
return categoryDescription; |
} |
|
/** |
* @param categoryDescription |
* The categoryDescription to set. |
*/ |
public void setCategoryDescription(String categoryDescription) { |
this.categoryDescription = categoryDescription; |
} |
|
/** |
* @return Returns the categoryName. |
* |
* @hibernate.property column="category_name" |
*/ |
public String getCategoryName() { |
return categoryName; |
} |
|
/** |
* @param categoryName |
* The categoryName to set. |
*/ |
public void setCategoryName(String categoryName) { |
this.categoryName = categoryName; |
|
|
} |
|
/** |
* @return Returns the id. |
* |
|
* @hibernate.id column="category_id" generator-class="native" |
* unsaved-value="null" |
*/ |
public Long getId() { |
return id; |
} |
|
/** |
* @param id |
* The id to set. |
*/ |
public void setId(Long id) { |
this.id = id; |
} |
|
/** |
* @return Returns the version. |
* |
* @hibernate.version |
*/ |
public Integer getVersion() { |
return version; |
} |
|
/** |
* @param version |
* The version to set. |
*/ |
public void setVersion(Integer version) { |
this.version = version; |
} |
|
/** |
* @see java.lang.Object#equals(Object) |
*/ |
public boolean equals(Object object) { |
if (!(object instanceof Category)) { |
return false; |
} |
Category rhs = (Category) object; |
return new EqualsBuilder().append(this.categoryDescription, |
rhs.categoryDescription).append(this.categoryName, |
rhs.categoryName).append(this.id, rhs.id).append(this.version, |
rhs.version).isEquals(); |
} |
|
/** |
* @see java.lang.Object#hashCode() |
*/ |
public int hashCode() { |
return new HashCodeBuilder(-837614407, -1874103513).append( |
this.categoryDescription).append(this.categoryName).append( |
this.id).append(this.version).toHashCode(); |
} |
|
/** |
* @see java.lang.Object#toString() |
*/ |
public String toString() { |
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) |
.append("id", this.id) |
.append("categoryName", this.categoryName).append("version", |
this.version).append("categoryDescription", |
this.categoryDescription).toString(); |
} |
} |
|
public void setUsers(List users) { |
this.users = users; |
} |
At line 431 changed 1 line. |
The many-to-one relationship between entry and category can be established by the entity classes. Hibernate relationships can typically be established on either side of the relationship or as a bi-directional one as well. For our purposes,this relationship will be maintained by an extra property and collection held by Entry. |
%%note __NOTE:__ The reason a java.util.List is used instead of a java.util.Set is because this is because [Sets aren't supported for indexed properties in Struts|http://www.mail-archive.com/[email protected]/msg26289.html].%% |
At line 433 changed 1 line. |
[{Java2HtmlPlugin |
!User modifications |
At line 435 changed 1 line. |
package org.appfuse.model; |
To allow navigation from a User objec to a list of Weblogs, you need to add a List of Weblogs to the User object. Modify ''User.java'' to add a ''weblogs'' List and accessor methods. |
At line 437 removed 175 lines. |
import java.util.Date; |
|
import org.apache.commons.lang.builder.EqualsBuilder; |
import org.apache.commons.lang.builder.HashCodeBuilder; |
import org.apache.commons.lang.builder.ToStringBuilder; |
import org.apache.commons.lang.builder.ToStringStyle; |
|
/** |
* @hibernate.class table="entry" |
*/ |
public class Entry extends BaseObject { |
|
private Long entryId; |
private String text; |
private Date timeCreated; |
private Integer version; |
private Long categoryId; |
private Category category; |
|
/* |
* Generate your getters and setters using your favorite IDE: In Eclipse: |
* Right-click -> Source -> Generate Getters and Setters |
*/ |
|
/** |
* @return Returns the category. |
* |
* @hibernate.many-to-one insert="false" update="false" cascade="none" |
* column="category_id" outer-join="true" |
*/ |
public Category getCategory() { |
return category; |
} |
|
|
|
/** |
* @param category |
* The category to set. |
*/ |
public void setCategory(Category category) { |
this.category = category; |
} |
|
/** |
* @return Returns the categoryId. |
* |
* @hibernate.property column="category_id" |
*/ |
public Long getCategoryId() { |
return categoryId; |
} |
|
/** |
* @param categoryId |
* The categoryId to set. |
* |
*/ |
public void setCategoryId(Long categoryId) { |
this.categoryId = categoryId; |
} |
|
/** |
* @return Returns the id. |
* |
* @hibernate.id column="entry_id" generator-class="native" |
* unsaved-value="null" |
*/ |
public Long getEntryId() { |
return entryId; |
} |
|
/** |
* @param id |
* The id to set. |
*/ |
public void setEntryId(Long entryId) { |
this.entryId = entryId; |
} |
|
/** |
* @return Returns the text. |
* |
* @hibernate.property column="entry_text" |
*/ |
public String getText() { |
return text; |
} |
|
/** |
* @param text |
* The text to set. |
*/ |
public void setText(String text) { |
this.text = text; |
} |
|
/** |
* @return Returns the timeCreated. |
* |
|
* @hibernate.property column="time_created" |
*/ |
public Date getTimeCreated() { |
return timeCreated; |
} |
|
/** |
* @param timeCreated |
* The timeCreated to set. |
*/ |
public void setTimeCreated(Date timeCreated) { |
this.timeCreated = timeCreated; |
} |
|
/** |
* @return Returns the version. |
* |
* @hibernate.version |
*/ |
public Integer getVersion() { |
return version; |
} |
|
/** |
* @param version |
* The version to set. |
*/ |
public void setVersion(Integer version) { |
this.version = version; |
} |
|
/** |
* @see java.lang.Object#equals(Object) |
*/ |
public boolean equals(Object object) { |
if (!(object instanceof Entry)) { |
return false; |
} |
Entry rhs = (Entry) object; |
return new EqualsBuilder().append(this.text, rhs.text).append( |
this.timeCreated, rhs.timeCreated).append(this.category, |
rhs.category).append(this.entryId, rhs.entryId).append( |
this.categoryId, rhs.categoryId).append(this.version, |
rhs.version).isEquals(); |
} |
|
/** |
* @see java.lang.Object#hashCode() |
*/ |
public int hashCode() { |
return new HashCodeBuilder(835056587, 1192670387).append(this.text) |
.append(this.timeCreated).append(this.category).append( |
this.entryId).append(this.categoryId).append( |
this.version).toHashCode(); |
} |
|
/** |
* @see java.lang.Object#toString() |
*/ |
public String toString() { |
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) |
.append("text", this.text).append("entryId", this.entryId) |
.append("version", this.version).append("categoryId", |
this.categoryId).append("category", this.category) |
.append("timeCreated", this.timeCreated).toString(); |
} |
} |
|
}] |
|
!![[One-to-Many] A Weblog object can have many Entries [#3] |
|
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. Hibernate tags are used to establish this relationship using a bag as the Hibernate collection type. |
|
At line 614 changed 1 line. |
package org.appfuse.model; |
protected List weblogs; |
At line 616 changed 1 line. |
import java.util.Date; |
/** |
* @hibernate.bag table="weblog_user" cascade="save-update" lazy="true" |
* @hibernate.collection-key column="username" |
* @hibernate.collection-many-to-many class="org.appfuse.model.Weblog" column="weblog_id" |
*/ |
public List getWeblogs() { |
return weblogs; |
} |
At line 618 changed 165 lines. |
import java.util.List; |
|
import org.apache.commons.lang.builder.EqualsBuilder; |
import org.apache.commons.lang.builder.HashCodeBuilder; |
import org.apache.commons.lang.builder.ToStringBuilder; |
import org.apache.commons.lang.builder.ToStringStyle; |
|
/** |
* @hibernate.class table="weblog" |
*/ |
public class Weblog extends BaseObject { |
|
private Long weblogId; |
private String username; |
private Date dateCreated; |
private String blogTitle; |
private Integer version; |
private List entries; |
|
/** |
* @return Returns the blogTitle. |
* |
* @hibernate.property column="blog_title" |
*/ |
public String getBlogTitle() { |
return blogTitle; |
} |
|
/** |
* @param blogTitle |
* The blogTitle to set. |
*/ |
public void setBlogTitle(String blogTitle) { |
this.blogTitle = blogTitle; |
} |
|
/** |
* @return Returns the dateCreated. |
* |
* @hibernate.property column="date_created" |
*/ |
public Date getDateCreated() { |
return dateCreated; |
} |
|
/** |
* @param dateCreated |
* The dateCreated to set. |
*/ |
public void setDateCreated(Date dateCreated) { |
this.dateCreated = dateCreated; |
} |
|
/** |
* @return Returns the entries. |
* |
* @hibernate.bag name="entries" lazy="true" inverse="true" |
* cascade="delete" |
* @hibernate.collection-key column="entry_id" |
* @hibernate.collection-one-to-many |
* class="org.appfuse.model.Entry" |
*/ |
public List getEntries() { |
return entries; |
} |
|
/** |
* @param entries |
* The entries to set. |
*/ |
public void setEntries(List entries) { |
this.entries = entries; |
} |
|
/** |
* @return Returns the id. |
* |
* @hibernate.id column="weblog_id" generator-class="native" |
* unsaved-value="null" |
*/ |
public Long getWeblogId() { |
return weblogId; |
} |
|
/** |
* @param id |
* The id to set. |
*/ |
public void setWeblogId(Long weblogId) { |
this.weblogId = weblogId; |
} |
|
/** |
* @return Returns the username. |
* |
* @hibernate.property column="username" |
*/ |
public String getUsername() { |
return username; |
} |
|
/** |
* @param username |
* The username to set. |
*/ |
public void setUsername(String username) { |
this.username = username; |
} |
|
/** |
* @return Returns the version. |
* |
* @hibernate.version |
*/ |
public Integer getVersion() { |
return version; |
} |
|
/** |
* @param version |
* The version to set. |
*/ |
public void setVersion(Integer version) { |
this.version = version; |
} |
|
/** |
* @see java.lang.Object#equals(Object) |
*/ |
public boolean equals(Object object) { |
if (!(object instanceof Weblog)) { |
return false; |
} |
Weblog rhs = (Weblog) object; |
return new EqualsBuilder().append(this.blogTitle, rhs.blogTitle) |
.append(this.weblogId, rhs.weblogId).append(this.username, |
rhs.username).append(this.entries, rhs.entries).append( |
this.dateCreated, rhs.dateCreated).append(this.version, |
rhs.version).isEquals(); |
} |
|
/** |
* @see java.lang.Object#hashCode() |
*/ |
public int hashCode() { |
return new HashCodeBuilder(-1412256665, -696169811).append( |
this.blogTitle).append(this.weblogId).append(this.username) |
.append(this.entries).append(this.dateCreated).append( |
this.version).toHashCode(); |
} |
|
/** |
* @see java.lang.Object#toString() |
*/ |
public String toString() { |
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) |
.append("weblogId", this.weblogId).append("version", |
this.version).append("username", this.username).append( |
"blogTitle", this.blogTitle).append("entries", |
this.entries).append("dateCreated", this.dateCreated) |
.toString(); |
} |
} |
|
|
public void setWeblogs(List weblogs) { |
this.weblogs = weblogs; |
} |
At line 785 changed 1 line. |
The Entry class is modified slightly to provide a placeholder for the relationships between Weblog and Entry. |
!Test it! |
At line 787 changed 1 line. |
[{Java2HtmlPlugin |
Create a unit test so you can verify that everything actually works. Create a __WeblogDaoTest__ class in your test/dao/**/dao directory. This file should extend GenericDaoTest. If you're using anything less than AppFuse 1.9, you may have to modify GenericDAOTest's "dao" variable so its __protected__ instead of private. Copy the code below into this test: |
At line 789 removed 198 lines. |
package org.appfuse.model; |
|
import java.util.Date; |
|
import org.apache.commons.lang.builder.EqualsBuilder; |
import org.apache.commons.lang.builder.HashCodeBuilder; |
import org.apache.commons.lang.builder.ToStringBuilder; |
import org.apache.commons.lang.builder.ToStringStyle; |
|
/** |
* @hibernate.class table="entry" |
*/ |
public class Entry extends BaseObject { |
|
private Long entryId; |
private String text; |
private Date timeCreated; |
private Integer version; |
private Category category; |
private Long categoryId; |
|
|
private Long weblogId; |
|
/* |
* Generate your getters and setters using your favorite IDE: In Eclipse: |
* Right-click -> Source -> Generate Getters and Setters |
*/ |
|
/** |
* @return Returns the category. |
* |
* @hibernate.many-to-one insert="false" update="false" cascade="none" |
* column="category_id" outer-join="true" |
*/ |
public Category getCategory() { |
return category; |
} |
|
/** |
* @param category |
* The category to set. |
*/ |
public void setCategory(Category category) { |
this.category = category; |
} |
|
/** |
* @return Returns the categoryId. |
* |
* @hibernate.property column="category_id" |
*/ |
public Long getCategoryId() { |
return categoryId; |
} |
|
/** |
* @param categoryId |
* The categoryId to set. |
* |
*/ |
public void setCategoryId(Long categoryId) { |
this.categoryId = categoryId; |
} |
|
/** |
* @return Returns the id. |
* |
* @hibernate.id column="entry_id" generator-class="native" |
* unsaved-value="null" |
*/ |
public Long getEntryId() { |
return entryId; |
} |
|
/** |
* @param id |
* The id to set. |
*/ |
public void setEntryId(Long entryId) { |
this.entryId = entryId; |
} |
|
/** |
* @return Returns the text. |
* |
* @hibernate.property column="entry_text" |
*/ |
public String getText() { |
return text; |
} |
|
/** |
* @param text |
* The text to set. |
*/ |
public void setText(String text) { |
this.text = text; |
} |
|
/** |
* @return Returns the timeCreated. |
* |
* @hibernate.property column="time_created" |
*/ |
public Date getTimeCreated() { |
return timeCreated; |
} |
|
/** |
* @param timeCreated |
* The timeCreated to set. |
*/ |
public void setTimeCreated(Date timeCreated) { |
this.timeCreated = timeCreated; |
} |
|
/** |
* @return Returns the version. |
* |
* @hibernate.version |
*/ |
public Integer getVersion() { |
return version; |
} |
|
/** |
* @param version |
* The version to set. |
*/ |
public void setVersion(Integer version) { |
this.version = version; |
} |
|
/** |
* @return Returns the weblogId. |
* |
* @hibernate.property column="weblog_id" |
*/ |
public Long getWeblogId() { |
return weblogId; |
} |
|
/** |
* @param weblogId |
* The weblogId to set. |
*/ |
public void setWeblogId(Long weblogId) { |
this.weblogId = weblogId; |
} |
|
/** |
* @see java.lang.Object#equals(Object) |
*/ |
public boolean equals(Object object) { |
if (!(object instanceof Entry)) { |
return false; |
} |
Entry rhs = (Entry) object; |
return new EqualsBuilder().append(this.text, rhs.text).append( |
this.timeCreated, rhs.timeCreated).append(this.weblogId, |
rhs.weblogId).append(this.category, rhs.category).append( |
this.entryId, rhs.entryId).append(this.categoryId, |
rhs.categoryId).append(this.version, rhs.version).isEquals(); |
} |
|
/** |
* @see java.lang.Object#hashCode() |
*/ |
public int hashCode() { |
return new HashCodeBuilder(-1879789101, 535224049).append(this.text) |
.append(this.timeCreated).append(this.weblogId).append( |
this.category).append(this.entryId).append( |
this.categoryId).append(this.version).toHashCode(); |
} |
|
/** |
* @see java.lang.Object#toString() |
*/ |
public String toString() { |
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) |
.append("weblogId", this.weblogId).append("text", this.text) |
.append("entryId", this.entryId) |
.append("version", this.version).append("categoryId", |
this.categoryId).append("category", this.category) |
.append("timeCreated", this.timeCreated).toString(); |
} |
} |
|
}] |
|
!![[Many-to-Many] [#4] |
|
|
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. |
|
Weblog modifications: |
|
At line 989 removed 646 lines. |
package org.appfuse.model; |
|
import java.util.Date; |
|
import java.util.List; |
import java.util.HashSet; |
import java.util.Set; |
|
import org.apache.commons.lang.builder.EqualsBuilder; |
import org.apache.commons.lang.builder.HashCodeBuilder; |
import org.apache.commons.lang.builder.ToStringBuilder; |
import org.apache.commons.lang.builder.ToStringStyle; |
|
/** |
* @hibernate.class table="weblog" |
*/ |
public class Weblog extends BaseObject { |
|
private Long weblogId; |
private String username; |
private Date dateCreated; |
private String blogTitle; |
private Integer version; |
private List entries; |
private Set users = new HashSet(); |
|
/** |
* @return Returns the blogTitle. |
* |
* @hibernate.property column="blog_title" |
*/ |
public String getBlogTitle() { |
return blogTitle; |
} |
|
/** |
* @param blogTitle |
* The blogTitle to set. |
*/ |
public void setBlogTitle(String blogTitle) { |
this.blogTitle = blogTitle; |
} |
|
|
/** |
* @return Returns the dateCreated. |
* |
* @hibernate.property column="date_created" |
*/ |
public Date getDateCreated() { |
return dateCreated; |
} |
|
/** |
* @param dateCreated |
* The dateCreated to set. |
*/ |
public void setDateCreated(Date dateCreated) { |
this.dateCreated = dateCreated; |
} |
|
/** |
* @return Returns the entries. |
* |
* @hibernate.bag name="entries" lazy="true" inverse="true" cascade="delete" |
* @hibernate.collection-key column="entry_id" |
* @hibernate.collection-one-to-many class="org.appfuse.model.Entry" |
*/ |
public List getEntries() { |
return entries; |
} |
|
/** |
* @param entries |
* The entries to set. |
*/ |
public void setEntries(List entries) { |
this.entries = entries; |
} |
|
/** |
* @return Returns the id. |
* |
* @hibernate.id column="weblog_id" generator-class="native" |
* unsaved-value="null" |
*/ |
public Long getWeblogId() { |
return weblogId; |
} |
|
/** |
* @param id |
* The id to set. |
*/ |
public void setWeblogId(Long weblogId) { |
this.weblogId = weblogId; |
} |
|
/** |
* @return Returns the username. |
* |
* @hibernate.property column="username" |
*/ |
public String getUsername() { |
return username; |
} |
|
/** |
* @param username |
* The username to set. |
*/ |
public void setUsername(String username) { |
this.username = username; |
} |
|
/** |
* @return Returns the users. |
* |
* @hibernate.set table="weblog_user" cascade="none" lazy="false" |
* @hibernate.collection-key column="weblog_id" |
* @hibernate.collection-many-to-many class="org.appfuse.model.User" |
* column="username" |
*/ |
public Set getUsers() { |
return users; |
} |
|
/** |
* Adds a user for the weblog |
* |
* @param rolename |
*/ |
public void addUser(User user) { |
getUsers().add(user); |
} |
|
/** |
* @param users |
* The users to set. |
*/ |
public void setUsers(Set users) { |
this.users = users; |
} |
|
/** |
* @return Returns the version. |
* |
* @hibernate.version |
*/ |
public Integer getVersion() { |
return version; |
} |
|
/** |
* @param version |
* The version to set. |
*/ |
public void setVersion(Integer version) { |
this.version = version; |
} |
|
/** |
* @see java.lang.Object#equals(Object) |
*/ |
public boolean equals(Object object) { |
if (!(object instanceof Weblog)) { |
return false; |
} |
Weblog rhs = (Weblog) object; |
return new EqualsBuilder().append(this.users, rhs.users).append( |
this.blogTitle, rhs.blogTitle).append(this.weblogId, |
rhs.weblogId).append(this.username, rhs.username).append( |
this.entries, rhs.entries).append(this.dateCreated, |
rhs.dateCreated).append(this.version, rhs.version).isEquals(); |
} |
|
/** |
* @see java.lang.Object#hashCode() |
*/ |
public int hashCode() { |
return new HashCodeBuilder(1149273015, 1751732143).append(this.users) |
.append(this.blogTitle).append(this.weblogId).append( |
this.username).append(this.entries).append( |
this.dateCreated).append(this.version).toHashCode(); |
} |
|
/** |
* @see java.lang.Object#toString() |
*/ |
public String toString() { |
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) |
.append("weblogId", this.weblogId).append("version", |
this.version).append("users", this.users).append( |
"username", this.username).append("blogTitle", |
this.blogTitle).append("entries", this.entries).append( |
"dateCreated", this.dateCreated).toString(); |
} |
} |
|
|
}] |
|
!User modifications |
|
[{Java2HtmlPlugin |
|
package org.appfuse.model; |
|
import java.io.Serializable; |
|
import java.util.ArrayList; |
import java.util.HashSet; |
import java.util.Iterator; |
import java.util.List; |
import java.util.Set; |
|
import org.apache.commons.lang.builder.EqualsBuilder; |
import org.apache.commons.lang.builder.HashCodeBuilder; |
import org.apache.commons.lang.builder.ToStringBuilder; |
import org.apache.commons.lang.builder.ToStringStyle; |
|
/** |
* User class |
* |
* This class is used to generate Spring Validation rules as well as the |
* Hibernate mapping file. |
* |
* <p> |
* <a href="User.java.html"> <i>View Source </i> </a> |
* </p> |
* |
* @author <a href="mailto:[email protected]">Matt Raible </a> Updated by |
* Dan Kibler ([email protected]) |
* |
* @hibernate.class table="app_user" |
*/ |
public class User extends BaseObject implements Serializable { |
protected String username; |
protected String password; |
protected String confirmPassword; |
protected String firstName; |
protected String lastName; |
protected Address address = new Address(); |
protected String phoneNumber; |
protected String email; |
protected String website; |
protected String passwordHint; |
protected Integer version; |
protected Boolean enabled; |
protected Set roles = new HashSet(); |
protected Set weblogs; |
|
/** |
* Returns the username. |
* |
* @return String |
* |
* @hibernate.id column="username" length="20" generator-class="assigned" |
* unsaved-value="version" |
*/ |
public String getUsername() { |
return username; |
} |
|
/** |
* Returns the password. |
* |
* @return String |
* |
* @hibernate.property column="password" not-null="true" |
*/ |
public String getPassword() { |
return password; |
} |
|
/** |
* Returns the confirmedPassword. |
* |
* @return String |
*/ |
public String getConfirmPassword() { |
return confirmPassword; |
} |
|
/** |
* Returns the firstName. |
* |
* @return String |
* |
* @hibernate.property column="first_name" not-null="true" length="50" |
*/ |
public String getFirstName() { |
return firstName; |
} |
|
/** |
* Returns the lastName. |
* |
* @return String |
* |
* @hibernate.property column="last_name" not-null="true" length="50" |
*/ |
public String getLastName() { |
return lastName; |
} |
|
public String getFullName() { |
return firstName + ' ' + lastName; |
} |
|
/** |
* Returns the address. |
* |
* @return Address |
* |
* @hibernate.component |
*/ |
public Address getAddress() { |
return address; |
} |
|
/** |
* Returns the email. This is an optional field for specifying a different |
* e-mail than the username. |
* |
* @return String |
* |
* @hibernate.property name="email" not-null="true" unique="true" |
*/ |
public String getEmail() { |
return email; |
} |
|
/** |
* Returns the phoneNumber. |
* |
* @return String |
* |
* @hibernate.property column="phone_number" not-null="false" |
*/ |
public String getPhoneNumber() { |
return phoneNumber; |
} |
|
/** |
* Returns the website. |
* |
* @return String |
* |
* @hibernate.property column="website" not-null="false" |
*/ |
public String getWebsite() { |
return website; |
} |
|
/** |
* Returns the passwordHint. |
* |
* @return String |
* |
* @hibernate.property column="password_hint" not-null="false" |
*/ |
public String getPasswordHint() { |
return passwordHint; |
} |
|
/** |
* Returns the user's roles. |
* |
* @return Set |
* |
* @hibernate.set table="user_role" cascade="save-update" lazy="false" |
* @hibernate.collection-key column="username" |
* @hibernate.collection-many-to-many class="org.appfuse.model.Role" |
* column="role_name" |
*/ |
public Set getRoles() { |
return roles; |
} |
|
/** |
* Adds a role for the user |
* |
* @param rolename |
*/ |
public void addRole(Role role) { |
getRoles().add(role); |
} |
|
/** |
* Sets the username. |
* |
* @param username |
* The username to set |
* @spring.validator type="required" |
*/ |
public void setUsername(String username) { |
this.username = username; |
} |
|
/** |
* Sets the password. |
* |
* @param password |
* The password to set |
* |
* @spring.validator type="required" |
* @spring.validator type="twofields" msgkey="errors.twofields" |
* @spring.validator-args arg1resource="user.password" |
* @spring.validator-args arg1resource="user.confirmPassword" |
* @spring.validator-var name="secondProperty" value="confirmPassword" |
*/ |
public void setPassword(String password) { |
this.password = password; |
} |
|
/** |
* Sets the confirmedPassword. |
* |
* @param confirmPassword |
* The confirmed password to set |
* @spring.validator type="required" |
*/ |
public void setConfirmPassword(String confirmPassword) { |
this.confirmPassword = confirmPassword; |
} |
|
/** |
* Sets the firstName. |
* |
* @spring.validator type="required" |
* @param firstName |
* The firstName to set |
*/ |
public void setFirstName(String firstName) { |
this.firstName = firstName; |
} |
|
/** |
* Sets the lastName. |
* |
* @param lastName |
* The lastName to set |
* |
* @spring.validator type="required" |
*/ |
public void setLastName(String lastName) { |
this.lastName = lastName; |
} |
|
/** |
* Sets the address. |
* |
* @param address |
* The address to set |
* |
* @spring.validator |
*/ |
public void setAddress(Address address) { |
this.address = address; |
} |
|
/** |
* Sets the email. |
* |
* @param email |
* The email to set |
* |
* @spring.validator type="required" |
* @spring.validator type="email" |
*/ |
public void setEmail(String email) { |
this.email = email; |
} |
|
/** |
* Sets the phoneNumber. |
* |
* @param phoneNumber |
* The phoneNumber to set |
* |
* @spring.validator type="mask" msgkey="errors.phone" |
* @spring.validator-var name="mask" value="${phone}" |
*/ |
public void setPhoneNumber(String phoneNumber) { |
this.phoneNumber = phoneNumber; |
} |
|
/** |
* Sets the website. |
* |
* @param website |
* The website to set |
*/ |
public void setWebsite(String website) { |
this.website = website; |
} |
|
/** |
* @param passwordHint |
* The password hint to set |
* |
* @spring.validator type="required" |
*/ |
public void setPasswordHint(String passwordHint) { |
this.passwordHint = passwordHint; |
} |
|
/** |
* Sets the roles. |
* |
* @param roles |
* The roles to set |
*/ |
public void setRoles(Set roles) { |
this.roles = roles; |
} |
|
/** |
* @return Returns the updated timestamp. |
* @hibernate.version |
*/ |
public Integer getVersion() { |
return version; |
} |
|
/** |
* @param updated |
* The updated version to set. |
*/ |
public void setVersion(Integer version) { |
this.version = version; |
} |
|
/** |
* @return Returns the weblogs. |
*/ |
public Set getWeblogs() { |
return weblogs; |
} |
|
/** |
* @param weblogs |
* The weblogs to set. |
*/ |
public void setWeblogs(Set weblogs) { |
this.weblogs = weblogs; |
} |
|
/** |
* @return Returns the enabled. |
* @hibernate.property column="enabled" |
*/ |
public Boolean getEnabled() { |
return enabled; |
} |
|
/** |
* @param enabled |
* The enabled to set. |
*/ |
public void setEnabled(Boolean enabled) { |
this.enabled = enabled; |
} |
|
/** |
* Convert user roles to LabelValue objects for convenience. |
*/ |
public List getRoleList() { |
List userRoles = new ArrayList(); |
|
if (this.roles != null) { |
for (Iterator it = roles.iterator(); it.hasNext();) { |
Role role = (Role) it.next(); |
|
// convert the user's roles to LabelValue Objects |
userRoles.add(new LabelValue(role.getName(), role.getName())); |
} |
} |
|
return userRoles; |
} |
|
/** |
* @see java.lang.Object#equals(Object) |
*/ |
public boolean equals(Object object) { |
if (!(object instanceof User)) { |
return false; |
} |
User rhs = (User) object; |
return new EqualsBuilder().append(this.password, rhs.password).append( |
this.passwordHint, rhs.passwordHint).append(this.address, |
rhs.address).append(this.roles, rhs.roles).append( |
this.firstName, rhs.firstName).append(this.lastName, |
rhs.lastName).append(this.version, rhs.version).append( |
this.weblogs, rhs.weblogs).append(this.enabled, rhs.enabled) |
.append(this.confirmPassword, rhs.confirmPassword).append( |
this.username, rhs.username).append(this.email, |
rhs.email).append(this.phoneNumber, rhs.phoneNumber) |
.append(this.website, rhs.website).isEquals(); |
} |
|
/** |
* @see java.lang.Object#hashCode() |
*/ |
public int hashCode() { |
return new HashCodeBuilder(-1892187061, -1292517047).append( |
this.password).append(this.passwordHint).append(this.address) |
.append(this.roles).append(this.firstName) |
.append(this.lastName).append(this.version) |
.append(this.weblogs).append(this.enabled).append( |
this.confirmPassword).append(this.username).append( |
this.email).append(this.phoneNumber).append( |
this.website).toHashCode(); |
} |
|
/** |
* @see java.lang.Object#toString() |
*/ |
public String toString() { |
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) |
.append("roles", this.roles).append("enabled", this.enabled) |
.append("firstName", this.firstName).append("lastName", |
this.lastName) |
.append("passwordHint", this.passwordHint).append("version", |
this.version).append("username", this.username).append( |
"weblogs", this.weblogs).append("fullName", |
this.getFullName()).append("email", this.email).append( |
"phoneNumber", this.phoneNumber).append("password", |
this.password).append("address", this.address).append( |
"confirmPassword", this.confirmPassword).append( |
"roleList", this.getRoleList()).append("website", |
this.website).toString(); |
} |
} |
|
|
}] |
|
!!DAO Stuff |
|
!WeblogDaoTest |
|
[{Java2HtmlPlugin |
|
At line 1639 removed 3 lines. |
import org.appfuse.Constants; |
import org.appfuse.model.Address; |
import org.appfuse.model.Weblog; |
At line 1643 changed 2 lines. |
import org.springframework.dao.DataAccessException; |
import org.springframework.dao.DataIntegrityViolationException; |
import org.appfuse.model.Weblog; |
At line 1646 changed 6 lines. |
public class WeblogDaoTest extends BaseDaoTestCase { |
|
private WeblogDAO wldao = null; |
private Weblog weblog = null; |
private UserDAO udao = null; |
private User user = null; |
public class WeblogDaoTest extends GenericDAOTest { |
At line 1653 changed 39 lines. |
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 testGetWeblogInvalid() throws Exception { |
try { |
weblog = wldao.getWeblog(new Long(3000)); |
fail("weblogId found in database, failing test..."); |
} catch (DataAccessException d) { |
assertTrue(d != 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()); |
public void testWeblogAndUsers() throws Exception { |
Weblog w = new Weblog(); |
w.setBlogTitle("My New Weblog"); |
w.setDateCreated(new Date()); |
At line 1693 changed 3 lines. |
user = udao.getUser("tomcat"); |
weblog.addUser(user); |
wldao.saveWeblog(weblog); |
// add it to the database |
dao.saveObject(w); |
At line 1697 changed 1 line. |
assertEquals(2, weblog.getUsers().size()); |
w = (Weblog) dao.getObject(Weblog.class, w.getWeblogId()); |
At line 1699 changed 5 lines. |
//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()); |
assertTrue(w.getUsers().isEmpty()); |
At line 1705 changed 11 lines. |
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"); |
// add a user |
User u = (User) dao.getObject(User.class, "mraible"); |
w.addUser(u); |
At line 1717 changed 1 line. |
wldao.saveWeblog(weblog); |
dao.saveObject(w); |
At line 1719 changed 2 lines. |
assertNotNull(weblog.getBlogTitle()); |
assertEquals("Cartman", weblog.getUsername()); |
w = (Weblog) dao.getObject(Weblog.class, w.getWeblogId()); |
At line 1722 changed 1 line. |
wldao.removeWeblog(weblog.getWeblogId()); |
assertTrue(w.getUsers().size() == 1); |
At line 1724 changed 6 lines. |
try { |
weblog = wldao.getWeblog(weblog.getWeblogId()); |
fail("saveWeblog didn't throw DataAccessException"); |
} catch (DataAccessException d) { |
assertNotNull(d); |
} |
// remove the user |
w.setUsers(null); |
dao.saveObject(w); |
|
w = (Weblog) dao.getObject(Weblog.class, w.getWeblogId()); |
|
assertNull(w.getUsers()); |
At line 1731 removed 1 line. |
|
At line 1733 removed 1 line. |
|
At line 1736 changed 1 line. |
!WeblogDAO |
Make sure you run __ant setup-db__ before running __ant test-dao -Dtestcase=UserDAO__. When running the test, you'll probably get a ''LazyInitializationException''. To solve this, change BaseDaoTestCase to extend Spring's [AbstractTransactionalDataSourceSpringContextTests|http://www.springframework.org/docs/api/org/springframework/test/AbstractTransactionalDataSourceSpringContextTests.html] if it doesn't already. In additional, you'll need to make a few changes to the existing tests so all the tests pass. [Here is a patch|LazyDaoTests.diff]. At a minimum, you'll need to fix BaseDAOTestCase and GenericDAOTest (onSetUp() -> onSetupBeforeTransaction()). |
At line 168 added 2 lines. |
Because the WeblogDaoTest is now extending AbstractTransactionalDataSourceSpringContextTests (ATDSSCT), there is a "jdbcTemplate" variable you can use to do additional querying. For instance, you could add the following at the end of your ''testWeblogAndUsers()'' method: |
|
At line 172 added 4 lines. |
String qry = "select count(*) from weblog_user where username = 'mraible' " + |
" and weblog_id = " + w.getWeblogId(); |
assertEquals(0, jdbcTemplate.queryForInt(qry)); |
}] |
At line 1741 changed 1 line. |
package org.appfuse.dao; |
!![[One-to-Many] A Weblog object can have many Entries [#3] |
At line 1743 changed 1 line. |
import java.util.List; |
Now you'll 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 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 1745 changed 1 line. |
import org.appfuse.model.Weblog; |
[{Java2HtmlPlugin |
At line 1747 changed 7 lines. |
public interface WeblogDAO extends Dao{ |
|
public Weblog getWeblog(Long weblogId); |
|
public List getWeblogs(Weblog weblog); |
|
public void saveWeblog(Weblog weblog); |
private List entries; |
At line 1755 changed 1 line. |
public void removeWeblog(Long weblogId); |
/** |
* @return Returns the entries. |
* |
* @hibernate.bag name="entries" lazy="false" cascade="all" |
* @hibernate.collection-key column="weblog_id" |
* @hibernate.collection-one-to-many class="org.appfuse.model.Entry" |
*/ |
public List getEntries() { |
return entries; |
} |
At line 1757 changed 2 lines. |
} |
|
public void setEntries(List entries) { |
this.entries = entries; |
} |
At line 1761 changed 1 line. |
!WeblogDAOHibernate |
Modify the __Entry__ class is so it contains a foreign key to its parent __Weblog__ class. |
At line 1765 changed 1 line. |
package org.appfuse.dao.hibernate; |
private Long weblogId; |
At line 1767 changed 1 line. |
import java.util.List; |
/** |
* @hibernate.property column="weblog_id" |
*/ |
public Long getWeblogId() { |
return weblogId; |
} |
At line 1769 changed 3 lines. |
import org.appfuse.dao.WeblogDAO; |
import org.appfuse.model.Weblog; |
import org.springframework.orm.ObjectRetrievalFailureException; |
public void setWeblogId(Long weblogId) { |
this.weblogId = weblogId; |
} |
}] |
At line 1773 changed 13 lines. |
/** |
* This class interacts with Spring's HibernateTemplate to save/delete and |
* retrieve Weblog objects. |
* |
* <p> |
* <a href="WeblogDAOHibernate.java.html"><i>View Source</i></a> |
* </p> |
* |
*/ |
public class WeblogDAOHibernate extends BaseDaoHibernate implements WeblogDAO { |
|
public Weblog getWeblog(Long weblogId) { |
Weblog weblog = (Weblog) getHibernateTemplate().get(Weblog.class, weblogId); |
At this point, you could add an additional test method to WeblogDaoTest to test that this relationship works. Of course, you'll need to run __ant setup-db__ to make sure your database knows about the relationship. |
At line 1787 changed 4 lines. |
if (weblog == null) { |
log.warn("uh oh, weblog '" + weblogId + "' not found..."); |
throw new ObjectRetrievalFailureException(Weblog.class, weblogId); |
} |
!![[Many-to-One] A Category object can be assigned to many entries [#4] |
At line 1792 changed 2 lines. |
return weblog; |
} |
The ''many-to-one'' relationship between __Category__ and __Entry__ 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 is maintained by a __categoryId__ property and a __Category__ object in __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. Notice that the relationship to __Category__ has ''insert="false" update="false"''. This is because the object is read-only. This can be useful for displaying a category's name on the UI when you're viewing an Entry. |
At line 225 added 5 lines. |
[{Java2HtmlPlugin |
|
private Long categoryId; |
private Category category; |
|
At line 1796 changed 1 line. |
* @see org.appfuse.dao.WeblogDAO#getWeblogs(org.appfuse.model.Weblog) |
* @hibernate.many-to-one insert="false" update="false" cascade="none" |
* column="category_id" outer-join="true" |
At line 1798 changed 2 lines. |
public List getWeblogs(Weblog weblog) { |
return getHibernateTemplate().find("from Weblog wl order by upper(wl.blogTitle)"); |
public Category getCategory() { |
return category; |
At line 1802 changed 11 lines. |
/** |
* @see org.appfuse.dao.WeblogDAO#saveWeblog(org.appfuse.model.Weblog) |
*/ |
public void saveWeblog(final Weblog weblog) { |
if (log.isDebugEnabled()) { |
log.debug("weblog's title: " + weblog.getBlogTitle()); |
} |
|
getHibernateTemplate().saveOrUpdate(weblog); |
// necessary to throw a DataIntegrityViolation and catch it in WeblogManager |
getHibernateTemplate().flush(); |
public void setCategory(Category category) { |
this.category = category; |
At line 1816 changed 1 line. |
* @see org.appfuse.dao.WeblogDAO#removeWeblog(java.lang.String) |
* @hibernate.property column="category_id" |
At line 1818 changed 3 lines. |
public void removeWeblog(Long weblogId) { |
Weblog weblog = getWeblog(weblogId); |
getHibernateTemplate().delete(weblog); |
public Long getCategoryId() { |
return categoryId; |
At line 1823 changed 2 lines. |
} |
|
public void setCategoryId(Long categoryId) { |
this.categoryId = categoryId; |
} |
At line 254 added 1 line. |
After making these changes, your __WeblogDaoTest__ should still pass. Verify it does by running __ant setup-db test-dao -Dtestcase=Weblog__. |
At line 1828 changed 1 line. |
!Sample Data |
''__Yeah baby, Yeah!__'' |
%%(color: green) |
BUILD SUCCESSFUL\\ |
Total time: 24 seconds |
%% |
At line 1830 changed 1 line. |
Add some sample data to /metadata/sql/sample-data.xml. |
Before working on the UI, it's helpful to have some sample data so you don't have to do manual data entry. Add the following XML to the bottom of __metadata/sql/sample-data.xml__. |
At line 1834 changed 37 lines. |
<table name='weblog'> |
<column>weblog_id</column> |
<column>blog_title</column> |
<column>date_created</column> |
<column>username</column> |
<column>version</column> |
<row> |
<value>1</value> |
<value><![CDATA[Sponge Bob is Cool]]></value> |
<value>2004-03-31</value> |
<value>tomcat</value> |
<value>1</value> |
</row> |
<row> |
<value>2</value> |
<value><![CDATA[Java Development = Fun]]></value> |
<value>2005-01-05</value> |
<value>mraible</value> |
<value>1</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='weblog'> |
<column>weblog_id</column> |
<column>blog_title</column> |
<column>date_created</column> |
<row> |
<value>1</value> |
<value><![CDATA[Sponge Bob is Cool]]></value> |
<value>2004-03-31</value> |
</row> |
<row> |
<value>2</value> |
<value><![CDATA[Java Development = Fun]]></value> |
<value>2005-01-05</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>name</column> |
<column>description</column> |
<row> |
<value>1</value> |
<value><![CDATA[Struts vs. 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 01:02:03.4</value> |
<value>1</value> |
<value>1</value> |
</row> |
<row> |
<value>2</value> |
<value><![CDATA[Test Value]]></value> |
<value>2005-04-12 01:02:03.4</value> |
<value>1</value> |
<value>1</value> |
</row> |
<row> |
<value>3</value> |
<value><![CDATA[Test Value 3]]></value> |
<value>2005-04-12 01:02:03.4</value> |
<value>2</value> |
<value>3</value> |
</row> |
</table> |
At line 1874 changed 2 lines. |
!Configure Spring for WeblogDAO |
Modifications need to be made in applicationContext-hibernate.xml for the new entity Weblog. |
---- |
At line 1877 changed 29 lines. |
[{Java2HtmlPlugin |
|
<property name="mappingResources"> |
<list> |
<value>org/appfuse/model/Role.hbm.xml</value> |
<value>org/appfuse/model/User.hbm.xml</value> |
<value>org/appfuse/model/UserCookie.hbm.xml</value> |
<value>org/appfuse/model/Weblog.hbm.xml</value> |
<value>org/appfuse/model/Entry.hbm.xml</value> |
<value>org/appfuse/model/Category.hbm.xml</value> |
</list> |
</property> |
}] |
|
|
|
[{Java2HtmlPlugin |
|
<!-- WeblogDAO: Hibernate implementation --> |
<bean id="weblogDAO" class="org.appfuse.dao.hibernate.WeblogDAOHibernate"> |
<property name="sessionFactory"><ref local="sessionFactory"/></property> |
</bean> |
}] |
|
|
!!Lazy-Loading Issues [#5] |
|
!!Managing relationships and indexed properties in the UI [#6] |
|
''Next Up:'' __Part II:__ [Create Weblog UI|HibernateRelationshipsUI] - Creating a UI to manage the relationships created in this tutorial. |