Problem:
entityManager.unwrap(SessionImplementor.class) cause no transactional entitymanager available exception.
Code:
#Component
public class HibernateEventWiring {
#Autowired
private ViewListener listener;
#PersistenceContext(unitName = "config-punit")
private EntityManager entityManager;
#PostConstruct
public void registerListeners() {
SessionFactory sessionFactory = getSessionFactory();
EventListenerRegistry registry = ((SessionFactoryImpl) sessionFactory).getServiceRegistry().getService(
EventListenerRegistry.class);
registry.getEventListenerGroup(EventType.PRE_UPDATE).appendListener(listener);
}
#Transactional
private SessionFactory getSessionFactory() {
// EXCEPTION: No transactional entitymanager available
return entityManager.unwrap(SessionImplementor.class).getFactory();
}
}
According to this excelent answer:
In the #PostConstruct (as with the afterPropertiesSet from the InitializingBean interface) there is no way to ensure that all the post processing is already done, so (indeed) there can be no Transactions.
As I see, you do not need a transaction nor an entity manager bean, but rather an entity manager factory bean. I think you should simply autowire the EntityManagerFactory and then unwrap the Hibernate SessionFactory from it.
#Autowired
private EntityManagerFactory entityManagerFactory;
#PostConstruct
public void registerListeners() {
SessionFactory sessionFactory = entityManagerFactory.unwrap(SessionFactory.class);
...
}
Related
I try to get my hands dirty with Spring + JPA and I read Spring in Action 4th edition. Because of code samples there are incomplete I look for needed parts of code myself in web. But seems I did smth wrong because when I call EntityManager.persist() it doesn't work. No even exception thrown
My code below
DataConfig
#Configuration
#EnableTransactionManagement
public class DataConfig {
#Bean
public DataSource dataSource() {
SingleConnectionDataSource ds = new SingleConnectionDataSource();
ds.setDriverClassName("com.mysql.cj.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/dbname");
ds.setSuppressClose(true);
ds.setUsername("user");
ds.setPassword("password");
return ds;
}
#Bean
public JpaVendorAdapter jpaVendorAdapter(){
HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
adapter.setDatabase(Database.MYSQL);
adapter.setShowSql(true);
adapter.setGenerateDdl(false);
adapter.setDatabasePlatform("org.hibernate.dialect.MySQLDialect");
return adapter;
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource, JpaVendorAdapter jpaVendorAdapter){
LocalContainerEntityManagerFactoryBean emfb = new LocalContainerEntityManagerFactoryBean();
emfb.setDataSource(dataSource);
emfb.setJpaVendorAdapter(jpaVendorAdapter);
emfb.setPackagesToScan("spittr.domain");
return emfb;
}
#Bean
public PlatformTransactionManager transactionManager(DataSource ds){
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setDataSource(ds);
return transactionManager;
}
}
Repository
#Repository
public class JpaSpittleRepository implements SpittleRepository{
#PersistenceUnit
private EntityManagerFactory emf;
//other methods...
#Transactional
public void save(Spittle spittle) {
EntityManager em = emf.createEntityManager();
em.persist(spittle);
}
}
So in this configuration save() saves nothing.
Of course if explicitly add a pair of lines of code to that method like:
#Transactional //unnecessary now
public void save(Spittle spittle) {
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
em.persist(spittle);
tx.commit();
}
save() works fine (even without #Transactional)
Also I found that #Transactional does wrap save() method with doBegin() and doCommit() methods of JpaTransactionManager.
Where would you suggest to dig more to find the problem?
That same book offers another way of configuring Repository by replacing injection of EntityManagerFactory with EntityManager:
//#PersistenceUnit
#PersistenceContext
//private EntityManagerFactory emf;
private EntityManager em;
As explained, calling emf.createEntityManager() in each method creates new EntityManager which complicates matters concerning transactions
Now it works, though for me the root cause of problem still unclear
I'd like for my ResourceConfig to have access to a database for its configuration. I've tried this:
#ApplicationPath("/api")
public class ApplicationConfig extends ResourceConfig {
#PersistenceContext(unitName = "myPU")
private EntityManager em;
#Inject
private MyEjb myEjb;
#PostConstruct
public void init() {
// em and myEjb are both null
...
}
But neither the EntityManager, not the EJB, are injected (both are null)
Is there a special way to do this in JAX-RS?
NOTE: I'm able to inject resources into a Path-annotated class just fine. I'm having trouble doing it in the actual ApplicationPath-annotated class.
I have JSF maven project with Hibernate. There are some DAO classes in project, but it have failed implementation I think.
public class HibernateUtil {
private static final SessionFactory sessionFactory;
static {
try {
// Create the SessionFactory from standard (hibernate.cfg.xml)
// config file.
Configuration configuration = new Configuration().configure();
StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder().
applySettings(configuration.getProperties());
sessionFactory = configuration.buildSessionFactory(builder.build());
} catch (Throwable ex) {
// Log the exception.
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
}
In each DAO I call this method
Session mySession = HibernateUtil.getSessionFactory().openSession();
And After that doing transactions.
Now I want create generic BaseDAO class and create base CRUD operations in it. But I need get EntityManager. How can I getEntityManager in my BaseDao?
In spring I do it:
public class BaseJpaDao<E> implements BaseDao<E>{
protected Class<?> entityClass;
#PersistenceContext(unitName = "mainDataBase")
private EntityManager entityManager;
public BaseJpaDao(Class<?> entityClass) {
this.entityClass = entityClass;
}
#Override
public E persist(E e) {
entityManager.persist(e);
return e;
}
But how do it in not spring project?
Use Hibernates factory methods:
// Use persistence.xml configuration
EntityManagerFactory emf = Persistence.createEntityManagerFactory("mainDataBase")
EntityManager em = emf.createEntityManager();
// Retrieve an application managed entity manager
// Work with the EM
em.close();
Taken from the docs.
Question: From where to start when trying to resolve FactoryBeanNotInitializedException exception while injecting EntityManager into service?
Code:
#Service
public class MyService {
....
#Autowired
private EntityManager entityManager;
Exception:
org.springframework.beans.factory.FactoryBeanNotInitializedException: FactoryBean is not fully initialized yet
try
#PersistenceContext(unitName="puName")
EntityManager em;
and make sure that EntityManager must be registered...
try #PersistenceContext instead of #Autowired
I'm using Spring 3.1.0.RELEASE with Hibernate 4.0.1.Final. I want to invoke an event listener on my entity bean when it is loaded from the DB, but I can't figure out what event I should be using. I load my entities in my DAO like so
#Repository("eventFeedsDao")
public class EventFeedsDaoImpl implements EventFeedsDao {
...
#Autowired
private SessionFactory sessionFactory;
...
#Override
public EventFeed findById(final Integer id) {
EventFeed eventFeed = null;
final Session session = sessionFactory.getCurrentSession();
final Criteria crit = session.createCriteria(EventFeed.class).add(Restrictions.eq("id", id));
final List<EventFeed> results = crit.list();
if (results != null && results.size() > 0) {
eventFeed = results.get(0);
} // if
return eventFeed;
} // findById
Here is how I'm trying to set up my event wiring ...
#Component
public class HibernateEventWiring {
#Autowired
private SessionFactory sessionFactory;
#Autowired
private EventMavenLoadListener listener;
#PostConstruct
public void registerListeners() {
EventListenerRegistry registry = ((SessionFactoryImpl) sessionFactory)
.getServiceRegistry().getService(EventListenerRegistry.class);
registry.getEventListenerGroup(EventType.LOAD).appendListener(listener);
}
}
and my listener class is as follows ...
#Component
public class EventMavenLoadListener implements LoadEventListener {
...
#Override
public void onLoad(final LoadEvent event, final LoadType loadType) throws HibernateException {
if(EventFeed.class.getName().equals(event.getEntityClassName())){
EventFeed entity = (EventFeed) event.getInstanceToLoad();
entity.setNetUtilsService(netUtilsService);
} // if
}
}
but the "onLoad" event is never called. What am I doing wrong? Should I be using another event?
For some reason that still eludes me, the EventType.PRE_LOAD event type was the way to go. This worked.
#Component
public class HibernateEventWiring {
#Autowired
private SessionFactory sessionFactory;
#Autowired
private EventMavenLoadListener listener;
#PostConstruct
public void registerListeners() {
final EventListenerRegistry registry = ((SessionFactoryImpl) sessionFactory)
.getServiceRegistry().getService(EventListenerRegistry.class);
registry.getEventListenerGroup(EventType.PRE_LOAD)
.appendListener((PreLoadEventListener) listener);
}
}
The load event is only triggered when loading an entity individually (session.get, initializing a proxy, fetching eager to-one associations).
The pre and post load events however follow JPA defined behavior and occur before and after the entity data is loaded regardless of how that "data load" occurred.
Its a case of bad name collision.
The preferred way in Hibernate 4, btw, to specify event listeners is through the use of an org.hibernate.integrator.spi.Integrator. See http://docs.jboss.org/hibernate/orm/4.1/devguide/en-US/html_single/#integrators