How to test if Hibernate Session is open? - java

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()

Related

How to persist/commit entity to database immediately in Activiti Service Task

I have a need to persist(insert) a entity to database immediately when the save (or saveAndFlush) code is called.
However although the entity is created in the context it is not persisted in the database immediately.
We are using Spring Boot.
public interface MessageRepository extends JpaRepository<MessageEntity, Long> {
}
In the Service class
#Service
public class TestService {
#Autowired
private MessageRepository messageRepository;
#Transactional
public MessageEntity saveMessage(MessageEntity entity) throws Exception {
entity = messageRepository.saveAndFlush(entity);
return entity;
}
}
Though the entity is created it is not persisted/committed to the database immediately.
We are facing this issue within the Activiti Tasks only.
Any feedback will be appreciated.
This worked.
#Component
public class MessageRepositoryCustomImpl implements MessageRepositoryCustom {
#PersistenceContext
EntityManager entityManager;
#Override
#Transactional(propagation = Propagation.REQUIRES_NEW)
public MessageEntity saveImmediate(MessageEntity entity) {
entityManager.persist(entity);
return entity;
}
}
One way of overcoming this situation is by taking advantage of the REQUIRES_NEW transaction attribute.
In your situation you would have to create a new repository:
public interface MessageRepositoryCustom{
void saveAndFLush(MessageEntity ent);
}
public MessageRepositoryCustomImpl implements MessageRepositoryCustom{
#Autowired
private SessionFactory sessionFactory;
#Transactional(propagation = Propagation.REQUIRES_NEW)
void saveAndFLush(MessageEntity ent){
Session session = sessionFactory.getCurrentSession();
session.persist(ent);
}
}
Then in your service you would use that repository:
#Transactional
public MessageEntity saveMessage(MessageEntity entity) throws Exception {
entity = messageRepositoryCutom.saveAndFlush(entity);
// other processing
return entity;
}
}
Now after the messageRepositoryCutom.saveAndFlush method has finished processing the entity will be physically persisted in the database as it was created in a separate transaction which has been commited.

Spring Boot and multiple databases

I've setup a basic spring project with a single database connection.
In the application.properties file I have the database settings:
spring.datasource.url = jdbc:mysql://192.168.1.19/ticket
spring.datasource.username = dbusername
spring.datasource.password = dbpassword
I've created a base DAO class which other DAOs extend:
#Transactional
public class Dao<E> {
#PersistenceContext
private EntityManager entityManager;
private Class<E> entityClass;
public Dao(Class<E> entityClass) {
this.entityClass = entityClass;
}
public void create(E object) {
entityManager.persist(object);
return;
}
public void delete(E object) {
if (entityManager.contains(object)) {
entityManager.remove(object);
} else {
entityManager.remove(entityManager.merge(object));
}
return;
}
#SuppressWarnings("unchecked")
public List<E> getAll() {
return entityManager.createQuery("from " + entityClass.getName()).getResultList();
}
public E get(long id) {
return entityManager.find(entityClass, id);
}
public void update(E object) {
entityManager.merge(object);
return;
}
}
Here's a sample entity that extends the base DAO:
#Repository
public class PersonDao extends Dao<Person> {
public PersonDao() {
super(Person.class);
}
}
Currently this uses a single database, but I need to be able to add a second database, and somehow define in each DAO which datasource to use. Each DAO will only use a single database, so there's no requirement for a DAO to be able to connect to multiple databases.
I've done some research, and that seems to suggest I need to use JdbcTemplate? but I can't seem to find a tutorial that matches my need. Also, at the minute the entityManager is injected into the DAO, but the JdbcTemplate examples I've looked at don't seem to use the entityManager, which is slightly confusing.
database.password1=<password1>
database.url1=jdbc\:mysql\://localhost\:3306/twodbone
database.username1=<username1>
database.password2=<password1>
database.url2=jdbc\:mysql\://localhost\:3306/twodbtwo
database.username2=<username2>
database.driverClassName=com.mysql.jdbc.Driver
In this way you can add the multiple databases and configure both hibernate.cfg.xml file and applicationContext.xml file also..
#Repository
public class FooRepository
{
#PersistenceContext
private EntityManager entityManager;
#Autowired(required = true)
private JdbcTemplate jdbcTemplate;
public void saveFoo(Foo foo)
{
this.entityManager.persist(foo);
}
public List<SomeReportPojo> getSomeReport()
{
return this.entityManager.queryForList("SELECT .. ",SomeProjectPojo.class);
}
}
this.jdbcTemplate should be kept rather than this.entityManager for jdbc templetes
this is simple example

Spring Entities Not Saved To Database

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();
}
}

Initialization of EntityManager class object, how to do it?

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

What's wrong with my JPA DAO? It will persist but there's an error on merge

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/

Categories

Resources