Showing posts with label persistence. Show all posts
Showing posts with label persistence. Show all posts

Wednesday, December 10, 2008

Adding logic to accessor methods in Hibernate

While reading Java Persistence with Hibernate I came across an interesting fact that Hibernate does not require you to have getter and setter methods. On top of that it does not rely on them to check if the value of a property has changes. This means that you can amend and change your data before giving it away from getter.

Assume you have a Person class and a person has a first and second names, both must be capitalized.

First, you can add logic into your methods, like validation:

public class Person{
   
private String firstName;
   
private String secondName;
   
public String getFirstName(){
       
return firstName;
   
}
   
public void setFirstName(String firstName)
               
throws InvalidNameException{
       
if(!StringUtil.isCapitalized(firstname))
           
throw new InvalidNameException(firstname);
       
this.firstname = firstname;
   
}
}

Second, you can have convenience methods:

public class Person{
   
private String firstName;
   
private String secondName;
   
public String getName(){
       
return firstName + ' ' + secondName;
   
}
   
public void setName(String name){
       
StringTokenizer t = new StringTokenizer(name);
       
firstname = t.nextToken();
       
secondname = t.nextToken();
   
}
}

NOTE:
The only exception is collections! You can not change collection values in your getter and setter methods. Otherwise, Hibernate will issue an UPDATE SQL statement every time it synchronizes with database.

To conclude, you can change a property's value also add logic in your getter/setter methods if and only if the property is not a collection.

Tuesday, December 9, 2008

Convenience methods in Parent / Child relationships in Hibernate

One of the most used associations in ORM is a parent/children relationship. Each parent has a set of children and a child has only one parent. So this is a snippet of a convenience method to manage children from a great book I'm currently reading Java Persistence with Hibernate.

public void addChildCategory(Category childCategory){
   
if(childCategory == null)
       
throw new IllegalArgumentException("Null child category!");
   
if(childCategory.getParentCategory() != null)
       
childCategory.getParentCategory().getChildCategories().remove(childCategory);
   
childCategory.setParentCategory(this);
   
childCategories.add(childCategory);
}

Similarly you can create a removeChildCategory() convenience method.

You probably want to make this methods public and getter/setter methods of the children field private. This will enforce cardinality of the association.

TIP:
Hibernate does not require your entity class to have getter and setter methods. Hibernate will access your entity class properties using Java's Reflection API. So even though your properties are private Hibernate will be able to access them.

In case you have a bidirectional association and your entity class has getter methods than the getter returns a modifiable reference to your children set. This may lead to potential cardinality problem. So, I suggest to wrap your collections in getter method with Collections.unmodifiableCollection(children) and Collections.unmodifiableSet(children).

Thursday, December 4, 2008

Hibernate: Self-mapping Parent/Child relationship using annotations

Yesterday I wrote about self mapping collections in Hibernate. I used XML mapping document to define the relationship. Today I would like to show how to achieve the same result using Java Annotations. So without further adu here is the java class:

@Entity
@Table(name = "CATALOGUE")
public class Catalogue implements Serializable {

    @Id
    @Column(name = "ID")
    private Integer id;

    @Column(name = "CONTENT", nullable = true)
    private String content;

    @ManyToOne
    @JoinColumn(name = "PARENT_ID")
    private Catalogue parent;

    @OneToMany(mappedBy = "parent")
    private Set<Catalogue> children = new HashSet<Catalogue>();

    public Catalogue() {
    }

    public Integer getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public Set<Catalogue> getChildren() {
        return children;
    }

    public void setChildren(Set<Catalogue> children) {
        this.children = children;
    }

    public void addChild(Catalogue child) {
        child.setParent(this);
        children.add(child);
    }

    public Catalogue getParent() {
        return parent;
    }

    public void setParent(Catalogue parent) {
        this.parent = parent;
    }
}

Wednesday, December 3, 2008

Hibernate: Mapping an entity to itself - Parent / Child relashipship

Well I am kinda into Hibernate right now. Converting the project that I'm working on to Hibernate. We have a catalogue that has a Parent/Child relationship, similar to directory structure or some tree. Basically a catalogue/direcotry has another catalogue/directory as a child or parent. So basically this entity maps to itself (self-mapping so to speak).

Hibernate XML mapping file:

Mapping java class:

public class Catalogue {
  private int id;
  private String content;
  private Catalogue parent;
  private Set<Catalogue> children =
                new HashSet<Catalogue>();

  public Parent(){
  }

  public int getId() {
    return id;
  }

  public void setId(int id) {
    this.id = id;
  }

  public String getContent() {
    return content;
  }

  public void setContent(String content) {
    this.content = content;
  }

  public Set<Catalogue> getChildren() {
    return children;
  }

  public void setChildren(Set<Catalogue> children){
    this.children = children;
  }

  public void addChild(Catalogue child){
    child.setParent(this);
    children.add(child);
  }
 
  public String getParent() {
    return parent;
  }

  public void setParent(Catalogue parent) {
    this.parent = parent;
  }
}