我们使用Guice Persist在我们的项目中注入EntityManager.
例如
public class MyDao{
@Inject
EntityManager em;
public void someMethod(){
//uses em instance
}
}
Run Code Online (Sandbox Code Playgroud)
但我们还不清楚如何使用注入的实例EntityManager.
我有一个Web应用程序,有一些奇怪的行为,我无法真正指责.我的问题的核心是我的休息端点返回的值存在不一致的行为.当我启动应用程序时,每次调用此端点时,我的查询都会返回相同的值.当我更新实体时,我的实体管理器开始表现得很奇怪.现在我的查询开始返回不同的结果.有一次它返回旧值而不是数据库中的值,或者我的结果列表包含代理而不是对象(混合).

我已经验证我的@transaction方法正确放置并且在我的调试堆栈中我看到事务拦截器和实体管理器是根据后端的请求创建的(所以没有guice持久性过滤器)
我的感觉表明问题出在会话环境中.我有这种感觉(但我无法真正掌握它)它在多个请求中重用了我的持久化上下文.
我已经将一些框架放在一起使这一切都有效.我使用resteasy作为jax-rs实现者.guice(4.0beta4)作为cdi实现者,hibernate作为jpa实现者.因为我们在注入entitymanager时需要使用提供者(因为每个事务都创建了entitymanager),所以我将它包装在EntityManagerProxy中.此类实现EntityManager接口,并将所有方法委托给provider.get().method().
public class EntityManagerProxy implements EntityManager {
private final Provider<EntityManager> entityManagerProvider;
@Inject
public EntityManagerProxy(final Provider<EntityManager> entityManagerProvider) {
this.entityManagerProvider = entityManagerProvider;
}
private EntityManager getEntityManager() {
return entityManagerProvider.get();
}
@Override
public void persist(final Object entity) {
getEntityManager().persist(entity);
}
}
Run Code Online (Sandbox Code Playgroud)
我的guice模块看起来像这样
public class OptiWEEEModule extends ServletModule implements Module {
@Override
protected void configureServlets() {
super.configureServlets();
bind(EntityManagerProxy.class);
// JPA
install(new JpaPersistModule("myPU"));
}
}
Run Code Online (Sandbox Code Playgroud)
我知道这是一个模糊的问题,但有人可以帮助我朝着正确的方向前进吗?这不是一个我可以提供错误消息的问题.
编辑:我现在指出问题所在.使用分析器,我看起来实体上下文被guice重用.这意味着它不是每次都执行查询,而是使用现有的实体管理器,每次传递@transactional注释时都应该创建该实体管理器.
我有一个使用GuicePersist,Hibernate和HikariCP的java8桌面应用程序与Postgres DB进行通信.我已成功使用此META-INF/persistence.xml让我的应用程序向数据库发送/接收数据:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
<!-- A JPA Persistence Unit -->
<persistence-unit name="myJPAunit" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<class>com.123fakestreet.bogus.tomb.impl.postgres.model.movies</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<!-- SQL stuff -->
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQL9Dialect" />
<property name="hibernate.show_sql" value="false" />
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.hbm2ddl.auto" value="validate" />
<!-- hikari CP -->
<property name="hibernate.connection.provider_class" value="org.hibernate.hikaricp.internal.HikariCPConnectionProvider" />
<property name="hibernate.hikari.minimumIdle" value="20" />
<property name="hibernate.hikari.maximumPoolSize" value="100" />
<property name="hibernate.hikari.idleTimeout" value="30000" />
<property name="hibernate.hikari.dataSourceClassName" value="org.postgresql.ds.PGSimpleDataSource" />
<property name="hibernate.hikari.dataSource.url" value="jdbc:postgresql://192.168.100.75:5432/mpDb" />
<property name="hibernate.hikari.username" value="cowboy" />
<property name="hibernate.hikari.password" value="bebop" />
<!-- Disable the …Run Code Online (Sandbox Code Playgroud) 我需要与 共享数据源JpaPersistModule。该数据源由 guice 注入器提供。
现在的问题是我必须在配置阶段构建模块,但数据源仅在运行时可用。
目前我有以下代码:
public class MyJpaConfigurationModule implements Module {
private Map<String, Object> jpaProperties = new HashMap<>();
private Module jpaModule = new JpaPersistModule("peristenceUnit").properties(jpaProperties);
public void configure(Binder binder) {
binder.requestInjection(this);
binder.install(jpaModule);
}
@Provides @Singleton
public DataSource provideDatasource() {
return ..... // some data source
}
@Inject
public void setJpaProperties(DataSource dataSource, PersistService persistService) {
jpaProperties.put("dataSource", dataSource);
persistService.start();
}
}
Run Code Online (Sandbox Code Playgroud)
我已经检查过,似乎 jpa 属性映射到处都是通过引用注入的,因此我的运行时更改应该变得可见,但如果将来发生变化怎么办?
解决此类冲突的正确方法是什么?
我们在tomcat 6上有一个使用Java,hibernate 4,guice 3,guice-persist 3的应用程序
connection.autocommit在hibernate.cfg.xml文件中配置为false:
<session-factory>
<property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/dev</property>
<property name="connection.username">root</property>
<property name="connection.password">root</property>
<property name="connection.autocommit">false</property>
<property name="connection.proof_property">true</property>
<!-- Disable second-level cache. -->
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<property name="cache.use_query_cache">false</property>
<property name="cache.use_minimal_puts">false</property>
<property name="max_fetch_depth">3</property>
<!-- Print SQL to stdout. -->
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<property name="id.new_generator_mappings">true</property>
<!-- Drop and then re-create schema on SessionFactory build, for testing. -->
<property name="hbm2ddl.auto">create</property>
<!-- Bind the getCurrentSession() method to the thread. -->
<property name="current_session_context_class">thread</property>
<!-- configuration pool via c3p0-->
<property name="c3p0.initialPoolSize">0</property>
<property name="c3p0.acquire_increment">1</property> …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用Guice Persist创建一个带有@Transactional注释方法的简单服务类:
public class TestServiceImpl implements TestService {
@Inject
private Provider<EntityManager> entityManager;
@Override
@Transactional
public Long createEvent(String name) {
Event event = new Event(name);
System.out.println("Is transaction active? " + entityManager.get().getTransaction().isActive() );
entityManager.get().persist(event);
return event.getId();
}
}
Run Code Online (Sandbox Code Playgroud)
遗憾的是,Guice Persist没有创建任何交易.日志输出可以在这里看到:http://pastebin.com/Mh5BkqSC
请注意第450行的打印:
交易是否有效?假
结果是数据库中没有存储任何内容:
mydb=# \d
List of relations
Schema | Name | Type | Owner
--------+--------------------+----------+----------
public | events | table | postgres
public | hibernate_sequence | sequence | postgres
(2 rows)
mydb=# select * from events;
id | …Run Code Online (Sandbox Code Playgroud) 我试图使用持久性和servlet guice扩展使用简单的webapp在Jetty上使用Guice和JPA.
我写了这个Service实现类:
public class PersonServiceImpl implements PersonService {
private EntityManager em;
@Inject
public PersonServiceImpl(EntityManager em) {
this.em = em;
}
@Override
@Transactional
public void savePerson(Person p) {
em.persist(p);
}
@Override
public Person findPerson(long id) {
return em.find(Person.class, id);
}
@Override
@Transactional
public void deletePerson(Person p) {
em.remove(p);
}
Run Code Online (Sandbox Code Playgroud)
}
这是我的servlet(用@Singleton注释):
@Inject
PersonService personService;
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String name = req.getParameter("name");
String password = req.getParameter("password");
String email = req.getParameter("email");
int age = …Run Code Online (Sandbox Code Playgroud) 出于某种原因,hibernate没有捕获诸如将实体映射到不存在的表之类的问题.我的persistence.xml文件看起来像这样......
<?xml version="1.0" encoding="UTF-8" ?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0">
<!-- A JPA Persistence Unit -->
<persistence-unit name="printLogixJpaUnit" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.printlogix.rp.server.domain.User</class>
<class>com.printlogix.rp.server.domain.UserImage</class>
<class>com.printlogix.rp.server.domain.TemplateInstance</class>
<class>com.printlogix.rp.server.domain.UserOrder</class>
<class>com.printlogix.rp.server.domain.OrderLineItem</class>
<class>com.printlogix.rp.server.domain.OrderStatus</class>
<class>com.printlogix.rp.server.domain.AgencyImage</class>
<class>com.printlogix.rp.server.domain.Agency</class>
<class>com.printlogix.rp.server.domain.Brokerage</class>
<class>com.printlogix.rp.server.domain.SystemTemplate</class>
<class>com.printlogix.rp.server.domain.TemplateType</class>
<class>com.printlogix.rp.server.domain.Product</class>
<class>com.printlogix.rp.server.domain.ProductDefinition</class>
<class>com.printlogix.rp.server.domain.ExpeditedAddress</class>
<class>com.printlogix.rp.server.domain.BrokerageUser</class>
<class>com.printlogix.rp.server.domain.StateProvince</class>
<class>com.printlogix.rp.server.domain.Country</class>
<class>com.printlogix.rp.server.domain.AwardClub</class>
<class>com.printlogix.rp.server.domain.SuperUser</class>
<class>com.printlogix.rp.server.domain.AgencyUser</class>
<class>com.printlogix.rp.server.domain.RememberMe</class>
<class>com.printlogix.rp.server.domain.PasswordResetRequest</class>
<class>com.printlogix.rp.server.domain.SystemTheme</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="hibernate.show_sql" value="true"/>
<!--Begin Credentials -->
<property name="hibernate.connection.url" value="jdbc:mysql://localhost/realtorprint_dev?autoReconnect=true"/>
<property name="hibernate.connection.username" value="test"/>
<property name="hibernate.connection.password" value="test"/>
<!--End Credentials -->
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
</properties>
</persistence-unit>
</persistence>
Run Code Online (Sandbox Code Playgroud) 在DB挂起空闲连接或DB关闭并备份后,我在webapp中收到以下错误:
javax.persistence.PersistenceException: org.hibernate.exception.JDBCConnectionException: could not inspect JDBC autocommit mode
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1365)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1293)
at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:265)
... 60 more
Caused by: org.hibernate.exception.JDBCConnectionException: could not inspect JDBC autocommit mode
at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:131)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:125)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:110)
at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.isAutoCommit(LogicalConnectionImpl.java:395)
at org.hibernate.engine.transaction.internal.TransactionCoordinatorImpl.afterNonTransactionalQuery(TransactionCoordinatorImpl.java:195)
at org.hibernate.internal.SessionImpl.afterOperation(SessionImpl.java:565)
at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1220)
at org.hibernate.internal.QueryImpl.list(QueryImpl.java:101)
at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:256)
... 70 more
Caused by: org.postgresql.util.PSQLException: This connection has been closed.
at org.postgresql.jdbc2.AbstractJdbc2Connection.checkClosed(AbstractJdbc2Connection.java:712)
at org.postgresql.jdbc2.AbstractJdbc2Connection.getAutoCommit(AbstractJdbc2Connection.java:678)
at sun.reflect.GeneratedMethodAccessor138.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.apache.tomcat.jdbc.pool.ProxyConnection.invoke(ProxyConnection.java:126)
at org.apache.tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.java:99)
at org.apache.tomcat.jdbc.pool.DisposableConnectionFacade.invoke(DisposableConnectionFacade.java:63)
at $Proxy66.getAutoCommit(Unknown Source)
at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.isAutoCommit(LogicalConnectionImpl.java:392) …Run Code Online (Sandbox Code Playgroud)