- 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.
>>>ITwacht<<<
You can find the specification here.
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;
}
}
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;
}
}
Reference implementation.
Official documentation:
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.
JPA 2 (JSR 317) is a superset of JPA 1 and part of Java EE6. Added features include:
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");
@Entity
@NamedEntityGraph(name="withBids", attributeNodes={@NamedAttributeNode("bids")})
public class Auction
{...}
Properties prop = new Properties();
prop.put("javax.persistence.loadgraph", em.getEntityGraph("withBids"););
Auction eagerBids= em.find(Auction.class, auction_id, prop);
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();
}
//...
}
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();
}
}
private EntityManager getEntityManager()The method should return an EntityManager created from the EntityManagerFactory attribute
public Item save(Item item)
import static org.junit.Assert.*;
assertFalse("id should not be null", item.getId()==null);
public Item findByPrimaryKey(Long id)
public void deleteByPrimaryKey(Long id)
private Long auctionId; private BigDecimal startAmount; private BigDecimal increment; private String status; private Date openTime; private Date closeTime; private Item item;
import static org.junit.Assert.*;
static AuctionDao auctionDao;
@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);
}
public void addBid(Bid bid) public int getBidCount()
public void addKeyword(String keyword) public List<String> getKeywords()
DELETE FROM Item i
@NamedQueries( {
@NamedQuery(name="xxx",query="XXXX"),
@NamedQuery(name="yyy",query="YYY") }
@Embeddable
public class BookPk implements Serializable{
private String title; private int edition;
private List<String> authors; private int yearPublished;
".*\\.jpg"
fail("picture.gif should fail validation");
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:
In practice, the biggest difference after abandoning JDO/JPA is that you will stop screaming loudly at your computer, annoying your coworkers.
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 />
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.Still JPA compliancy requires the instanceof operator to work correctly.
Gavin King