JPA using #PersistenceContext - jpa

How to get the Persistence Unit Name dynamically?
For example in below example,I am hard coding unitName to application_openjpa, but I want to give it dynamically as unitName=#{unitName} so if I have different project uses the entity jar, but can use its own persistence.xml file
#PersistenceContext(unitName="application_openjpa")
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}

Since an application normally have limited number of persistence units, how about create two setter methods and annotate it with different unitName attribute, eg:
#PersistenceContext(unitName="testEM")
public void setTestEntityManager(EntityManager testEM) {
this.testEM = testEM;
}
#PersistenceContext(unitName="prodEM")
public void setProdEntityManager(EntityManager prodEM) {
this.prodEM = prodEM;
}
Then you can choose between testEM and prodEM dynamically ?

Related

Is it possible to inject a context specific PersistenceContext?

In a jsf application data is managed injecting a PersistenceContext.
#PersistenceContext(unitName = "MyPU")
private EntityManager em;
PersistenceContext is static and choosen at compile time. Is there a way to inject a different PersistenceContext based on the user ? My idea is to enforce authorization checks on database side too, so if there is a hole in application security the user cannot access or modify restricted data.
Create some factory :
#Stateless
public class PersistenceContextFactory {
#PersistenceContext(unitName="MyPU")
private EntityManager emPU;
#PersistenceContext(unitName="MyOtherPU")
private EntityManager emOtherPU;
public EntityManager getEntityManager(User user) {
if(user.hasSomeRight()) {
return emPU;
} else {
return emOtherPU;
}
}
}

Run method after deploying and save the result with to database

I have started a Quarkus project and i have there 2 tables, i am trying to run a Method immediately after deploying, In the method i use Entitymanger to save some results in the database.
In pure Jakarta EE, you could an EJB and annotate it with #Startup. But Since quarkus uses CDI.
#ApplicationScoped
public class StartApp {
private static final String PERSISTENCE_UNIT_NAME = "Employee";
public void init(#Observes #Initialized(ApplicationScoped.class) Object init) {
EntityManagerFactory factory =
Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
EntityManager em = factory.createEntityManager();
Directory directory = new Directory("/some/info", true, false, ".xml");
em.persist(directory);
em.close();
}
}
How can i do that!? some guess !
I think what you need is this:
#ApplicationScoped
class StartApp {
void startup(#Observes StartupEvent event) {
// Do whatever needs to be done.
}
}
More information and options can be found on the very well documented quarkus pages. https://quarkus.io/guides/cdi-reference#startup-event
Ps. don't forget about your transactions and maybe take a look at Hibernate ORM.

microprofile-config custom ConfigSource using JPA

I am currently trying to setup a custom ConfigSource reading config values from our DB2. As the ConfigSources are loaded via ServiceLoader it looks like there is no way to access the database via JPA as the ServiceLoader is scanning for custom ConfigSources very early.
Any ideas?
You can anotate your ConfigSource as a singleton session bean and mark it for eager initialization during the application startup sequence.
Also you need to define a static member variable holding your config values.
With this setup you can lazy load your properties values from an injected JPA source or also from any other CDI or EJB.
See the following example Code
#Startup
#Singleton
public class MyConfigSource implements ConfigSource {
public static final String NAME = "MyConfigSource";
public static Map<String, String> properties = null; // note to use static here!
#PersistenceContext(unitName = ".....")
private EntityManager manager;
#PostConstruct
void init() {
// load your data from teh JPA source or EJB
....
}
#Override
public int getOrdinal() {
return 890;
}
#Override
public String getValue(String key) {
if (properties != null) {
return properties.get(key);
} else {
return null;
}
}
#Override
public String getName() {
return NAME;
}
#Override
public Map<String, String> getProperties() {
return properties;
}
}
ConfigSources are POJO’s because if a CDI bean expected config to be injected into it at startup based on a ConfigSource that had dependencies on CDI’s you could get into startup looping issues.
For this reason the example CongigSoruce is constructed twice - once at the beginning from the Config-API and later from the CDI implemenation on #PostConstruct. With the static variable 'properties' we overload the values from the already constructed ConfigSource. Of course you can also separate the code in two classes if you like.

How do I create a separate entity manager for bulk operations in a JTA environment?

