jpa etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
jpa etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

11 Temmuz 2012 Çarşamba

JPA tips 2


A previous post about this topic: http://hilaltarakci.blogspot.com/2011/03/jpa-tips.html

Actually, long version of this post includes notes taken while i was reading Chapter 9- Working with Objects of book Java Persistence with Hibernate (http://www.manning.com/bauer2/). However, i could not post it because of the copyright rules..

 But at least, i can recommend to buy the book and read the whole chapter..

25 Mart 2011 Cuma

JPA tips

In this post, i tried to summarize Java Persistence API: Best Practices slides prepared by Carol McDonald and available at http://www.slideshare.net/caroljmcdonald/td09jpabestpractices2.



Two types of persistence context:

  • · Transaction scoped
  • · Extended scoped persistence context




Configure L2 caching for entities that are

  • · read often
  • · modified infrequently
  • · Not critical if stale

protect any data that can be concurrently modified with a locking strategy

  • · Must handle optimistic lock failures on flush/commit
  • · configure expiration, refresh policy to minimize lock failures

Configure Query cache

  • · Useful for queries that are run frequently with the same parameters, for not modified tables

Navigating Entity Relationships

Data fetching strategy

  • · EAGER – immediate

    · LAZY – loaded only when needed

    · LAZY is good for large objects and/or with relationships with deep hierarchies




Database Design Tips

Smaller tables use less disk, less memory, can give better performance

> Use as small data types as possible

> use as small primary key as possible

> Vertical Partition:

split large, infrequently used columns into a separate one-to-one table

Use good indexing

> Indexes Speed up Querys

> Indexes slow down Updates

> Index columns frequently used in Query Where claus


Mapping Inheritance Hierarchies





Transactions

Do not perform expensive and unnecessary operations that are not part of a transaction

> Hurt performance

> Eg. logging – disk write are expensive, resource contention on log

Do not use transaction when browsing data

> @TransactionAttribute(NOT_SUPPORTED)


There is also a blog entry of the same writer about JPA caching, possibly initiated from the slides at http://www.slideshare.net/caroljmcdonald/td09jpabestpractices2 . (http://blogs.sun.com/carolmcdonald/entry/jpa_caching)


22 Aralık 2010 Çarşamba

using blob field with jpa and web services

In the project, client side has to store local machine specific data in the cenral database and this field has to be binary large object (blob).. Jpa with hibernate is used as orm tool..Unfortunately, according to http://opensource.atlassian.com/projects/hibernate/browse/JPA-8 jpa does not support java.sql.Blob.. Indeed, the following error shows up when i tried to do so:
// bean
import java.sql.Blob;
import javax.persistence.Lob;

class MyClass{
@Lob
@Column(name = "FLD_BLOB")
private Blob myBlob;
...
}

// the error when deployed on Glassfish (jaxws is used for web services)
javax.xml.ws.WebServiceException: Unable to create JAXBContext ...
Caused by: java.security.PrivilegedActionException: com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 2 counts of IllegalAnnotationExceptions
java.sql.Blob is an interface, and JAXB can't handle interfaces.
this problem is related to the following location:
at java.sql.Blob
at public java.sql.Blob
...
java.sql.Blob does not have a no-arg default constructor.
...
java.sql.Blob is an interface, and JAXB can't handle interfaces.
...

So, use byte [] instead of java.sql.Blob

Web service using the bean with blob field is succesfully deployed and in the wsdl, the blob field is like this:
< xs:element name= " myBlob " type= " xs:base64Binary " minoccurs= " 0 " >
Moreover, when client side stubs are generated, the field is again generated as byte []..

Testing the blob field:
I used the code at http://www.java-tips.org/java-se-tips/java.io/reading-a-file-into-a-byte-array.html in order to prepare test data from a file and the following lines to write back the read bytes into a file to test correctness:

FileOutputStream fos = new FileOutputStream( "blobDataReadFromDB.png");
fos.write(myBean.getMyBlob());

The test data is a 5.4 MB-mp3.

Two test cases are considered.
In the first test case, the web services are treated as applications and tested without deployment. The blob field is successfully persisted and retrieved from database in this case..
In the second test case, web services are deployed and then tested.. The blob data is persisted successfully, but, the following error shows up when trying to retreive the data: (the underlying database is postgresql..)
ERROR org.hibernate.util.JDBCExceptionReporter - Large Objects may not be used in auto-commit mode.
...
sun-org.hibernate.exception.GenericJDBCException: could not execute query at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:103)
....
Caused by: org.postgresql.util.PSQLException: Large Objects may not be used in auto-commit mode.
at org.postgresql.largeobject.LargeObjectManager.open(LargeObjectManager.java:200)

Here is someone in a similar situation: https://forum.hibernate.org/viewtopic.php?f=1&t=994742&start=0 The following answer in this link, worked for me:

