Understanding JPA,3

 

Page 3 of 6

Persistence units

Now that the entity class is complete, you can move on to persistence.xml, shown in Listing 3. This is an XML file placed in the META-INF folder; it's used to specify the persistence provider name, entity class names, and properties like the database connection URL, driver, user, password, and so on.

Listing 3. A sample persistence.xml file

<?xml version="1.0"?>
<persistence>
<persistence-unit name="testjpa" transaction-type="RESOURCE_LOCAL">
<provider>
org.apache.openjpa.persistence.PersistenceProviderImpl
</provider>
<class>entity.Customer</class>
<properties>
<property name="openjpa.ConnectionURL" value="jdbc:derby://localhost:1527/D:/OpenJPA/Derby/testdb;create=true"/>
<property name="openjpa.ConnectionDriverName"
value="org.apache.derby.jdbc.ClientDriver"/>
<property name="openjpa.ConnectionUserName" value="admin"/>
<property name="openjpa.ConnectionPassword" value="admin"/>
<property name="openjpa.Log" value="SQL=TRACE"/>
</properties>
</persistence-unit>
</persistence>

Some important things to note about Listing 3 and the persistence.xml file:

  • persistence.xml can have multiple persistence units. Each unit can be used by different JPA vendor or can be used to persist to different databases.
  • The vendor-specific persistence provider name is specified in the <provider> tag. The persistence provider for OpenJPA is org.apache.openjpa.persistence.PersistenceProviderImpl.
  • The entity class names are specified in the <class> tag.
  • The database connection properties can be specified within the <properties> tag. Note that the property name will differ for each vendor.
  • OpenJPA has its own default logging facility, the default level of which is INFO.

The real show

Now that the prep work is out of the way, you're ready to write a class that will insert a record into the CUSTOMER table. This is shown in Listing 4.

Listing 4. sample code for object persistence

public static void main(String[] args) {
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("testjpa");
EntityManager em = entityManagerFactory.createEntityManager();
EntityTransaction userTransaction = em.getTransaction();

userTransaction.begin();
Customer customer = new Customer();
customer.setFirstName("Charles");
customer.setLastName("Dickens");
customer.setCustType("RETAIL");
customer.setStreet("10 Downing Street");
customer.setAppt("1");
customer.setCity("NewYork");
customer.setZipCode("12345");
em.persist(customer);
userTransaction.commit();
em.close();
entityManagerFactory.close();
}

Drill down to see what the code in Listing 4 actually does. The action starts with the Persistence class. The javadoc says, "Persistence is a bootstrap class that is used to obtain an EntityManagerFactory," like so:

EntityManagerFactory emf=Persistence.createEntityManagerFactory("testjpa");

The work of the Persistence class is pretty simple:

  • In the classpath resources, the Persistence class searches for javax.persistence.spi.PersistenceProvider files in META-INF/services/directory. It reads the PersistenceProvider implementation class names from each file.
  • It then calls createEntityManagerFactory() on each PersistenceProvider with the persistenceUnitName until it gets a an EntityManagerFactory back that isn't null. The provider name for OpenJPA is org.apache.openjpa.persistence.PersistenceProviderImpl.

How does PersistenceProvider get the right EntityManagerFactory? This is up to the vendor to implement.

EntityManagerFactory is a factory for creating an EntityManager. EntityManagerFactory should be cached and should ideally be called once for each persistence unit name in the whole application.

EntityManager manages entities; it is responsible for their addition, updating, and deletion. You can find an entity without a transaction; however, add, update, and delete operations need to be within a transaction.

If you ignore transaction management in a fetch operation, the entity does not become managed and hence the system will do a trip to the database every time you try to fetch a record from the data store; in such a scenario, you'd end up fetching a separate object every time.

The rest of the code is pretty self-explanatory. It creates a customer object, sets the values to the appropriate properties, and inserts the object to the data store, as you can see in Listing 5.

Listing 5. A code snippet for object persistence

EntityTransaction userTransaction = em.getTransaction();
userTransaction.begin();
em.persist(customer);
userTransaction.commit();

You may have already noticed by now that the code does not set the custId and updatedTime to the customer object explicitly. Because the primary key generation strategy is AUTO, the JPA provider will take care of populating the primary key. Similarly, version fields (updatedTime, in this case) are also automatically populated by the JPA provider.

Now you need to find the record that's been inserted. Finding a record with a primary key is as simple as Customer cust = em.find(Customer.class, objId);, as you can see in Listing 6.

Listing 6. Fetching data as an object

....
OpenJPAEntityManager oem = OpenJPAPersistence.cast(em);
Object objId = oem.getObjectId(customer);
Customer cust = em.find(Customer.class, objId);
....


Because the primary key is unknown up front, the application must cast EntityManager to OpenJPAEntityManager to get the primary key object by passing the customer object that was persisted earlier. This logic might differ for other vendors.

發佈了31 篇原創文章 · 獲贊 0 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章