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

9 August 2022

Jakarta persistence 3.1 highlights

  • autocloseable EntityManager and EntityManagerFactory
  • Criteria CASE expression support Expressions as conditions
  • JPQL (and criteria API)
    • CEILING, EXP, FLOOR, LN, POWER, ROUND, SIGN
    • LOCAL DATE/TIME/DATETIME

You can find the specification here.

30 December 2019

JPA: Composite Primary Key with Foreign Keys



 
Entity for the ProductSales Table:

package com.example.model;

import javax.persistence.*;

@Entity
@IdClass(ProductSalesPK.class)
public class ProductSales {

 @Column(name = "QUANTITY")
 private int quantity_sold;

 @Id
 @ManyToOne
 @JoinColumn(name = "sales_id")
 private Sales sales;

 @Id
 @ManyToOne
 @JoinColumn(name = "product_id")
 private Product product;

 public ProductSales() {
 }

 public ProductSales(Sales sales, Product product, int quantity_sold) {
  this.sales = sales;
  this.product = product;
  this.quantity_sold = quantity_sold;
 }

 public Product getProduct() {
  return product;
 }

 public Sales getSales() {
  return sales;
 }

 public void setProduct(Product product) {
  this.product = product;
 }

 public void setSales(Sales sales) {
  this.sales = sales;
 }

 public int getQuantity_sold() {
  return quantity_sold;
 }

 public void setQuantity_sold(int quantity_sold) {
  this.quantity_sold = quantity_sold;
 }
}

ProductSalesPK Id class:

package com.example.model;

import java.util.Objects;

public class ProductSalesPK {
    private int sales;
    private String product;

 public ProductSalesPK(int sales_id, String product_id) {
  this.sales = sales_id;
  this.product = product_id;
 }

 @Override
 public int hashCode() {
  int hash = 5;
  hash = 83 * hash + this.sales;
  hash = 83 * hash + Objects.hashCode(this.product);
  return hash;
 }

 @Override
 public boolean equals(Object obj) {
  if (obj == null) {
   return false;
  }
  if (getClass() != obj.getClass()) {
   return false;
  }
  final ProductSalesPK other = (ProductSalesPK) obj;
  if (this.sales != other.sales) {
   return false;
  }
  if (!Objects.equals(this.product, other.product)) {
   return false;
  }
  return true;
 } 
}
Entity class fpor Product:

package com.example.model;
package com.example.model;

import java.util.Objects;
import javax.persistence.*;
import javax.validation.constraints.*;
@Entity
public class Product {
 @NotNull(message="product id not null") @Size (min = 1,message="product id not empty") 
 @Id
    private String product_id; 
 @NotNull(message="product name not null") @Size (min = 10,message="product name length at least 10")
    private String prod_name;
 @Min(value=5, message="price >= {value}")
    private double price;
    private String prod_desc;

 public Product() {
 }

  
    public Product(String id, String name, double price, String description) {
        this.product_id = id;
        this.prod_name = name;
        this.price = price;
        this.prod_desc = description;
    }

    public String getId() {
        return product_id;
    }

    public String getName() {
        return prod_name;
    }

    public void setName(String name) {
        this.prod_name = name;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public String getDescription() {
        return prod_desc;
    }

    public void setDescription(String description) {
        this.prod_desc = description;
    }
    
    @Override
    public String toString() {
        String s = String.format("Product id: %s\n"
        + "Name: %s\n"
        + "Description: %s\n"
        + "Price: $%.2f", product_id, prod_name, prod_desc, price);
        return s;
    }

    @Override
    public int hashCode() {
        int hash = 3;
        hash = 97 * hash + Objects.hashCode(this.product_id);
        hash = 97 * hash + Objects.hashCode(this.prod_name);
        hash = 97 * hash + (int) (Double.doubleToLongBits(this.price) ^ (Double.doubleToLongBits(this.price) >>> 32));
        hash = 97 * hash + Objects.hashCode(this.prod_desc);
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Product other = (Product) obj;
        if (!Objects.equals(this.product_id, other.product_id)) {
            return false;
        }
        if (!Objects.equals(this.prod_name, other.prod_name)) {
            return false;
        }
        if (Double.doubleToLongBits(this.price) != Double.doubleToLongBits(other.price)) {
            return false;
        }
        if (!Objects.equals(this.prod_desc, other.prod_desc)) {
            return false;
        }
        return true;
    }
    
}

10 May 2016

JPA links (updated)

Reference implementation.

Official documentation:

Others:
Providers often have good JPA documentation as well. Might include extensions (and JDO stuff) though:

Specific topics:
Background:

