从API,我可以看到它与代理有关.但我找不到很多关于代理的信息,也不理解调用session.get和调用之间的区别session.load.有人可以解释或指导我参考页面吗?
谢谢!!
我有一个使用Hibernate 4和Spring Transactions的Spring 3.2应用程序.所有方法都运行良好,我可以正确访问数据库以保存或检索实体.然后,我介绍了一些多线程,并且由于每个线程都访问了db,我从Hibernate收到以下错误:
org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions
Run Code Online (Sandbox Code Playgroud)
我从网上读到我要添加<prop key="hibernate.current_session_context_class">thread</prop>到我的Hibernate配置中,但是现在每次我尝试访问db时都会得到:
org.hibernate.HibernateException: saveOrUpdate is not valid without active transaction
Run Code Online (Sandbox Code Playgroud)
但是我的服务方法是注释的@Transactional,并且在添加之前一切正常<prop key="hibernate.current_session_context_class">thread</prop>.
为什么没有交易,尽管方法是用@Transactional注释的?我怎么解决这个问题?
这是我的Hibernate配置(包括会话上下文属性):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
<!-- Hibernate session factory -->
<bean
id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" >
<property name="dataSource" >
<ref bean="dataSource" />
</property>
<property name="hibernateProperties" >
<props>
<prop key="hibernate.hbm2ddl.auto">create</prop>
<prop key="hibernate.dialect" >org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.current_session_context_class">thread</prop>
</props>
</property>
<property name="annotatedClasses" …Run Code Online (Sandbox Code Playgroud) 我需要知道,Hibernate的会话是否是线程安全的.但很明显,每个线程都会附加一个新会话来执行.但我的问题是,如果在一个线程中我更新了一个实体的某个值,那么在同一时间执行期间会反映在其他线程中吗?
我的问题是当我从两个线程顺序触发更新时,值正确更新但是当我几乎完全触发更新时它就失败了.
例如.现阶段的表.
ID NAME MARKS
------- --------- --------
1 John 54
Run Code Online (Sandbox Code Playgroud)
我想做的是:
Student student = session.load(Student.class, 1);
student.setMarks(student.getMarks() + 1);
session.update(student);
session.close();
Run Code Online (Sandbox Code Playgroud)
当我尝试在循环中运行上面的代码时说10,那么表"student"中的"标记"的值被正确更新,即值被更新为64,这是正确的.
但是当我尝试在线程环境中运行相同的代码时,它会产生错误的结果.
我正在Grails编写一个多线程应用程序,其他线程需要访问GORM/Hibernate.当他们尝试访问GORM时,我收到错误"org.hibernate.HibernateException:没有Hibernate会话绑定到线程,配置不允许在这里创建非事务性的".
确定公平,有人可以指导我设置线程的最佳方式来访问吗?错误消息几乎听起来像你只需要更改一些配置选项但我感觉,它不是那么简单......
我想使用spring测试框架测试hibernate session的save()方法.@Test方法是:
@Test
@Transactional
public void testSave() {
User expected = createUser();
getGenericDao().currentSession().save(expected);
User actual = getUser(generatedId);
assertUsersEqual(expected,actual);
}
Run Code Online (Sandbox Code Playgroud)
我想将用户刷新到数据库中.我想让我的用户在这个方法之后进入数据库
getGenericDao().currentSession().save(expected);
Run Code Online (Sandbox Code Playgroud)
然后我想使用spring数据框架转到数据库,并通过下一行获取此保存的用户:
User actual = getUser(generatedId);
Run Code Online (Sandbox Code Playgroud)
我尝试使用hibernate flush方法,如:
currentSession().setFlushMode(MANUAL);
//do saving here
currentSession().flush();
Run Code Online (Sandbox Code Playgroud)
它不会将我的用户刷新到数据库中!但是,如果我没有使用@Transactional spring注释并将我的用户保存在编程弹簧事务中,那么我实现了我想要的.不幸的是,由于没有spring @Transactional,因此保存到db的用户不会回滚.因此,我的测试方法会更改后续测试方法的db和行为.
所以我需要将我的用户刷新到db里面的测试方法(不是在最后),并在测试方法结束时回滚所有对db的更改.
UPDATE建议准备方法如下:
@Transactional
public void doSave(User user){
getGenericDao().currentSession().save(user);
}
Run Code Online (Sandbox Code Playgroud)
并且在testSave中调用doSave什么都不做.执行此方法后,我仍然没有db中的用户.我设置断点并从命令行检查我的数据库.
更新非常感谢您的回复.问题是方法flush()不会将我的用户放入数据库.我尝试了Isolation.READ_UNCOMMITTED并且它没有将我的用户放入数据库.我可以实现我想要的,但前提是我在@Test方法上关闭spring事务并在程序化事务中保存.然后@Test方法不回滚,为后续的@Test方法留下保存的用户.这里保存用户的@Test方法不像删除用户的@Test方法那样危险,因为它没有回滚.因此必须对@Test方法提供Spring事务支持,我无法将我的用户(或删除)放入db.实际上,只有在@Test方法结束并且@Test方法的事务被调用后,才会将用户放入(或删除)到db中.所以我想在@Test方法的中间将我的用户保存到db中,并在@Test方法结束时回滚它
谢谢!
java hibernate spring-test hibernate-session spring-transactions
我有一个应用程序,Spring和Hibernate3在生产中运行良好.以下是Spring的applicationContext.xml中的会话工厂的配置
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mappingDirectoryLocations">
<list>
<value>classpath:/hibernate</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect
</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.use_sql_comments">true</prop>
<prop key="hibernate.max_fetch_depth">2</prop>
<prop key="hibernate.autocommit">false</prop>
<prop key="hibernate.current_session_context_class ">thread</prop>
<prop key="hibernate.generate_statistics">true</prop>
<prop key="hibernate.jdbc.batch_size">20</prop>
</props>
</property>
</bean>
<bean id="txManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- the transactional advice (what 'happens'; see the <aop:advisor/> bean
below) -->
<tx:advice id="txAdvice" transaction-manager="txManager">
<!-- the transactional semantics... -->
<tx:attributes>
<tx:method name="*" propagation="REQUIRED" />
<tx:method name="get*" propagation="SUPPORTS" read-only="true" />
<tx:method name="count*" …Run Code Online (Sandbox Code Playgroud) 我在@Async服务层方法上使用注释.
当我EAGERLY加载@OneToMany集合字段时,一切正常,但是当我尝试访问LAZY加载的元素时,我发现Hibernate SessionImplementor对象session为null.这显然给了我一个例外:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role:
....
Run Code Online (Sandbox Code Playgroud)
这是我的收藏领域:
@OneToMany(mappedBy="abc", fetch=FetchType.LAZY, cascade=CascadeType.REMOVE)
@OrderBy(value="xsd asc")
@JsonIgnore
private Set<Item> items = new HashSet<Item>();
Run Code Online (Sandbox Code Playgroud)
如何绑定hibernate会话以便LAZELY在@Async上下文中加载我的对象?
编辑
这是我的trancactionManager/entityManager配置
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="emf"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter" ref="hibernateJpaVendorAdapter">
</property>
<property name="packagesToScan" value="it.domain"/>
<property name="persistenceUnitName" value="persistenceUnit"/>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop>
<!--${hibernate.format_sql} -->
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
<!-- ${hibernate.show_sql} -->
<prop …Run Code Online (Sandbox Code Playgroud) 我正在为我的AbstractHibernateRepository保存方法编写一个单元测试.我正在使用spring test runner但运行时遇到以下异常:
org.hibernate.service.UnknownServiceException: Unknown service requested [org.hibernate.engine.jdbc.connections.spi.ConnectionProvider]
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:201)
Run Code Online (Sandbox Code Playgroud)
我的测试:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("file:src/main/webapp/WEB-INF/spring/spring-hibernate.xml")
public class AbstractHibernateRepoTest extends AbstractHibernateRepo<Video> {
@Autowired private SessionFactory sessionFactory;
private Video video;
public AbstractHibernateRepoTest()
{
super(Video.class);
}
@Before
public void setUp ()
{
video = new Video();
video.setId("xyz");
video.setName("Video Name");
video.setSrc("Source");
video.setThumbnail("Thumbnail");
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(video) ;
session.close();
}
@Test
public void testSaveMethod ()
{
video.setId("asa");
String id = (String) save(video);
Assert.assertEquals(video.getId(), id);
}
@After
public void breakDown ()
{
sessionFactory.close();
}
}
Run Code Online (Sandbox Code Playgroud)
库: …
我知道这Session是Hibernate使用的一级缓存这一事实,一旦我们从 中检索实体session,对于具有相同标识符的同一实体的后续 get 调用将从而不是从 DB 中获取,直到是Open。sessionsession
话虽如此,我对休眠如何将一级缓存与数据库同步有疑问?考虑以下场景
//Lets say I have created the session
Session s1 = sessionFactory.getSession();
User u1 = s1.get(User.class, 1); //Getting User with ID=1
//s1 is not yet closed
//Lets say I create some other session
Session s2 = sessionFactory.getSession();
User u2 = s2.get(User.class, 1); //Getting User with ID=1
u2.setName("Abc"); // Changed a field
s2.save(u2); // Saved the changes to DB
s2.close(); //Closed …Run Code Online (Sandbox Code Playgroud) 我正在寻找一个干净的解决方案来监听事务启动。这意味着我希望侦听器成为 spring 上下文中的一个 bean(组件),它将在新事务启动时从 TransactionPlatformManager 或 Hibernate Session 或类似的东西接收事务启动事件。
沿途的一些东西:
@Component
class TransactionListener implements ?? {
@Autowired
private Something x;
public void onTransactionBegin(...) {
x.doSomething()
}
}
Run Code Online (Sandbox Code Playgroud)
具体来说,我正在缓解系统范围的问题,并且我需要在事务开始时设置一个本地线程,这样我就可以在处理休眠实体时进一步访问该本地线程以检索信息。
我查看了来源,没有发现任何可以实现此类监听器的痕迹。我发现的唯一解决方案是子类化 HibernateTransactionManager 及其 doBegin() 方法,我觉得这不是特别好。
hibernate ×9
java ×6
spring ×5
spring-test ×2
grails ×1
grails-orm ×1
jpa ×1
proxy ×1
session ×1