You might need to put your DB operations into a transaction:
session.beginTransaction();
...
session.getTransaction().commit();

Normally, retrieve operations do not require a transaction since they leave the database unchanged.. You only use transactions for create, update and delete operations since they change database state.. However, retrieval of blob field require transaction as well, maybe due to paging..

I also used and tested the blob field through a bpel process.. Again, persistence and retrieval is successful..

13 Aralık 2010 Pazartesi

persistence using jpa

I have one database, but the atomicity of transactions is large. In other words, many entities must be manipulated in one transaction. Therefore, the design is something like that:
  • a general superclass entity that holds shared stuff amongst all other entities that are subject to be persisted.
  • an entity manager class that is responsible for creation of emf and em.
  • a general dao for the superclass mentioned above, to accomplish shared, general persistence tasks (crud operations - create, retrieve, update, delete ). The entity class type and an entity manager is injected to this dao.
  • specific dao classes for entities that needs operations other than crud. Something to note down is that since transaction management must be done in an upper layer in this case, no begin, commit or rollback transaction operation appear at dao (persistence) layer.
// general superclass
@MappedSuperclass
public class MyBean implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.TABLE)
private Long id = -1L;
// ...
}

//////////////////////////////////////////////////////////////
// a specific class
public class SpecificBean extends MyBean {
// ...
}

//////////////////////////////////////////////////////////////
// entity manager class
public class MyEntityManager {

private static final String PERSISTENCE_UNIT = "MyPU";

@PersistenceUnit(unitName = PERSISTENCE_UNIT)
private EntityManagerFactory emf;

public EntityManager getEm() {
if (emf == null) {
emf = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT);
}
return emf.createEntityManager();
}
}

//////////////////////////////////////////////////////////////
// general dao for superclass MyBean
public class MyBeanDao {

private Class clazz;
protected EntityManager em;

public MyBeanDao(Class clazz, EntityManager em) {
this.clazz = clazz;
this.em = em;
}

public void create(MyBean bean) {
em.persist(bean);
}

public MyBean retrieve(Long id) {
return (MyBean) em.find(this.clazz, id);
}

public void remove(Long id) {
MyBean bean = retrieve(id);
if (bean != null) {
em.remove(bean);
}
}

public MyBean update(MyBean bean) {
MyBean updated = em.merge(bean);
return updated;
}

public void closeEm() {
em.close();
}

public void initTransaction() {
em.getTransaction().begin();
}

public void finishTransaction() {
em.getTransaction().commit();
}

public void rollbackTransaction() {
em.getTransaction().rollback();
}
}

//////////////////////////////////////////////////////////////
// specific dao classes
public class SpecificDao extends MyBeanDao {

public SpecificDao (EntityManager em) {
super(SpecificBean.class, em);
}
// extra methods
}

//////////////////////////////////////////////////////////////
// sample call

MyEntityManager mem = new MyEntityManager ();
EntityManager em = mem.getEm();

SpecificDao dao = new SpecificDao (em);

dao.initTransaction();
// do something
// ....
dao.finishTransaction();



more effective solutions may exist.. this is just a sample design..

11 Şubat 2010 Perşembe

trouble in persisting type List <String> in jpa

Trying to persist an attribute with type List causes trouble in jpa.
here is a link: http://stackoverflow.com/questions/287201/how-to-persist-a-property-of-type-liststringin-jpa
the solution is changing from List to String with separated values with delimiter..
the explanation by Bill James at Nov 13 '08 at 15:34 (the above link) seems good..

5 Kasım 2009 Perşembe

named query

named query is a great tool provided by jpa while developing your dao classes.. (i mean it is used while developing dao classes, not tool for doing the job itself..)



18 Ekim 2009 Pazar

Could not execute JDBC batch update

the error Could not execute JDBC batch update comes out when the entities are as follows and you are trying to save the parent entity:

parent entity
  @OneToMany(cascade = CascadeType.ALL)
   @JoinTable(name = "TBL_INCIDENT_ABSEVIDGRP", joinColumns = {
        @JoinColumn(name = "FLD_INCIDENT_ID")
    },
    inverseJoinColumns = {
        @JoinColumn(name = "FLD_ABSEVIDGRP_ID")
    })
private List childList = new ArrayList();

child entity
    @ManyToOne
    @JoinTable(name = "TBL_INCIDENT_ABSEVIDGRP", joinColumns = {
        @JoinColumn(name = "FLD_ABSEVIDGRP_ID")
    },
    inverseJoinColumns = {
        @JoinColumn(name = "FLD_INCIDENT_ID")
    })
private Parent parent;

the error is solved by commenting out the green and bold code portion..
the lack of red code portion leads to the following error while saving the parent entity:
Error while commiting the transaction
javax.persistence.RollbackException: Error while commiting the transaction
        at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:71)
