Dai*_*mon 2 java spring hibernate jpa spring-boot
我正在使用弹簧靴,它完美地让我成为实体经理.我决定从实体管理器测试获取会话工厂并将其用作示例.但我得到了下一个问题:javax.persistence.TransactionRequiredException: no transaction is in progress
性能
spring.datasource.url= jdbc:postgresql://localhost:5432/ring
spring.datasource.username=postgres
spring.datasource.password=root
spring.jpa.show-sql = false
spring.jpa.properties.hibernate.format_sql=false
#Note: The last two properties on the code snippet above were added to suppress an annoying exception
# that occurs when JPA (Hibernate) tries to verify PostgreSQL CLOB feature.
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQL9Dialect
spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults = false
spring.jpa.properties.hibernate.current_session_context_class = org.springframework.orm.hibernate5.SpringSessionContext
Run Code Online (Sandbox Code Playgroud)
服务类
package kz.training.springrest.service;
import kz.training.springrest.entity.User;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceUnit;
@Service
public class UserService {
@PersistenceContext
private EntityManager entityManager;
@Transactional
public void insertUser(User user) {
SessionFactory sessionFactory = entityManager.unwrap(Session.class).getSessionFactory();
Session session = sessionFactory.getCurrentSession();
session.save(user);
}
}
Run Code Online (Sandbox Code Playgroud)
跑步者
package kz.training.springrest.run;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@SpringBootApplication
@EntityScan("kz.training.springrest.entity")
@EnableTransactionManagement
@ComponentScan(basePackages="kz.training.springrest")
public class SpringrestApplication {
public static void main(String[] args) {
SpringApplication.run(SpringrestApplication.class, args);
}
}
Run Code Online (Sandbox Code Playgroud)
你有任何想法如何解决它?
我不太明白为什么你的服务方法如此不必要地复杂化.你应该只是这样做
@Transactional
public void insertUser(User user) {
entityManager.persist( user );
}
Run Code Online (Sandbox Code Playgroud)
如果有需要访问本机Hibernate的点,您Session可以直接打开并Session直接使用如下:
@Transactional
public void doSomethingFancyWithASession() {
Session session = entityManager.unwrap( Session.class );
// use session as needed
}
Run Code Online (Sandbox Code Playgroud)
这里的概念是Spring EntityManager使用@PersistenceContext注释为您提供已经功能的实例.该实例将安全地用于您的spring bean正在执行的当前线程.
其次,通过使用@Transactional,这会导致Spring的事务管理自动确保EntityManager绑定到事务,无论是事务RESOURCE_LOCAL还是JTA事务都基于您的环境配置.
你因为打电话问题而遇到了问题#getCurrentSession().
发生了什么是Spring创建的EntityManager,然后当你调用时在你的方法中#getCurrentSession(),你要求Hibernate创建一个第二个会话,它不受你的@Transactional注释启动的事务的约束.简而言之,它基本上类似于以下内容:
EntityManager entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
Session aNewSession = entityManager.unwrap( Session.class )
.getFactory()
.getCurrentSession();
// at this point entityManager is scoped to a transaction
// aNewSession is not scoped to any transaction
// this also likely uses 2 connections to the database which is a waste
Run Code Online (Sandbox Code Playgroud)
所以按照我上面提到的范例,你应该不再遇到问题.如果您正确地允许Spring 为您注入实例,则永远不需要调用#getCurrentSession()或#openSession()在Spring环境中调用EntityManager.
| 归档时间: |
|
| 查看次数: |
5438 次 |
| 最近记录: |