    8 February 2016

    JPA CriteriaQuery call structure

    The sequence of calls and the objects involved in a CriteriaQuery is complex at first. 
    CriteriaQuery uses a fluid builder patters which mimics the structure of a JPQL/SQL query. I highlighted the creation of the parameters and the calls in which they are used.
    The parameters are not exactly those in the API, i oversimplified to give an idea of the general structure of a criteria query.


    3 February 2014

    JPA 2.x what's new (edit)

    JPA 2 (JSR 317) is a superset of JPA 1 and part of Java EE6. Added features include:

    • Entities
      • mixing of field and getter method annotations
      • JSR 303 validation
    • Relations
      • unidirectional OneToMany
      • use JoinTable for all relation cardinalities
    • Automatic actions upon Entity changes
      • CascadeType.DETACH
      • orphanRemoval: delete an orphan Entity if its relation to its parent Entity is broken
    • Collections
      • Support for mapping collections of Basic and Embeddable types (@ElementCollection)
      • Map keys and values can both be Basic, Embeddable and Entity types
    • Embeddables
      • Can be nested
      • Can have attributes with relations
      • Can inherit from a MappedSuperclass
    • Ordering
      • @OrderBy: determine order in which elements of List attributes are loaded
      • @OrderColumn: support for preserving List order in the database using an OrderColumn
    • Queries
      • TypedQuery <T>
      • Criteria API
        • metamodel generation
      • JPQL
        • functions and operations in SELECT clause
        • COALESCE function (returns first non null argument)
        • TYPE function: get class of Entity to compare with literal
        • CASE expression
        • KEY, VALUE, and ENTRY keywords for map operations
        • use of enums
        • enum and temporal literals
    • Locking
      • pessimistic locking support
      • lock mode arguments in EntityManager methods
    • Cache API
    JPA 2 is implemented in Hibernate 3.5+

    JPA 2.1 (JSR 338) is part of Java EE 7. Added features include:

    • StoredProcedureQuery
    •   StoredProcedureQuery proc = em.createStoredProcedureQuery("squareRoot");
        proc.registerStoredProcedureParameter("square", Double.class, ParameterMode.IN);
        proc.registerStoredProcedureParameter("root", Double.class, ParameterMode.OUT);
        proc.setParameter("square", 338.0);
        proc.execute();
        Double result = (Double)storedProcedure.getOutputParameterValue("root");
      
    • @Converter/@Convert: write custom code to convert java data to/from database data
    • JPQL 
      • selectively  access  entity subclasses: TREAT (relation.parentEntityAttribute AS  childEntity)
      • support for predefined and user defined database functions: FUNCTION(name,args...)
              WHERE FUNCTION (isAllowed, theater.movie, user.age)
    • update and delete using the Criteria API
    • Standardised schema generation properties 
    • Entity Graphs allow runtime control over which parts of an entity are fetched. Here's an example:
    • @Entity
      @NamedEntityGraph(name="withBids", attributeNodes={@NamedAttributeNode("bids")})
      public class Auction
      {...}
      • The Auction above has bids that are normally lazily loaded.
      • Using the entity graph you can ask for a variant where the bids are eagerly loaded:
      Properties prop = new Properties();
      prop.put("javax.persistence.loadgraph", em.getEntityGraph("withBids"););
      Auction eagerBids= em.find(Auction.class, auction_id, prop); 
      •  In addition to declaring the graph with annotations, you can construct it at runtime with an API
      • The graph can also be set as a hint to a query
    JPA 2.1 is implemented in Hibernate 4.3+

    4 November 2013

    JPA : choose your enum ordinals (Updated)

    Ordinal enums are brittle with JPA.
    If you change the order of the enum constants,
    the ordinal number that is saved to the database changes.

    You can solve that by assigning your own code in the enum (10,20,30 in the example).
    In the entity, make the enum transient.
    Before saving the entity put your code in an int attribute, which will be stored in the database.
    After loading convert the int back to the enum.

     Update: In JPA 2.1 you can also do this with @Converter


