Showing posts with label JPA. Show all posts
Showing posts with label JPA. Show all posts

Monday, 24 December 2012

JPA Troubleshooting: "org.hibernate.PropertyNotFoundException: Could not find a setter for property myProp in class mypackage.Foo"

Make sure that you have imported javax.persistence.Transient (right) instead of java.beans.Transient (wrong).

Sunday, 12 February 2012

JPA: How to know if a OptimisticLockException os thrown

try {
  //access the DAO...
} 
catch(Exception e) {
  if("nested exception is javax.persistence.OptimisticLockException".equals(e.getMessage()))
    //then it is a OptimisticLockException
}

See also...

See how to implement Versioning

Wednesday, 1 February 2012

JPA: How to implement Versioning (@Version)

In another article I will explain what versioning is and differences between optimistic and pessimistic versioning. Here I will just describe how to implement optimistic versioning it..

@Entity
public class Foo {
 // ...

 prive Long version;
 @Version
 public Long getVersion() { return version; }
 public void setVersion(Long version) { this.version = version; }

 // ...
}

On each transaction commit if the entity is modified (persist or merge) the version column is increased by one.

Other possibilities

Instead of a Long you could use a Integer or a Date..but Date has performance problems and does not guarantee good behavior if two commits are happened with milliseconds time difference (see http://swinbrain.ict.swin.edu.au/wiki/Implementing_Concurrency_Controls_using_Hibernate).

See also...

If you get StaleObjectStateException or OptimisticLockException then make sure that you don't persist the loading time of the entity (see http://micharg.blogspot.com/2012/02/jpaversioning-thrown.html)
How to catch a OptimisticLockException

JPA:Versioning: thrown OptimisticLockException or StaleObjectStateException

In a project that I use versioning (@Version) I consistenly got OptimisticLockException or StaleObjectStateException. The reason was that each time I read (entityManager.find()) an entity from the db I updated an attributed of it (loadDate)...
@PostLoad
public void postLoad() throws Exception {
  loadDate = new Date();
}

So the entity was changed and it was automatically merged when the transactions contained the entityManager.find() was finished (commited). Pretty silly...

For more info on the above technique of persisting the loading time of an entity see http://micharg.blogspot.com/2012/02/jpa-how-to-persist-loading-of-entity.html

JPA: How to persist the loading time of an entity

@Entity
public class GenericEntity implements Serializable {

// ...

@Column(name="LOAD_DATE")
@Temporal(TemporalType.TIMESTAMP)
public Date getLoadDate() { return loadDate; }
public void setLoadDate(Date loadDate) { this.loadDate = loadDate; }

@PostLoad
public void postLoad() throws Exception {
  loadDate = new Date();
}

// ...

}

Monday, 30 January 2012

JPA: @OneToMany error: Field 'usersB_ID' doesn't have a default value

Moral: If you use @OneToMany always declare @JoinTable

Code with error:

@Entity
public class Users {

  @OneToMany
  public Set getUsersA() { return usersA; }


  @OneToMany
  public Set getUsersB() { return usersB; }

}


Problem description: In a @OneToMany relationship is you don't specify a join table then JPA creates one with the combined name of the outer class and the return type of the getter, i.e. in our case Users_User. Since usersA and usersB are of the same class then JPA creates only one join table. When we add a User in (e.g.) usersA and persist/merge Users in db then an sql cmd such as the following is executed:
insert into Users_user (Users_ID, users_ID) values (1,3)
but Users_user has 3 columns: id, FK to User class because of getUsersA(), FK to User class because of getUsersB(). But the 3rd column remains null in the previous sql statement and therefore an error is thrown: Field 'usersB_ID' doesn't have a default value

Solution: Create 2 join tables

@Entity
public class Users {

  @OneToMany
  @JoinTable
   (
       name="Users_usersA",
       joinColumns={ @JoinColumn(name="Users_ID", referencedColumnName="ID") },
       inverseJoinColumns={ @JoinColumn(name="USER_ID", referencedColumnName="ID") }
   )
  public Set getUsersA() { return usersA; }


  @OneToMany
  @JoinTable
   (
       name="Users_usersB",
       joinColumns={ @JoinColumn(name="Users_ID", referencedColumnName="ID") },
       inverseJoinColumns={ @JoinColumn(name="USER_ID", referencedColumnName="ID") }
   )
  public Set getUsersB() { return usersB; }

}


Sunday, 29 January 2012

JPA Criteria: Safe JPA Criteria for Enum

enum FooType:
public enum FooType {
  //...
}
Entity Foo (containing attribute FooType):
@Entity
public class Foo {

    protected FooType type;
    @Enumerated(EnumType.STRING)
    public FooType getType() { return type; }
    public void setType(FooType type) { this.type = type; }
}
DAO method to find all Foos by FooType:
public List findAllFooByType(FooType type) {
     CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
     CriteriaQuery cq = cb.createQuery(Foo.class);
     Root invitation = cq.from(Foo.class);
        cq.where( 
          cb.equal(invitation.get(Foo_.type), type));
        cq.select(invitation);
     TypedQuery typedQuery = getEntityManager().createQuery(cq);
     return typedQuery.getResultList();
}

References

http://blogs.oracle.com/Lance/entry/generating_the_jpa_2_0

JPA: How to add unique constraint on an attribute

References

http://stackoverflow.com/questions/1839186/unique-constraint-check-in-jpa

Oopen Issue

Open issue:An issue yet unsolved is how to catch properly the exception reason and present it to the user. For example when a user signs up I do not want to allow the use of an existing username.

Friday, 27 January 2012

JPA/Hibernate error: cannot simultaneously fetch multiple bags

Solution: replace all instances of List (ArrayList) by Set (HashSet)

References

First read StackOverflow for the reason behind the error (tip: JPA annotations are parsed not to allow more than 2 eagerly loaded collection). Definitely read the excellent article of explodingjava about the problem and an in depth analysis how to solve it.

JPA: where by enum

Entity object Foo containing enum MyEnum:
@Entity
class Foo implements Serializable {

 // ....

 private MyEnum e;

 @Enumerated(EnumType.STRING)
 public MyEnum getE() {
   return e;
 }
 
 public void setE(MyEnum e) {
   this.e = e;
 }

 // ....

}
JPA Criteria query: find all Foo containing MyEnum==method parameter e:
public List findByMyEnum(MyEnum e) {
  CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
  CriteriaQuery cq = cb.createQuery(Foo.class);
  Root foo = cq.from(Game.class);
  cq.where( cb.equal(game.get(Foo_.e), e) );
  cq.select(foo);
  TypedQuery typedQuery = getEntityManager().createQuery(cq);
  return typedQuery.getResultList();
}

JPA+Hibernate: How to show the bounded values instead of the question marks on the queries

log4j.properties:
#log4j.logger.org.hibernate=INFO, hb
log4j.logger.org.hibernate.SQL=DEBUG
log4j.logger.org.hibernate.type=TRACE
#log4j.logger.org.hibernate.hql.ast.AST=info
#log4j.logger.org.hibernate.tool.hbm2ddl=warn
#log4j.logger.org.hibernate.hql=debug
#log4j.logger.org.hibernate.cache=info
#log4j.logger.org.hibernate.jdbc=debug

#log4j.appender.hb=org.apache.log4j.ConsoleAppender
#log4j.appender.hb.layout=org.apache.log4j.PatternLayout
#log4j.appender.hb.layout.ConversionPattern=HibernateLog --> %d{HH:mm:ss} %-5p %c - %m%n
#log4j.appender.hb.Threshold=TRACE

Rereferences

http://stackoverflow.com/questions/2536829/hibernate-show-real-sql

Thursday, 19 January 2012

Ignore a parent class when Serializing to XML

Scenario: I use JPA and have create a Generic Entity entity which extend all the classes that I want to persist. Now I want some classes to be serialized into XML with JAXB. But I get an Exception because Serializable cannot be serialized into XML by JAXB. Code with error:
// "implements Serializable" gives Exception #1
public class GenericEntityImpl implements Serializable {

// gives Exception #2
protected PK id = null;
// gives Exception #3
protected Locale locale;

}
@XmlRootElement(name="child")
public class Child extends GenericEntityImpl {



}
Exception:
Caused by: com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 3 counts of IllegalAnnotationExceptions
java.io.Serializable is an interface, and JAXB can't handle interfaces.
 this problem is related to the following location:
  at java.io.Serializable
  at public java.io.Serializable core.domain.GenericEntityImpl.getId()
  at core.domain.GenericEntityImpl
  at foo.Child
java.io.Serializable does not have a no-arg default constructor.
 this problem is related to the following location:
  at java.io.Serializable
  at public java.io.Serializable core.domain.GenericEntityImpl.getId()
  at core.domain.GenericEntityImpl
  at foo.Child
java.util.Locale does not have a no-arg default constructor.
 this problem is related to the following location:
  at java.util.Locale
  at public java.util.Locale core.domain.GenericEntityImpl.getLocale()
  at core.domain.GenericEntityImpl
  at foo.Child
Code without error (recommendation link):
@XmlAccessorType(XmlAccessType.NONE)
public class GenericEntityImpl implements Serializable {

// same

}
@XmlRootElement(name="child")
public class Child extends GenericEntityImpl {

// same

}
Notes: Tried adding on GenericEntityImpl the annotation @XmlTransient but didn't work. Also tried adding to Child the annotation @XmlAccessorType(XmlAccessType.FIELD) and moving all the JAXB annotation on the attributes but didn't work either (see this recommendation); note that the JPA annotations are on the methods.

Friday, 23 December 2011

JPA: how to save a List of Blob


@Entity
@Table(name="FOO")
public class FOO {

 // Item should implement Serializable; do not
 // add here any JPA annotations
 public ArrayList getItems() {...}
}

// no JPA annotations
public class Item implements Serializable {


}

References

StackOverflow

Wednesday, 14 December 2011

JPA: DO NOT PUT CascadeType in both parts of a two class-relationship (1-1,m-n,n-m,whatever)!!!

JPA: DO NOT PUT CascadeType in both parts of a two class-relationship (1-1,m-n,n-m,whatever)!!! Assume a Boy who has many Toys (1-n relationship). Boy.java
@OneToMany(targetEntity=Toy.class, mappedBy="Toy", fetch=FetchType.EAGER)//CascadeType here?
public Set getToys() {
 return toys;
}
Toy.java
@ManyToOne//CascadeType here?
@JoinColumn(name="BOY_ID")
public Boy getBoy() {
 return boy;
}
Where should I put the Cascade? In Boy or in Toy?Or in both? ANSWER: only in one of them. If you put it in both then one will override the other!!

Example #1 (wrong: overriding cascade)

cascade=CascadeType.ALL in Boy:getToys()
cascade={CascadeType.PERSIST,CascadeType.MERGE} in Toy::getBoy()
// throws exception "Deleted entity passed to persist"
entityManager.deleteById(toy.getId());

Example #2 (right)

cascade={CascadeType.PERSIST,CascadeType.MERGE} only in Toy::getUser()
//works fine :)
entityManager.deleteById(toy.getId());

Sunday, 27 November 2011

JSF error: on ElementCollection of enum Caused by: java.lang.IllegalArgumentException: Unknown name value for enum class javax.persistence.EnumType: MY_TYPE_A

Wrong (targetClass = EnumType.class):

@ElementCollection(targetClass = EnumType.class)
 @JoinTable(name = "A__LINK__MY_TYPE", joinColumns = @JoinColumn(name = "MY_TYPE_FK"))
 @Enumerated(EnumType.STRING)
 public Set getMyTypes() {
  return myTypes;
 }

Correct (targetClass = MyType.class):

@ElementCollection(targetClass = MyType.class)
 @JoinTable(name = "A__LINK__MY_TYPE", joinColumns = @JoinColumn(name = "MY_TYPE_FK"))
 @Enumerated(EnumType.STRING)
 public Set getMyTypes() {
  return myTypes;
 }

JPA: FetchType default values

  • @OneToOne: EAGER
  • @OneToMany: LAZY
  • @ManyToOne: EAGER
  • @ManyToMany: LAZY
As far as I can figure it out (at least it make sense) if a table (class) contains the Foreign Key (FK) then a join is not necessary (except for the ManyToMany case) and therefore it's EAGER :)

References

@OneToOne @OneToMany @ManyToOne @ManyYoMany

Thursday, 24 November 2011

JPA/SQL: a column cannot have the name "references"

If a column has the name "references" then I cannot create the table....Obviously it's illegal! Why??? Is there any conflict with foreign keys?? Updated: 4 Dec 2011 For example the Java code
private String references;
public String getReferences() {
  return references;
}
public void setReferences(String references) {
  this.references = references;
}
translates into the following SQL:
create table ...,references varchar(255),
and MySLQ thinks that the column is a Foreign Key...which is invalid syntax... In order to solve this just rename references into (eg) ref

JPA: Collection of enums

Wrong annotations

@OneToMany(cascade=CascadeType.ALL)
@Enumerated(EnumType.STRING)
public List getMyEnum() { ... }

Right annotations

@ElementCollection
@JoinTable(name = "DB_MYCLASS__LINK__MYENUM", joinColumns = @JoinColumn(name = "MYENUM_FK"))
@Enumerated(EnumType.STRING)
public List getMyEnum() { ... }

Friday, 11 November 2011

JPA/Hibernate reminder: initialize all fields! if not then set it to null

If I don't initialize a field then I get a transient exception.
If I initialized it by calling a class constructor then the new object is
persisted to db. What if I want this Foreign Key (FK) to be empty?

solution: If I initialize it to null then everything it's ok (why?).

Note: If I remove the CascadeType.ALL then I get again the transient exception

References

http://cagataycivici.wordpress.com/2005/11/15/pivefacedwith/