In JPA, when doing bulk operations such as this
update LogEntry e set e.customer = null where e.customer.id = :cid
It is recommended to use a separate entity manager to avoid breaking synchronization, according to this: UPDATE SET Queries in JPA/JPQL
For example, the EntityManager may not be aware that a cached entity object in its persistence context has been modified by an UPDATE query. Therefore, it is a good practice to use a separate EntityManager for UPDATE queries.
How do I create a separate entity manager in a JTA environment such as Wildfly using hibernate? Do I need to create a separate persistence unit for bulk operations?
EDIT: Given I dont need a separate PU for bulk operations, is this a sufficient way of solving it using a new transaction?
#Transactional
public class JpaCustomerRepository implements CustomerRepository {
#Inject
private EntityManager em;
...
#Override
public Customer remove(long id) {
CustomerEntity entity = em.find(CustomerEntity.class, id);
if (entity != null) {
updateLogEntriesToNull(entity);
em.remove(entity);
return entity;
} else {
return null;
}
}
#Transactional(value=TxType.REQUIRES_NEW)
public void updateLogEntriesToNull(CustomerEntity entity) {
em.createNamedQuery(LogEntry.updateCustomerToNull)
.setParameter("cid", entity.getId())
.executeUpdate();
}
...
}
Where LogEntry.updateCustomerToNull is the bulk query.
Answer: This does not work because the interceptor is not invoked when called from inside the same class.
EDIT2: Following the suggestions from Andrei, this should work:
#Transactional
public class JpaCustomerRepository implements CustomerRepository {
public static class BulkUpdater {
#Inject
private EntityManager em;
#Transactional(value=TxType.REQUIRES_NEW)
public void updateLogEntriesToNull(CustomerEntity entity) {
em.createNamedQuery(LogEntry.updateCustomerToNull)
.setParameter("cid", entity.getId())
.executeUpdate();
}
}
#Inject
private EntityManager em;
#Inject
private BulkUpdater bulkUpdater;
...
#Override
public Customer remove(long id) {
CustomerEntity entity = em.find(CustomerEntity.class, id);
if (entity != null) {
bulkUpdater.updateLogEntriesToNull(entity);
em.remove(entity);
return entity;
} else {
return null;
}
}
...
}
Testing confirms that the interceptor gets called twice.
The recommendation is valid only if you also do other stuff with the EntityManager (when there is a risk of manipulating/reading the same entities as the BULK UPDATE). The easiest solution: make sure that this BULK UPDATE is executed in a separate service, within a new transaction. No need to create a separate PU (persistence unit) for bulk operations.

Spring Roo: use JPA entity as a DAO

The code below is what Spring Roo generates by default, the EntityManager is injected in your domain model POJOs with the rest of the methods to manage the entity (save, update, delete, findXXX, ...).
Maybe it is a more object-oriented approach (in contrast to the anemic domain model), but what I don't understand is:
Is there any performance issue when EntityManager is injected in every entity (imagine you retrieve 1000 entities from a database)
Shouldn't the transactional management (#Transactional annotations) go in a service layer? (imagine you want to operate with two different entities in an atomic way).
Can you think about other pros/cons of this code against a classical DAO layer?
The code looks like this (some methods are removed for clarity):
#Configurable
#Entity
#RooJavaBean
#RooToString
#RooEntity
public class Answer {
#PersistenceContext
transient EntityManager entityManager;
#Transactional
public void persist() {
if (this.entityManager == null) this.entityManager = entityManager();
this.entityManager.persist(this);
}
#Transactional
public void remove() {
if (this.entityManager == null) this.entityManager = entityManager();
if (this.entityManager.contains(this)) {
this.entityManager.remove(this);
} else {
Answer attached = Answer.findAnswer(this.id);
this.entityManager.remove(attached);
}
}
#Transactional
public Answer merge() {
if (this.entityManager == null) this.entityManager = entityManager();
Answer merged = this.entityManager.merge(this);
this.entityManager.flush();
return merged;
}
public static final EntityManager entityManager() {
EntityManager em = new Answer().entityManager;
if (em == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
return em;
}
public static long countAnswers() {
return entityManager().createQuery("SELECT COUNT(o) FROM Answer o", Long.class).getSingleResult();
}
public static List<Answer> findAllAnswers() {
return entityManager().createQuery("SELECT o FROM Answer o", Answer.class).getResultList();
}
...
}
You will find more on this at the link in the third point.
You don't get a Service layer in a typical Roo application. Your service methods are contained within the entity itself, hence it is possible to use #Transactional within your entity to ensure the particular method involves in a transaction. However, you will be able to get a separate service layer with the latest 1.2 version of Spring Roo, which will make it possible.
ADM vs. DDD : A separate question on SO would help on this. Anyways, you can gain a lot of insight with this thread on SpringSource Roo forum. http://forum.springsource.org/showthread.php?77322-Spring-Roo-with-a-services-DAO-architecture
Cheers and all the best with Roo! :)