...
Caused by: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: Child Entity
 

6 Ekim 2009 Salı

notes on schuchert jpa tutor 4

finally the last tutor at http://schuchert.wikispaces.com/JPA+Tutorial+4+-+Inheritance+and+Polymorphic+Queries

lets move!
now, all tests should pass..
well, time to go to my own project, thanks to schuchert, tutors are really helpful :)

notes on schuchert jpa tutor 3

now the tutor i follow is http://schuchert.wikispaces.com/JPA+Tutorial+3+-+A+Mini+Application

lets see what happens..

so perfect, just in test methods of LibraryTest, the assertEquals methods used to compare floats that take 2 params are deprecated. Instead define a delta as follows and pass it as 3rd param to mentioned methods. Thus, tests will pass i think :)
private static final float DELTA = (float) 0.0;
...
assertEquals(.., .., DELTA);




5 Ekim 2009 Pazartesi

notes on schuchert jpa tutor 2

the tutor is at http://schuchert.wikispaces.com/JPA+Tutorial+2+-+Working+with+Queries+1

lets follow..
  • comment out the exception in the  unsuccessfulSingleResultTooManyEntries  test case of QueriesTest.. thus, it will pass..
 @Test// (expected = NonUniqueResultException.class)
    public void unsuccessfulSingleResultTooManyEntries() {
insertPerson();
        insertPerson();

        // This will fail because we expect a single result
        // but in fact there are 2 results returned.
        em.createQuery("from Person").getSingleResult();
    }

this is because,  getSingleResult() does not get angry when there are more than one records and just picks the first one..



4 Ekim 2009 Pazar

notes on schuchert jpa tutor 1

i am following schuchert's jpa tutor 1 at http://schuchert.wikispaces.com/JPA+Tutorial+1+-+Getting+Started
however, my environment is netbeans 6.5 + glassfish v2 + postgre..
lets note down some drawbacks i faced:
  • i get the following error while trying to run PersonTest :
Testcase: emptyTest(entity.PersonTest):        Caused an ERROR
[PersistenceUnit: SchuchertJpaTutor1PU] Unable to build EntityManagerFactory
javax.persistence.PersistenceException: [PersistenceUnit: SchuchertJpaTutor1PU] Unable to build EntityManagerFactory
        at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:677)
        at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:126)
        at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:51)
        at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:33)
        at entity.PersonTest.initEmfAndEm(PersonTest.java:24)
Caused by: org.hibernate.HibernateException: Could not find datasource
        at org.hibernate.connection.DatasourceConnectionProvider.configure(DatasourceConnectionProvider.java:56)
        at org.hibernate.connection.ConnectionProviderFactory.newConnectionProvider(ConnectionProviderFactory.java:124)
        at org.hibernate.ejb.InjectionSettingsFactory.createConnectionProvider(InjectionSettingsFactory.java:29)
        at org.hibernate.cfg.SettingsFactory.buildSettings(SettingsFactory.java:62)
        at org.hibernate.cfg.Configuration.buildSettings(Configuration.java:2009)
        at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1292)
        at org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory(AnnotationConfiguration.java:859)
        at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:669)
Caused by: javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file:  java.naming.factory.initial
        at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:645)
        at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:288)
        at javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:325)
        at javax.naming.InitialContext.lookup(InitialContext.java:392)
        at org.hibernate.connection.DatasourceConnectionProvider.configure(DatasourceConnectionProvider.java:52)

Testcase: emptyTest(entity.PersonTest):        Caused an ERROR
null
java.lang.NullPointerException at entity.PersonTest.cleanup(PersonTest.java:31)
Test entity.PersonTest FAILED

to fix:
- use in memory database in unit tests with persistence.xml as follows:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.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_1_0.xsd">
<persistence-unit name="SchuchertJpaTutor1TestPU" transaction-type="RESOURCE_LOCAL">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <non-jta-data-source></non-jta-data-source>
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    <properties>
        <property name="hibernate.connection.url" value="jdbc:hsqldb:mem:unit-testing-jpa"/>
        <property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver"/>
        <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
        <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
        <property name="hibernate.connection.username" value="sa"/>
        <property name="hibernate.connection.password" value=""/>
    </properties>
  </persistence-unit>
</persistence>
- add hsqldb.jar and (possibly) servlet.jar to test libs 

and run the test again, it should pass now..

  • when Address is added to Person, delete the final keyword from getter and setter methods for address.(it results in compile error..)

i will continue with the next tutorial, so see you at the next blog entry :)

7 Eylül 2009 Pazartesi

jpa inheritance mechanism

i do not reinvent the wheel by explaning jpa inheritance mechanism here, it is already well documented at many places one of which http://windhood.wordpress.com/2009/03/03/jpa-inheritance-overview/