    public enum Status{
      OPEN(10), CLOSED(20), CANCELLED(30);
      private int code;  
      
      private Status(int code) {  
        this.code = code;  
      }  
           
      public int getCode() {  
        return code;  
      }
         
      public static  Status getStatus(int code){
        for (Status stat : Status.values()) {
          if (stat.getCode()==code) return stat;
        }
        return null; // not found: invalid code
      }
    }
           
    @Entity
    public class Auction{
      private int status;
      @Transient private Status statEnum;
    
      public int getStatus(){
        return status;
      }
    
       public void setStatus(int status){
        this.status = status;
      }
    
      @PostLoad private void int2enum(){
        statenum = Status.getStatus(status);
      }
    
      @PrePersist private void enum2int(){
        status = statEnum.getCode();
      }
      //...
    }


    NB: kudos to Guy for moving conversion to callbacks.

    13 March 2013

    Netbeans 7.3 comes with JPQL runner

    A welcome addition to the new Netbeans release, issued last month:


    22 April 2012

    DAO Example

    public interface AnniversaryDao {
      Anniversary getByYear(int years);
    }
    
    public class AnniversaryJdbcDao implements AnniversaryDao{
      private static final String GET_BY_YEAR = 
        "SELECT * from Anniversary WHERE years = ?";
      //...
      public Anniversary getByYear(int years) {
        //…
        PreparedStatement statement = connection.prepareStatement(GET_BY_YEAR);
        statement.setInt(1,years);
        ResultSet rs = statement.executeQuery();
        if (rs.next()){
          result = new Anniversary(
          rs.getInt("years"),
          rs.getString("material"),
          rs.getString("flowers"));
        }
       //  ....
      return result;
      }
    }
    
    public class AnniversaryJpaSeDao implements AnniversaryDao{
       EntityManagerFactory emf = Persistence
        .createEntityManagerFactory("JPA-03PU");
    
      private EntityManager getEntityManager() {
        return emf.createEntityManager();
      }
      //...
      public Anniversary getByYear(int years) {
        return getEntityManager().createNamedQuery(findAnniversayByYear)
          .setParameter("years", years)
          .getSingleResult();
      }
    }
    
    @ManagedBean
    @RequestScoped
    public class AnniversaryJpaEe6Dao implements AnniversaryDao{
      @¨PersistenceContext private EntityManager em;
    
      //...
      public Anniversary getByYear(int years) {
        return em.createNamedQuery(findAnniversayByYear)
          .setParameter("years", years)
          .getSingleResult();
      }
    }
    

    25 September 2011

    JPA labs – high level instructions (edit)

    Lab 3 Exercise 2 Task 1

    Adjusting the table and column names

    1. Create the com.acme.entities.AuctionUser entitiy
      1. Follow the same procedure as in Lab 1 Exercise 3 Task 3, steps 1-6
      2. Add the attributes shown in the Student Guide page 2-9, Figure 2-4
      3. Press ALT+INSERT to  add a default constructor and a constructor accepting all attributes except the auctionUserId
    2. Add an annotation to save the entity to the table A_USER
    3. Add an annotation to save the auctionUserId attribute to the id column
    4. Add an annotation to save the displayName attribute to the name column.
      1. Set the column length to 50.
    5. Modify the main method created in Lab 1 to save an AuctionUser entity
      1. At the beginning of the method create auctionUser JaneDoe with email address jane@doe.com
      2. After the statement to persist the item, add a similar statement to persist the user
    6. Choose Run -> Run Main Project
    7. Follow the same procedure as in Lab 1 Exercise 3 Task 3, step 9 to run the project and verify the table was created as intended and JaneDoe was inserted.

    Lab 4 Exercise 2 Task 2

    Working with the entity manager

