I heard about EntityManager is not thread-safe, so we use #PersistenceContext instead of #Autowired.
However, I found about two ways to create JPAQueryFactory on the Internet.
define a bean like this
#Configuration
public class JPAQueryFactoryConfiguration {
#Bean
public JPAQueryFactory jpaQueryFactory(#Autowired EntityManager entityManager) {
return new JPAQueryFactory(entityManager);
}
}
#PersistenceContext on EntityManager ,new JPAQueryFactory(entityManager) every time
#Service
public class TestServiceImpl implements TestService {
#PersistenceContext
private EntityManager entityManager;
#Override
public void test(){
JPAQueryFactory jpaQueryFactory = new JPAQueryFactory(entityManager);
xxxxxxxxxxxx
}
}
I'm counfused. But, I think the first way is not correct according to the difference between #PersistenceContext and #Autowired
i am just biginer in EJB ,
type of JPAQueryFactory is Provider
is not EntityManager , just Cast
JPAQueryFactory query = new JPAQueryFactory((Provider<EntityManager>) em);
or use the declaration of JPAQueryFactory
EntityManagerFactory emf =
Persistence.createEntityManagerFactory("com.baeldung.querydsl.intro");
EntityManager em = entityManagerFactory.createEntityManager();
JPAQueryFactory queryFactory = new JPAQueryFactory(em);
As this article shows, you need to use both the entity manager and JPAQueryFactory as follows:
Extend SimpleJpaRepository and implement BaseRepository
BaseRepository is an interface that extends JpaRepository
public abstract class BaseRepositoryImpl<T, ID>
extends SimpleJpaRepository<T, ID>
implements BaseRepository<T, ID> {
EntityManager em;
JPAQueryFactory queryFactory;
public BaseRepositoryImpl(Class<T> domainClass, EntityManager em) {
super(domainClass, em);
this.em = em;
this.queryFactory = new JPAQueryFactory(em);
}
}
and create a class that extends your BaseRepositoryImpl to use JPAQueryFactory in it.
Related
i am searching for a way to create a listener that is also a spring component, however when i try to autowire the entity manager bean, it is always null, what am i doing wrong?
#Component
public class TestListener {
#Autowired
private TestRepository entityManager;
#PrePersist
#PreUpdate
void beforeEntityUpdateOrSave(final Entity entity) {
entityManager.someOperation() // -> NullPointerException, because the bean is "null"
}
}
the Entity class has the listener in the #EntityListeners annotation.
#EntityListeners(TestListener.class)
public class Entity
Is the class TestRepository annotated with #Repository?
You could try making the field entityManager final. I would also recomend using constructor injection instead. Field injection sometimes leads to strange behaviour.
#Component
public class TestListener {
private final TestRepository entityManager;
public TestListener(#Autowired TestRepository entityManager){
this.entityManager = entityManager;
}
...
}
}
I have made this class which creates bundle from database records.
The records are got from stored procedures and names of this procedures are taken from ServiceConfig instance which is Spring #Configuration.
Now I use java Map to bind each DB entity class with according ServiceConfig method.
I would like to extend it and use Enum instead of procNameSupplier here. Is it possible to access ServiceConfig from enum?
#Component
public class BundleMaker {
#PersistenceContext
private final EntityManager entityManager;
private final Map<Class<? extends IRecord>, Supplier<String>> procNameSupplier = new HashMap<>();
public BundleMaker(EntityManager entityManager, ServiceConfig config) {
this.entityManager = entityManager;
procNameSupplier.put(MainDepRecord.class, config::mainDepProc);
//...
}
public <T extends IRecord> Bundle bundle(Class<T> cl) {
StoredProcedureQuery query;
query = entityManager.createStoredProcedureQuery(procNameSupplier.get(cl).get(), cl)
.registerStoredProcedureParameter(1, cl, REF_CURSOR);
List<T> resultList = query.getResultList();
List<Resource> resources = resultList.stream()
.map(T::toResource)
.collect(Collectors.toList());
return new Bundle(resources);
}
}
We have set up the Spring Framework like this:
#Eager
public interface CatalogElementRepository extends PagingAndSortingRepository<CatalogElementEntity, Long> {
}
#Service
public class CatalogImpl implements CatalogManager {
#Inject
CatalogElementRepository catalogElementRepository;
#Override
public CatalogElement createCatalogElement(CatalogElementEntity catalogElement) {
return this.catalogElementRepository.save(catalogElement);
}
}
#Stateless
#Remote(CatalogManager.class)
public class CatalogManagerBean implements CatalogManager {
#Inject
CatalogManager delegate;
#Override
public CatalogElement createCatalogElement(CatalogElementEntity catalogElement) {
return this.delegate.createCatalogElement(catalogElement);
}
}
So whenever someone calls the method on the remote interface createCatalogElement, I'd assume the entity gets stored in the database. It does not (weirdly enough, findOne still returns the very same entity, but it can't be found via findByProperty).
Other questions said to add #Transactional, so I added #javax.transaction.Transactional and org.springframework.transaction.annotation.Transactional on the methods and classes to be on the safe side, nothing worked.
What could be the problem?
I don't see any configuration files for the Spring Framework, but it's a legacy project, so they might just be hidden very well.
For some reason using this class as a producer for the EntityManager helped:
public class SpringConfig {
#PersistenceUnit
EntityManagerFactory emf;
#PersistenceContext
EntityManager em;
#Produces
#ApplicationScoped
public EntityManagerFactory createEntityManagerFactory() {
return this.emf;
}
#Produces
public EntityManager createEntityManager() {
return this.em;
}
public void close(#Disposes EntityManagerFactory entityManagerFactory) {
entityManagerFactory.close();
}
public void close(#Disposes EntityManager entityManager) {
entityManager.close();
}
}
I have following abstract dao class with me:
I am using find(Long primaryKey) method for getting data.
like
public abstract class AbstractDao<T> {
static final Logger logger = Logger.getLogger(AbstractDao.class);
#PersistenceContext
private EntityManager entityManager;
protected EntityManager getEntityManager() {
return this.entityManager;
}
public T find(Long primaryKey) {
//Here entityManager is null therefore I am getting null pointer exception
return entityManager.find(entityClass,primaryKey);
}
}
Please suggest some techniques to intitalize entityManager object.
You can remove PersistenceContext annotation from EntityManager and create next abstract method
public abstract void setEntityManager(EntityManager entityManager);
In this way you can put next method in the main class
#PersistenceContext(unitName = "HERE YOU HAVE TO PUT NAME OF ENTITY MANAGER FACTORY")
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
and all will be works ;) I have it in my owner DAO and all works
If you are exercising CRUD procedures do you have to do this (with transaction type: RESOURCE_LOCAL not JTA)
#PersistenceUnit(unitName="mongo")
EntityManagerFactory emf;
EntityManager em;
#Inject
private SomeObj injectableObj;
public void create()
{
em = emf.createEntityManager(); <---- here
SomeObj obj = new SomeObj();
em.persist(obj);
}
public void read()
{
em = emf.createEntityManager(); <---- here
Query query = em.createQuery("Select s from SomeObj s");
}
public void update()
{
em = emf.createEntityManager(); <---- here
SomeObj s = em.find(SomeObj.class, injectableObj.getId());
s.setSomeObj(injectableObj.getSomeObj());
}
public void delete()
{
em = emf.createEntityManager(); <---- here
SomeObj s = em.find(SomeObj.class, injectableObj.getId());
em.remove(s);
}
Question: Is there anyway to inject the EntityManager?
Maybe try to look here for exemples :
Injections EntityManager
I prefer to use : Injection via #PersistenceContext
You can use injection. I use it like this:
#PersistenceContext(unitName = "some_jndi_name")
private EntityManager em;