instead, i mention a bug i have met.. i think it is a bug, correct me if i am wrong :)

assume there is a root class ClassA which ClassB inherits from.. and there is a ClassC which inherits from ClassB..

@Inheritance(strategy=InheritanceType.JOINED)
public ClassA {
...
}

@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public ClassB extends ClassA {
...
}

public ClassC extends ClassB {
...
}

It does not matter which inheritance type you specified for ClassB, for all hierarchy, the inheritance type specified for ClassA, the very root class, is used. 
In above case, the inheritance strategy is JOINED for all..

well, that is all.. 

19 Ağustos 2009 Çarşamba

converting java classes to schema: schemagen

schemagen tool comes with jaxb reference implementation and can be used to generate schemas from java classes. here is the command line version http://java.sun.com/webservices/docs/2.0/jaxb/schemagen.html and ant version https://jaxb.dev.java.net/jaxb20-ea/docs/schemagenTask.html When command line version is used, the names of the generated schema files are given automatically as schema1.xsd, schema2.xsd,.. etc. (one schema file per namespace). However, controlling names of files is possible when ant task is used, so i prefer using ant task.
Here is my sample schemagen ant file:

<?xml version="1.0" encoding="UTF-8"?>
<project name="projectname" default="generate-schema" basedir=".">

<path id="classpath">
<pathelement location="path/to/classes"/>
<fileset dir="/path/to/jaxb/lib">
<include name="**/*.jar"/>
</fileset>
</path>

<taskdef name="schemagen" classname="com.sun.tools.jxc.SchemaGenTask">
<classpath refid="classpath"/>
</taskdef>

<target name="generate-schema">
<schemagen srcdir="path/to/src" destdir="path/to/generatedfiles">
<classpath refid="classpath"/>
<schema namespace="http://namespace" file="nameOfMySchema.xsd" />
</schemagen>
</target>

</project>

However, if java classes contains jpa specific annotations, the apt tool could not handle this and throw annotation specific exceptions when the lib coming with jaxb ri is used in the classpath.
Annotations for Persistence part on http://www.devx.com/Java/Article/34069/0/page/1 solves this. download sample code on http://assets.devx.com/sourcecode/18778.zip and use the lib coming with the sample on path 18778/JAXB/lib. Actually, the above ant file is a simplified version of 18778/JAXB/3-JAXB and JPA/build.xml coming with the example..

So, it is ok for now :)

29 Haziran 2009 Pazartesi

a sample web based application

i am developping a homework web based application by using the following technologies:
  • apache tomcat 6.0.18, installed with Netbeans 6.5.1
  • toplink (with jpa annotations) for persistence, netbeans automatically creates jpa controller classes
  • jsf, using jsf framework of netbeans, netbeans automatically creates jsf classes and crud pages
  • derby database, coming bundled with netbeans and can be easily managed inside the ide
  • web services, jaxws, using netbeans facilities during development (actually independent from jpa part)
Steps for jpa part:
  1. create a web application with jsf framework added, select tomcat as server runtime.
  2. create a database from databases under services tab. (use that db in the following step) (http://www.netbeans.org/kb/60/ide/java-db.html may help)
  3. create a persistence unit, selecting toplink, the created db in the above step and drop and create as table generation strategy.
  4. create entity classes
  5. generate jsf faces from entity classes
  6. deploy and try from localhost something like that : http://localhost:8084/Registration/faces/welcomeJSF.jsp, do not forget to put faces in the address, that makes the faces servlet deal with that page.
  7. add derbyclient.jar manually (under /opt/sun/javadb/lib in my linux environment ) if you get the following error during run:

Exception [TOPLINK-4003] (Oracle TopLink Essentials - 2.0.1 (Build b09d-fcs (12/06/2007))): oracle.toplink.essentials.exceptions.DatabaseException
Exception Description: Configuration error. Class [org.apache.derby.jdbc.ClientDriver] not found.


and deploy and try again!

my project is working :)

Steps for web service part:

  1. create the web service and deploy again.. if successful, you should see the wsdl at somewhere like that http://localhost:8084/Registration/RegistrationWS?wsdl, generated jpa controller classes can be used within web service operations.
  2. create an other web aplication project. this will be the client that makes use of all deployed web services.
  3. in the client web app, generate the web service client from wsdl.
  4. crate a .jsp file in which you call the web service. this can be done automatically by right clicking in jsp and selecting 'Web Services Client Resources -> Call Web Servicve Operation'
  5. deploy the client web app and test from localhost..

Edit on 20.15 : if you get the following error while generating jsf from entity classes,

Could not find Id property. Be sure the accessor method name matches the variable name.

just move the jpa annotations from variable declarations to accessor methods. That fixed the problem in my case. btw, i faced this problem in Windows Xp, but in OpenSuse everything was fine already..