我在Spring Boot文档中看到了JPA配置的这个属性spring.jpa.open-in-view=true.那么它被设置为true,它是默认值吗?
它到底意味着什么?我没有找到任何解释这种行为.
它应该是使用Hibernate SessionFactory来代替EntityManagerFactory?如果是,我该如何设置EntityManagerFactory?
感谢任何帮助.
谢谢!
我正在尝试使用命令模式来允许我的Web层在单个事务的上下文中使用Hibernate实体(从而避免延迟加载异常).但是,我现在对如何处理交易感到困惑.
我的命令调用使用@Transactional注释注释的服务层方法.这些服务层方法中的@Transactional(readOnly=true)一些是只读的- 例如- 并且一些是读/写的.
我的服务层公开了一个命令处理程序,它执行代表Web层传递给它的命令.
@Transactional
public Command handle( Command cmd ) throws CommandException
Run Code Online (Sandbox Code Playgroud)
我假设我正确地使命令处理程序的handle()方法成为事务性的.这就是混乱的来源.如果命令的实现调用多个服务层方法,命令处理程序无法知道命令中调用的操作是只读,读/写还是组合两个.
我不明白传播在这个例子中是如何工作的.如果我要创建该handle()方法readOnly=true,那么如果该命令随后调用带有注释的服务层方法会发生什么@Transactional(realOnly=false)?
我希望更好地理解这一点并欢迎您的评论......
安德鲁
对于WebApplicationContext,我应该@Transactional在控制器或服务中添加注释吗?Spring文档让我有些困惑.
这是我的web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>Alpha v0.02</display-name>
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>*.json</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
Run Code Online (Sandbox Code Playgroud)
这是我的application-context.xml,它定义了一个spring dispatcher servlet:
<?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:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:annotation-config />
<mvc:annotation-driven />
<tx:annotation-driven />
<context:component-scan base-package="com.visitrend" />
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" …Run Code Online (Sandbox Code Playgroud) 我已经安排了一个带有 annotation 的作业@Scheduled,它应该使用 spring data jpa 处理数据并将其保存到数据库中。save调用该方法没有任何异常,但没有插入数据库。在同一个带注释的方法中,我调用了findAll工作正常并获取数据的方法。可能是什么原因?
@Repository
public interface PossibleOfferLinkRepository extends PagingAndSortingRepository<PossibleOfferLink, Long> {
}
@Configuration
@ComponentScan
@EnableAutoConfiguration
@Import({Scheduler.class})
@EntityScan(basePackages="model_package")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@EnableScheduling
@ConditionalOnProperty(value= "property_name")
public class Scheduler {
...
@Scheduled(fixedRate=100000)
public void scheduleCrawlerJob() throws MalformedURLException {
Iterable<PossibleOfferLink> links = repo.findAll();
PossibleOfferLink link = repo.save(new PossibleOfferLink(new URL("...")));
}
}
Run Code Online (Sandbox Code Playgroud)
马文
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.1.8.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency> …Run Code Online (Sandbox Code Playgroud) 我正在使用Spring 3.1并编写了我的DAO和服务层(事务性).
但是在特殊情况下,为了避免延迟初始化异常,我必须创建一个spring mvc请求处理程序方法@transactional.但它没有将事务附加到该方法.方法名称是ModelAndView home(HttpServletRequest请求,HttpServletResponse响应). http://forum.springsource.org/showthread.php?46814-Transaction-in-MVC-Controller 从这个链接看来,无法将事务(默认情况下)附加到mvc方法.该链接中建议的解决方案似乎适用于Spring 2.5(覆盖handleRequest).任何帮助都会得到真正的认可.谢谢
@Controller
public class AuthenticationController {
@Autowired
CategoryService categoryService;
@Autowired
BrandService brandService;
@Autowired
ItemService itemService;
@RequestMapping(value="/login.html",method=RequestMethod.GET)
ModelAndView login(){
return new ModelAndView("login.jsp");
}
@RequestMapping(value="/home.html",method=RequestMethod.GET)
@Transactional
ModelAndView home(HttpServletRequest request, HttpServletResponse response){
List<Category> categories = categoryService.readAll();
request.setAttribute("categories", categories);
List<Brand> brands = brandService.readAll();
request.setAttribute("brands", brands);
List<Item> items = itemService.readAll();
request.setAttribute("items", items);
Set<Image> images = items.get(0).getImages();
for(Image i : images ) {
System.out.println(i.getUrl());
}
return new ModelAndView("home.jsp");
}
Run Code Online (Sandbox Code Playgroud) 我正在使用实体管理器的本机方法,并且我想在发生某些错误时回滚。为此,我尝试了@Transactional注释,但这不会回滚。下面是我的示例代码
控制器
@Autowired
ServiceImpl ServiceImpl;
@RequestMapping("/saveinfo")
@ResponseBody
@Transactional
public String saveinfo(Long id)
{
ServiceImpl.saveInfo(id);
}
Run Code Online (Sandbox Code Playgroud)
服务等级
@Autowired
DAOImpl daoImpl;
@Transactional
public String saveinfo(Long id)
{
daoImpl.saveInfo1(id);
daoImpl.saveInfo12(id);
daoImpl.saveInfo12(id);
}
Run Code Online (Sandbox Code Playgroud)
DAO类
@Override
public BigInteger saveInfo11() {
Query query = entityManagerUtil.entityManager().createNativeQuery("insert query");
return (BigInteger)query.getSingleResult();
}
@Override
public BigInteger saveInfo12() {
Query query = entityManagerUtil.entityManager().createNativeQuery("insert query");
return (BigInteger)query.getSingleResult();
}
@Override
public BigInteger saveInfo13() {
Query query = entityManagerUtil.entityManager().createNativeQuery("insert query");
return (BigInteger)query.getSingleResult();
}
Run Code Online (Sandbox Code Playgroud)
现在在上面的代码中,
如果我有一些运行时错误,saveInfo3()那么我想回滚 和 的
saveInfo1()方法saveInfo2() …
我@Transactional在控制器类中有如下方法:主要问题是每个服务调用根据日志在其自己的事务中运行。
控制器是否忽略了事务功能?
我希望学生记录不会被保存,因为我在使用另一个服务之后抛出异常,但更新仍然发生在数据库中。我什至有@EnableTransactionManagement配置类。你能帮我解决这个问题吗?
@RestController
@RequestMapping("/api")
public class Resource {
@Transactional
@RequestMapping(value="/test", method = RequestMethod.PUT, produces = "application/json")
public StudentDTO updateRecord(@RequestBody StudentDTO DTO) throws ApplicationException{
studentservice.find(1234); //jparepository.findone() runs in one transaction
studentservice.save(dto); //jparepository.save() runs in one transaction
testservice.throwException(); // this method throws application exception
}
@Configuration
@ComponentScan(basePackages={"com.student.*"})
@EnableAutoConfiguration(exclude = {MetricFilterAutoConfiguration.class, MetricRepositoryAutoConfiguration.class})
@EnableConfigurationProperties
@EnableTransactionManagement
public class Application {
}
Run Code Online (Sandbox Code Playgroud)
下面是日志:
[TRACE] org.springframework.transaction.interceptor.TransactionInterceptor - Getting transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.findOne]
[TRACE] org.springframework.transaction.interceptor.TransactionInterceptor - Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.findOne]
[TRACE] org.springframework.transaction.interceptor.TransactionInterceptor - Getting …Run Code Online (Sandbox Code Playgroud) 我认为最好的做法是将@Transactional注释放在服务层类上,而不要放在控制器上(请参阅fe 为什么我们不应该将Spring MVC控制器设为@Transactional?)。但这不适用于我的Spring Boot应用程序。这是为什么?
registerAction控制器中的方法(请参见下面的代码)执行多个服务调用。当fe mailService.sendActivationMail(...)失败时,我想从userService.registerUser(...)呼叫中回滚插入的用户。是否需要将@Transactional注释放在控制器类上?
当@Transactional在控制器类上设置注释时,我的Spring Boot应用程序正确使用事务:
AuthController.java
@RestController
@RequestMapping("/api/auth")
@Transactional
public class AuthController {
@Autowired
private UserService userService;
@Autowired
private ProfileService profileService;
@Autowired
private MailService mailService;
@RequestMapping(path = "register", method = RequestMethod.POST)
public Profile registerAction(@Valid @RequestBody Registration registration) {
ApiUser user = userService.registerUser(registration);
Profile profile = profileService.createProfile(user, registration);
mailService.sendActivationMail(user);
return profile;
}
}
Run Code Online (Sandbox Code Playgroud)
但是,当在@TransactionalService类上(而不是在控制器上)设置注释时,事务不起作用:
UserService.java
@Service
@Transactional
public class UserService {
@Autowired
private ApiUserRepository userRepository; …Run Code Online (Sandbox Code Playgroud) 我在Spring有休息风格控制器.在控制器中我注入了dao接口.从控制器我坚持数据.换句话说,我喜欢REST Web服务.人们发给我数据,我坚持下去.
/**
* Payment rest controller which receives
* JSON of data
*/
@Controller
@RequestMapping("/data")
public class PaymentTransaction {
@Autowired
private TestDao dao;
@RequestMapping(value = "/test", method = RequestMethod.POST)
@ResponseBody()
public String test(HttpServletRequest request) {
...
}
Run Code Online (Sandbox Code Playgroud)
目前我在Dao类中有@transaction注释.例如:
import org.springframework.transaction.annotation.Transactional;
@Component
@Transactional
public interface TestDao {
@Transactional(propagation = Propagation.REQUIRED)
public void first();
}
Run Code Online (Sandbox Code Playgroud)
我读过这是非常糟糕的风格.在stackoverflow上使用这个答案,这里有解释和示例为什么这很糟糕 - 我们不能在DAO和控制器中添加这个注释.我们必须在服务层添加它.
但我不明白什么是服务层?或者在哪里?我没有这样的东西.我应该在哪里写@Transactional注释?
最好的祝福,
当我在spring mvc中调用EntityManager.persist()时出现异常,虽然@Transactional在方法上添加了它,但它可以在不集成spring mvc的情况下工作:
HTTP ERROR 500
Problem accessing /ssshp/addDept/wwewd. Reason:
No EntityManager with actual transaction available for current thread - cannot reliably process 'persist' call
Caused by:
javax.persistence.TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably process 'persist' call
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:278)
at com.sun.proxy.$Proxy49.persist(Unknown Source)
at cn.ziav.ssshp.facade.SpringFacadeImpl.createDept(SpringFacadeImpl.java:28)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:817)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:731)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at …Run Code Online (Sandbox Code Playgroud) 我正面临着有趣的 LazyInitializationException 解决方案。为了防止这种情况(在 OneToMany 或 ManyToMany 上),一种已知的解决方案是使用 JOIN FETCH Query。你可以看到她的几个例子之一:https ://thoughts-on-java.org/best-practices-for-many-to-many-associations-with-hibernate-and-jpa/
其他更简单的解决方案是使用 Spring 中的 @Transactional。例如像这样:
@DeleteMapping(value ="/product/{tagId}")
@ResponseBody
@Transactional
public String deleteProductWithoutRelation(@PathVariable String product, Model model) {
Optional<Product> pr = productService.selectProduct(product);
if (pr.isPresent()) {
tag.get().getCustomer().size(); //usualy throws LazyInitializationException,
//without JOIN-FETCH Statment or @Transactional
return deletedTagId;
}
Run Code Online (Sandbox Code Playgroud)
当然,您可以在存储库服务中放置一些方法的@Transactional,以封装此解决方案。那么这两种解决方案的优点或缺点是什么?
spring ×10
java ×6
jpa ×5
hibernate ×4
spring-mvc ×4
spring-boot ×3
spring-data ×2
transactions ×2
controller ×1
java-ee ×1
service ×1