Sunday, 12 August 2012

JPA Entity, Embeddable and Authorized Types

Introduction

JPA stands for Java Persistence API.  It is a mean by which developers can easily describe how to persist the data contained in Java objects using some annotations and a configuration file called persistence unit. This API is made available in the javax.persistence package. Typically, JPA is used in combination with an implementing framework (such as Hibernate for example).

This post is the first of a series introducing JPA with practical examples. It can be read like a reminder too. The code examples are are available from Github in the JPA directory. We will start with some basic annotations first.

@Entity

An entity creates a relationship between a Java class and (typically) a database table.
  • An entity class must have at least a public or protected constructor with no argument.
  • An entity class must have an @Id.
  • An entity class must not be final or have final variables.
  • The variables (or attributes) of an entity class to be persisted must be private, protected or package-private, and must be accessed via setter and getters from outside the class.
  • An entity class must implement Serializable in order to be transmittable in a detached status.

@Embeddable

An embeddable class is nearly an entity class, except that it cannot be persisted by itself alone. It can be used as a 'component' containing data to be persisted, in another entity.
Embeddable example:
@Embeddable
public class SomeEmbeddable implements Serializable {

    private String s;

    public SomeEmbeddable() { }

    public String getS() { return s; }
    public void setS(String s) { this.s = s; }

}

Authorized Types

The following entity example regroups the authorized types for persistence:
@Entity
public class AuthorizedTypes implements Serializable {

    @Id
    private long id;

    // Primitives

    private boolean bool;
    private Boolean bool2;
    private byte byt;
    private Byte byt2;
    private char c;
    private Character c2;
    private double dou;
    private Double dou2;
    private float floa;
    private Float floa2;
    private int i;
    private Integer i2;
    private long l;
    private Long l2;
    private short s;
    private Short s2;

    // Serializable types

    private String str;
    private BigInteger bi;
    private BigDecimal bd;
    private Serializable userDefined;
    private byte[] ba;
    private Byte[] ba2;
    private char[] ca;
    private Character[] ca2;

    public enum Color { WHITE, BLACK, RED; }
    private Color col;

    // Other entities and embeddables

    @OneToOne
    private OtherEntity otherEntity;

    private SomeEmbeddable someEmbeddable;

    @ElementCollection
    private Collection<SomeEmbeddable> coll;

    @ElementCollection
    private Set<SomeEmbeddable> st;

    @ElementCollection
    private List<SomeEmbeddable> list;

    @ElementCollection
    private Map<String, Serializable> mpp;

    // Time-related

    // Keeps date only
    @Temporal(TemporalType.DATE)
    private java.util.Date MyDate;

    // Keeps time only
    @Temporal(TemporalType.TIME)
    private java.util.Date MyTime;

    // Keeps date and time
    @Temporal(TemporalType.TIMESTAMP)
    private java.util.Date MyTimestamp;

    @Temporal(TemporalType.TIMESTAMP)
    private java.util.Calendar cal;

    // Keeps date only
    private java.sql.Date sqlDate;

    // Keeps time only
    private java.sql.Time sqlTime;

    // Keeps date and time
    private java.sql.Timestamp sqlTimeStamp;

    // Setters & Getters....

}
These are the basic persistence elements one can use and combine in entities. The above needs more configuration to be fully operational. It is only an illustration of concepts.

8 comments:

  1. Hi Jérome,

    I tried to run your example code from GitHub but hitting some roadblocks.

    I imported the whole JPA project in Eclipse and manage to compile everything. Now, I'm trying to run one of the examples (SelectFrom.java), but get this error message:

    log4j:WARN No appenders could be found for logger (org.jboss.logging).
    log4j:WARN Please initialize the log4j system properly.
    log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
    Exception in thread "main" java.lang.ExceptionInInitializerError
    at com.jverstry.jpa.CriteriaAPI.SelectFrom.main(SelectFrom.java:21)
    Caused by: javax.persistence.PersistenceException: No Persistence provider for EntityManager named JPA
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:69)
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:47)
    at com.jverstry.jpa.JPA.(JPA.java:18)
    at com.jverstry.jpa.JPA.(JPA.java:11)
    ... 1 more

    Apparently when executing the example, the reference to the persistence.xml file is not properly resolved. Any idea?

    Thanks.

    Marc

    ReplyDelete
  2. Hi, my examples were developed with NetBeans.

    I have just checked again and the persistence.xml file is within /src/main/resources/META-INF/persistence.xml. This makes sure the file is available at the right location in the Jar during execution. Eclipse may not be happy with this original location or you may have not copied this file too.

    If this is does not solve your issue, I recommend you to ask a question at stackoverflow.com. People with more Eclipse experience than me will surely be more qualified to help you with this issue.

    ReplyDelete
  3. Hi Jérome , persistence xml must be placed on META-INF directory under src folder in eclipse like src/META-INF/persistence.xml, for resolving logj error just add log4j jar on your classpath.

    ReplyDelete
    Replies
    1. Thanks, I guess this will help Marc! I think this also has to do with Maven project structures. My example is implemented as a Maven project, which explains why I have put my persistence under /src/main/resources/META-INF/persistence.xml. May be Marc's project is not a maven project...

      Delete
    2. hi jerome, when i tried to run the e.g "com.jverstry.jpa.CriteriaAPI.SelectFrom" , importing it as maven project in eclipse juno, I faced this error.
      ------------------
      Exception in thread "main" java.lang.ClassFormatError: Absent Code attribute in method that is not native or abstract in class file javax/validation/Validation
      ------------------
      http://www.mkyong.com/hibernate/java-lang-classformaterror-absent-code-attribute-in-method-that-is-not-native-or-abstract-in-class-file/

      showed a solution. But its also not helping me out.

      Delete
    3. It looks like a dependency issue. Have you checked this: http://stackoverflow.com/questions/15386950/classformaterror-absent-code-attribute-in-method-that-is-not-native-or-abstract ?

      Delete
    4. jerome, i tried adding this dependency , but didnt help.


      org.jboss.spec
      jboss-javaee-6.0
      1.0.0.Final
      pom
      provided


      its still giving the same error..

      Delete
    5. Unfortunately, I don't have experience with eclipse juno. I suggest you ask a question on stackoverflow.com itself. There is surely someone with more Eclipse experience than me who will help you.

      Delete