    1. In the Item entitiy
      1. Press ALT+INSERT to generate a constructor that takes all attributes except the id as an argument
      2. Press ALT+INSERT to generate a default constructor
    2. Create the ItemDao class in the (new) com.acme.daos package
      1. Add a static EntityManagerFactory attribute
        1. Initialize the attribute with an EntityManagerFactory for your persistence unit
      2. Implement the method
        private EntityManager getEntityManager()
        The method should return an EntityManager created from the EntityManagerFactory attribute
      3. Implement the method
        public Item save(Item item) 
        1. The method should call the getEntityManager method
        2. The method should persist the item within a transaction
          1. Look at the main method for inspiration
        3. return the item
    3. Create a unit test to test the save() method.
      1. Right-click the Project node and choose New –> Other.
      2. Select JUnit from the list of Categories and JUnit Test from the list of File Types, then click Next
        1. Type ItemTest for the class name
        2. Select Test Packages as the location
        3. Type com.acme.daos for the package name
        4. Click Finish. 
        5. Select JUnit 4.x if prompted for the JUnit version:
        6. Add an import for static assertXXX JUnit utility methods:
          import static org.junit.Assert.*;
        7. Add a static ItemDao attribute. Initialise it in the @BeforeClass annotated method.
        8. Create a test method called save() to test the save() method on the ItemDao
          1. Annotate the method with @Test
        9. In the test method
          1. Create a new Item and set all attributes except the id
          2. Save the Item using the ItemDao
          3. Use the assertFalse method to test the Item id is not null
          4. assertFalse("id should not be null", item.getId()==null);
          5. Right click ItemTest.java and choose Run File
          6. If you see a green bar with 100% in it, the test passed. If you see a red bar, the test failed.
        10. In the ItemDao class, implement the following method:
          public Item findByPrimaryKey(Long id)
        11. Create an annotated test method called find  in the ItemTest class to test the findByPrimaryKey method. In this method:
          1. Create a new Item and set all attributes except the id
          2. Save the Item using the ItemDao
          3. Pass the primary key of the saved item to findByPrimaryKey to retrieve the Item from the database
          4. Use the assertEquals method to test that the key of the returned Item has the same key.
          5. Run the test and correct errors until it succeeds.
            Optional steps
          1. Create a method in the ItemDao class.
            public void deleteByPrimaryKey(Long id) 
            1. Get an entity manager
            2. Start a transaction
            3. Look up the Item using the getReference method on the entity manager
            4. Delete the item using the remove method on the entity manager
            5. Commit the transaction
          2. Create an annotated test method called find in the ItemTest class to test the deleteByPrimaryKey method. in this method:
            1. Create a new Item and set all attributes except the id
            2. Save the Item using the ItemDao
            3. Pass the primary key of the saved item to deleteByPrimaryKey to delete the Item from the database
            4. Pass the primary key of the saved item to findByPrimaryKey to retrieve the Item from the database
            5. Use the AssertNull method to verify that the item is not found.

          Lab 5 Exercise 2 Task 1

          Creating a unidirectional One-to-One relationship between two entities

          1. Create the com.acme.entities.Auction entitiy with these attributes:
            private Long auctionId;
            private BigDecimal startAmount;
            private BigDecimal increment;
            private String status;
            private Date openTime;
            private Date closeTime;
            private Item item;
            
          2. Map the Date attributes to TIMESTAMP columns using the @Temporal annotation
          3. Establish a OneToOne relation with Item
          4. Press ALT+INSERT to generate getters and setters, a default constructor and a constructor accepting all attributes except the auctionId
          5. Create the com.acme.daos.AuctionDao class
            1. Copy the static EntityManagerFactory attribute from ItemDao
            2. implement the same methods as in ItemDao, but this time for the Auction entity
          6. Create a unit test to test the save() method.
            1. Right-click the Project node and choose New –> Other.
            2. Select JUnit from the list of Categories and JUnit Test from the list of File Types, then click Next
            3. Type AuctionTest for the class name
            4. Select Test Packages as the location
            5. Type com.acme.daos for the package name
            6. Click Finish. 
          7. Add an import for static assertXXX JUnit utility methods:
            import static org.junit.Assert.*;
          8.  Add an attribute
            static AuctionDao auctionDao;
          9. Initialise it in the @BeforeClass annotated method.
        12. Create a test method called save() to test the save() method on the ItemDao
          1. you may modify the method to pass the attributes in the constructor instead of using the setters
              @Test
              public void save(){
                  Auction auction = new Auction();
                  auction.setOpenTime(new Date());
                  GregorianCalendar cal = new GregorianCalendar();
                  cal.roll(Calendar.MONTH, true);
                  auction.setCloseTime(cal.getTime());
                  auction.setStartAmount(new BigDecimal("100.00"));
                  auction.setIncrement(new BigDecimal("10.00"));
                  auction.setStatus(Status.OPEN)
                  auction = auctionDao.save(auction);
                  assertTrue("id is greater than zero", auction.getAuctionId() > 0);
              }
          
