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
Related
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.
I am facing Transaction errors such:
org.hibernate.LazyInitializationException: failed to lazily initialize
a collection of role:
app.Parent.children, could
not initialize proxy - no Session
Here on parent.getChildren().size().
But I do have an #Transactional on #Service methods:
1 transaction on createFactory() to create a factory and give the entitymanager
1 transaction on create() to create the entity
#Path("api/parents")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
#Controller
public class ParentResource {
#Autowired
private ParentService parentService;
#POST
public Parent create(Parent parent) {
ParentFactory parentFactory = parentService.createFactory(parent);
return parentService.create(parent);
}
}
#Service
public class ParentService {
#PersistenceContext
private EntityManager em;
#Transactional
public ParentFactory createFactory(Parent parent) {
return new ParentFactory(parent, em);
}
#Transactional
public Parent create(ParentFactory parentFactory) {
return parentFactory.create();
}
}
// No Transactional annotation
public class ParentFactory {
private Parent parent;
private EntityManager em;
public ParentFactory(Parent parent, EntityManager em) {
this.parent = parent;
this.em = em;
}
public parent create() {
if(parent.getChildren().size() < 3) { // Exception here
em.persist(this.parent);
}
}
}
I'd like to be able to test when my Hibernate Session is alive or not, so that I can check when it's lost and why.
Thanks !
I think the best way to handle your requirement is to use jpa validator #Size(min=3) on the children property
Try with session.getTransaction().isActive()
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();
}
}
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;
I'm using JPA and EJBs on WebSphere 7.
I have the following class:
#Entity
#Table(name="WIDGET")
public class Widget implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
private String details;
/* getters and setters */
}
I have a DAO like so:
#Stateless
public class WidgetDAO implements WidgetDAOLocal {
#PersistenceUnit
private EntityManagerFactory emf;
private EntityManager em;
public EntityManager getEntityManager() {
if (emf == null) {
throw new Exception();
}
return emf.createEntityManager;
}
public Widget getWidget(Long id) {
Widget widget = null;
EntityManager em = getEntityManager();
try {
widget = (Widget)em.find(Widget.class, widgetId);
} finally {
em.close();
}
return widget;
}
public Widget createWidget(Widget widget) {
EntityManager em = getEntityManager();
try {
em.persist(widget);
em.flush();
} finally {
em.close();
}
return widget;
}
public Widget updateWidget(Widget widget) {
EntityManager em = getEntityManager();
try {
widget = getEntityManager().merge(widget);
em.flush();
} finally {
em.close();
}
return widget;
}
}
The create works fine and my widget appears in the database.
But when I try to do a merge, I get an error. The code to do the merge and the error I get follows:
public WidgetService {
#EJB
private WidgetDAO widgetDAO;
public WidgetDAO getWidgetDAO() {
return this.widgetDAO;
}
public Widget getWidget(Long id) {
return this.getWidgetDAO().getWidget(id);
}
public void updateDetails(Long widgetId, String details) {
Widget w = this.getWidget(widgetId);
w.setDetails(details);
this.widgetDAO.updateWidget(w);
}
}
The error is:
Exception caught from before_completion synchronization operation:
<openjpa-1.2.1-SNAPSHOT-r422266:686069 nonfatal user error> org.apache.openjpa.persistence.InvalidStateException:
The generated value processing detected an existing value assigned to this field: com.mydomain.domain.Widget.id.
This existing value was either provided via an initializer or by calling the setter method.
You either need to remove the #GeneratedValue annotation or modify the code to the initializer processing.
Any help on this is greatly appreciated!
Merge takes a copy of your entity, detaches it and persists the new one, which i presume attempts to set the ID from the old and causes you the conflict on your generated values. If you just want to update your object you should do so within a transaction and commit that.
Thanks for the help everybody, I figured it out, here's the cause of the problem and the solution that worked for me.
In my DAO I was doing this:
#Stateless
public class WidgetDAO implements WidgetDAOLocal {
#PersistenceUnit
private EntityManagerFactory emf;
private EntityManager em;
public EntityManager getEntityManager() {
if (emf == null) {
throw new Exception();
}
return emf.createEntityManager;
}
Because the EntityManagerFactory was being injected via the #PersistenceUnit annotation, the entities were "Application-Managed", causing some kind of conflict with WebSphere.
I changed the code to this:
#Stateless
public class WidgetDAO implements WidgetDAOLocal {
#PersistenceContext
private EntityManager em;
public EntityManager getEntityManager() {
return em;
}
public Widget updateWidget(Widget widget) throws Exception {
return getEntityManager().merge(widget);
}
The #PersistenceContext annotation causes the entities to be "Container-Managed", and everything works now.
Thanks for the all the help and suggestions here. At the end of the day, I worked out the solution after re-focusing on the "Managing Entities" section of the documentation here:
http://docs.oracle.com/javaee/5/tutorial/doc/