        13. Right click ItemTest.java and choose Run File. Run the test and correct errors until it succeeds.

        Lab 5 Exercise 3 Task 1

        Creating a bidirectional One-to-Many/Many-to-One relationship

        1. Add a bidirectional One-to-Many/Many-to-One relationship between Auction (1) and Bid (many)
          1. Add an annotated bids attribute to the Auction entity
            1. Set cascade mode to ALL
            2. Initialize the attribute to an empty list of bids
            3. Add an auction attribute to the Bid entity
              1. Press ALT+INSERT to generate auction getter/setter methods
              2. Add an annotation for the relationship
              3. Press ALT+INSERT to generate a constructor that takes all attributes except the id as arguments
              4. Press ALT+INSERT to generate a default constructor
              5. Implement these methods in the Auction entity
                public void addBid(Bid bid)
                public int getBidCount()
            4. Implement a saveBids() methods in the AuctionTest class
              1. Create an auction
              2. Add 3 new bids with amounts of 150, 175 and 225
              3. Save the auction
              4. Assert that the saved auction got an ID
              5. Assert that the new auction has 3 bids
              6. Run the test until it passes.

            Lab 6 Exercise 2 Task 1

            Persisting an Entity with a superclass

            1. Create an entity called com.acme.entities BookItem.
            2. Make the BookItem entity a subclass of Item.
            3. The attributes of the entity are described in module 2 of the Student Guide.
            4. In the main method add the creation of a BookItem and save it to the database.
            5. Run the main method
            6. Examine which changes were made to the database tables

            Lab 7 Exercise 2 Task 1

            Persisting an Entity with an enum Field

            1. Create the Status enum.
              1. Right click on the com.acme.entities package and choose New>Java class
                1. Type Status for the Class Name.
                2. Choose enum for the type
              2. Click OK
            2. Add these values to the enum: OPEN, CLOSED, CANCELLED
            3. Refactor the type of Auction.status and change it to Status
              1. Change getter and setter methods
              2. Change the call to setStatus in AuctionTest.java
            4. Run the AuctionTest and correct errors until it succeeds
            5. Check the database definition of Auction.status and check the inserted data. What has changed?
            6. Add an Enumerated annotation to the status field and set enumeration type to STRING
            7. Run the AuctionTest and correct errors until it succeeds
            8. Check the database definition of Auction.status and check the inserted data. What has changed?

            Lab 7 Exercise 3 Task 1

            Persisting an Entity with a List field

            1. Add a Set of String keywords to the Item entity and initialize it to an empty Set.
            2. Annotate it as an ElementCollection
            3. Implement these methods:
              public void addKeyword(String keyword)
              public List<String> getKeywords()
            4. Add an annotated test method saveKeywords() to ItemTest. You can use the test methods for bids in Auction as a source of inspiration.
            5. Run the AuctionTest and correct errors until it succeeds.
            6. Describe the database table where the keywords are saved.

            Lab 8 Exercise 2

            Performing a query with the Java Persistence API QL

            1. Add a dynamicJpqlQuery() test to the ItemTest class. In the method
              1. Perform this JPQL query (within a transaction)
              2. DELETE FROM Item i
                1. What does this query do?
              3. Create 3 Items using ItemDao.save(Item i), using different values for all atributes.
              4. Save them to the database
              5. Perform a JPQL query to retrieve  them
              6. Assert you retrieved 3 results
              7. perform a  JPQL query to retrieve only items in stock
              8. Assert you retrieved the correct number of results
            2. Optional: Add a testPaging() test method that creates 25 Items and retrieves them in groups of maximum 10. Verify that it runs correctly.

            Lab 8 Exercise 3

            Performing a query with SQL

            1. Copy the dynamicJpqlQuery() test in the ItemTest class to nativeSqlQuery()
            2. In the method replace all queries with native queries

            Lab 8 Exercise 4

            1. Add a constructor to the Item class that accepts all attributes
              1. Type ALT+INSERT into the item class
              2. Choose Constructor…
              3. Check all attributes except the ID
              4. Click Generate
            2. Add a default constructor to the Item class
              1. Type ALT+INSERT into the item class
              2. Choose Constructor…
              3. Click Generate
            3. Copy the CriteriaTest.java file from the labs08 directory to the com.acme.entities package in the test directory
            4. Examine the code
            5. Run the code

            Lab 9 Exercise 2 Task 1

            Creating and running a named query

            1. Define a named query called ClearAuctions using an annotiation on the Auction entity that deletes all auctions
            2. Define a named query called FindByStatusAuctions using an annotiation on the Auction entity. To define multiple named queries use @NamedQueries:
              @NamedQueries( {
                  @NamedQuery(name="xxx",query="XXXX"), 
                  @NamedQuery(name="yyy",query="YYY") }
              1. The query should select all auctions with a certain status
              2. Set the status in the query as a named parameter
            3. Add an annotated test method called testNamedQuery() to the AuctionTest clas.
            4. Execute the ClearAuctions query (you can find inspiration in the tests in the previous chapter)
              • Do not use the Dao, but create an EntityManager
              • Perform the delete operation within a transaction
            5. Execute the FindByStatusAuctions query to look for all closed auctions
            6. Assert no entries are found
            7. Run the test and correct errors until it succeeds
            8. Modify the testNamedQuery() test to insert three auctions and add them to the auction table
              1. Add a convenience constructor with common attributes and a default constructor to the entity
              2. The start date of the first auction should be between those of the second and the third item(we will use this in the next exercise)
              3. Only two auctions should be in open
              4. Save them using the Dao
            9. Assert one entry is found
            10. Run the test and correct errors until it succeeds

            Lab 9 Exercise 2 Task 2

            Creating multiple named queries

            1. Write a new NamedQuery FindAllAuctions that finds all auctions.
            2. Copy the testNamedQuery() test to a new test and call it testOrderedQuery()
            3. Replace the last query in the copied test method (FindByStatusAuctions) with the FindAllAuctions Query and store the results in a List
            4. Assert that the first auction starts after the second.
            5. Run the test and correct errors until it succeeds
            6. Write a new NamedQuery called FindAllOrderByOpenTimeAuctions that sorts by ascending openTime.
            7. Add the query at the end of testOrderedQuery.
            8. Assert that the first auction starts before the second.

            Lab 10 Exercise 2

            Performing a Query With Multiple Criteria

            1. Define a named query called clearItems that deletes all items. Use an annotation on the Item entity
            2. Add an annotated test method called incompleteItems() to the ItemTest class.
            3. In the incompleteItems method
              1. Call the clearItems named query
              2. Create 3 items.
                1. An Item with a description
                2. An Item with an image
                3. An Item with an image and a description
                     (Use test methods from previous labs for inspiration)
            4. Build a criteria query that selects all items that have a description OR an image that is NULL
              Hint: use CriteriaBuilder.isNull()
            5. Execute the query
            6. Assert 2 entries are found
            7. Run the test and correct errors until it succeeds

            Lab 10 Exercise 3 (extra)

            Performing a query with a named parameter

            1. Copy the incompleteItems() test method and call the copy namedParameter()
            2. Replace the query with a Criteria query that selects all items with a given description
              1. The description should be received as a parameter called “desc”
            3. Execute the query for each description in your items
            4. Assert that you get exactly one result each time
            5. Run the test and correct errors until it succeeds

            Lab 13 Exercise 2 Task 1

            Creating a Composite Key

            1. Create the BookPk class in the com.acme.enitities package
            2. Add the @Embeddable annotation and the Serializable interface to theclass declaration.
              @Embeddable
              public class BookPk implements Serializable{
            3. Add the following fields:
              private String title;
              private int edition;
              1. Right-click an empty line and choose Insert Code.
              2. Choose Getter and Setter.
              3. Select all fields and click Generate.
              4. Right-click an empty line and choose equals() and hashCode().
              5. Select all fields in the list.
              6. Click Generate.
            4. Create the TextBook entity class in the the com.acme.enitities package
              1. Add an EmbeddedId of type BookPk
              2. Add attributes
                private List<String> authors;
                private int yearPublished;
              3. Extra: Annotate the authors attribute as an ElementCollection
            5. In the main method add the creation of a BookItem and save it to the database
            6. Run the main method
            7. Examine which changes were made to the database tables 

            Lab 13 Extra: Exercise 3 Task 1

            Using validation

            This lab supposes the validator reference implementation has been downloaded to $Home/pkg

            1. In the projects window right click the libraries folder and select Add Library
              1. Click Create...
              2. Enter Library Name: Validation
              3.  Click OK
                1. Click Add JAR/Folder...
                  1.  Select $HOME/pkg/hibernate-validator/hibernate-validator*.jar
                    1. * depends on the version of validator
                2. Click Add JAR/Folder...
                  1.  Select $HOME/pkg/hibernate-validator/lib/required/validator-api-1.0.0.GA.jar
                3. Click OK
              4. Click Add Library
            2. In the Item entity annotate the image with a validation that 
              1. prints the message "Only JPG images are accepted"
              2. only accept values matching this pattern
                        ".*\\.jpg"
            3. In the ItemTest class add a test method test Validation that
              1. saves an Item with a null image
              2. saves an item with an image string ending in .jpg
              3. saves an item with an image string ending in .gif
                1. surround the last save line with a try block
                2. catch a ConstraintViolationException 
                  1. add an empty catch block
                3. in the try block add as a last line
                4.         fail("picture.gif should fail validation");
            4. Run the test and correct errors until it succeeds

            19 September 2011

            JPA entity state transitions and EntityManager methods

              • only the most common EntityManager methods/transitions are mentioned
              • void return types have been omitted
              • refresh() is also loading from the database

              15 July 2011

              NetBeans, Hibernate and JPA2

              When you create a new persistence unit in a standalone NetBeans project, it only proposes Hibernate with JPA1.
              This is because NetBeans bundles an old Hibernate release.
              To work with Hibernate/JPA2, download a recent Hibernate (>= 3.5) and SLF4J (same version as the one used in your hibernate download).
              Add a new persistence library with these jars from the hibernate installation directory:

              • hibernate3.jar
              • jars from lib/jpa folder
              • jars from lib/required folder
              • an SLF4J implementation library from the SLF4J download, e.g. slf4j-jdk14-1.6.1.jar
                • if you are using ehcache there is no need to download SLF4J separately. It bundles  slf4j-jdk14-1.6.1.jar.
              NetBeans (>= 6.9) will recognize the library as a Hibernate/JPA2 provider.

              6 April 2011

              Google App Engine: JPA or Objectify?

              In practice, the biggest difference after abandoning JDO/JPA is that you will stop screaming loudly at your computer, annoying your coworkers.
              Jeff Schnitzer

              27 November 2010

              Using JPA with Spring

              SL-370 module 1 shows an example of using JPA with Java SE.
              If you want to use Spring with JPA, the java code is just like in Java EE. Here's how the configuration files for Spring look for an example similar to the Java SE example:

              persistence.xml

              <?xml version="1.0" encoding="UTF-8"?>
              <persistence version="2.0"
              xmlns="http://java.sun.com/xml/ns/persistence"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
              http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
               <persistence-unit name="StockPU" transaction-type="RESOURCE_LOCAL">
               <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
               <properties>
                <property name="javax.persistence.jdbc.user" value="public"/>
                <property name="javax.persistence.jdbc.password" value="public"/>
                <property name="javax.persistence.jdbc.url" 
                 value="jdbc:derby:MyDB;create=true"/>
                <property name="javax.persistence.jdbc.driver" 
                 value="org.apache.derby.jdbc.EmbeddedDriver"/>
                <property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
                <property name="eclipselink.logging.level" value="SEVERE"/>
               </properties>
               </persistence-unit>
              </persistence>
              
              Spring XML configuration snippet(e.g. in application-config.xml):
              <bean id="entityManagerFactory" 
               class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean" 
               lazy-init="true">
               <property name="persistenceUnitName" value="StockPU" />
              </bean>
              <bean name="transactionManager" 
               class="org.springframework.orm.jpa.JpaTransactionManager">
               <property name="entityManagerFactory" ref="entityManagerFactory" />
              </bean>
              
              <tx:annotation-driven />
              

              28 April 2010

              Dealing with Hibernate proxies

              To deal with lazy loading Hibernate uses proxy objects.
              Pitfalls for this approach have been documented. Basically the instanceof operator can fail on a sublcass of an entity.
              The bug ticket on this has been rejected, with typical JBoss flair:

              If you think this through a bit more carefully, you will see why it is impossible.
              Gavin King
              Still JPA compliancy requires the instanceof operator to work correctly.
              Here are some ways to deal with the proxies: