我有一个非常基本的Spring Boot/JPA stack应用程序,它有一个控制器、服务层和存储库,它不像我所理解的那样持久更新。
微不足道的实体:
java prettyprint-override">@Entity
public class Customer {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private String name;
protected Customer() {}
public Customer(String name) { this.name = name; }
// standard getters,setters //
}
一个微不足道的存储库:
@Repository
public interface CustomerRepository extends CrudRepository<Customer, Long> {}
一个简单的服务层:
// If the service is @Transactional and the controller is not, the update does NOT occur
@Transactional
@Service
public class CustomerService {
private static final Logger LOG = getLogger(CustomerService.class);
@Autowired
private CustomerRepository customerRepository;
boolean updateCustomerName(Long id, String name) {
Customer customer = customerRepository.findOne(id);
if (customer == null) { return false; }
// Modifies the entity
customer.setName(name);
// No explicit save()
return true;
}
}
和一个REST控制器,它全部使用:
// If the controller is @Transactional and the service is not, the update occurs
@RestController
@RequestMapping("/mvc")
public class CustomerController {
@Autowired
private CustomerService customerService;
@RequestMapping(path = "{id}", method = RequestMethod.PUT)
public ResponseEntity updateCustomerName(@PathVariable Long id, @RequestParam("name") String name) {
customerService.updateCustomerName(id,name);
return ResponseEntity.noContent().build();
}
}
我启用了SQL调试日志,并查看了selects、update等。
使用上面的代码:当服务方法被控制器调用时,修改的实体不持久化。SQL日志显示实体的select
,但没有update
。
如果没有标记@transactional
,则也不会更新
如果我将显式的customerRepository.save(customer)
添加到服务方法中,那么也会发生更新。但我的理解是ORM应该自动保存修改过的持久实体。
我确信这个问题与web请求中的EntityManager生命周期有关,但我感到困惑。是否需要进行其他配置?
完整示例请访问https://github.com/monztech/so-41515160
编辑:这已经解决了,见下文。根据Spring规范,@transactional
在package-private方法中不起作用,并且错误地没有将update service方法公有。
如果方法为public
并且服务类具有@transactional
批注,则将发生更新。
不过,我还有另一个问题。为什么@transactional
注释是必需的?(没有它就不会发生更新)实体管理器不应该仍然保持对象吗,因为Spring使用了视图中的open session机制,而不依赖于任何事务?
使updateCustomerName
方法公开。
Spring V4.2.5发行版 Hibernate V5.1.0.final 我有一个Junit测试方法,它执行加载、更新属性并调用。 在方法签名中添加会阻止执行更新SQL(日志中没有生成SQL)。 删除,将生成更新SQL,并更新数据库。 实体是使用Netbeans的实体类从数据库自动生成的。 主实体与FetchType.Eager有一对一的关系,与FetchType.Eager有一对多的关系(
@Transactional标记是最近添加的。所以不确定它是否像预期的那样工作。 代码: 服务类别:
问题内容: 考虑一下我有一个方法以ActiveRecord模式样式执行一些工作和日志记录机制: 在失败的情况下,我想保留一条错误消息,但是如果我抛出异常,catch子句中的事务将被回滚并且我的LogEntry将不会保留。我看到的唯一方法是手动调用after 。 有没有更干净的解决方案来执行此操作? 谢谢。 UPD: 由于我有一个执行持久化的静态方法,因此我需要对接受的答案应用以下技巧: 问题答案:
在我的代码中,服务方法savePerson被注释为@Transactional。在这个方法中,Person实体被持久化,并且在中间故意抛出运行时异常。我支持不提交事务,但Person实体将保留在数据库中。。。。回滚不起作用,我不知道为什么。 这是我的Hibernate配置: 这是我的服务: 刀
但获得以下异常: 我搜索了一下,在SO上找到了类似的问题,解决方法如下: 这就解决了问题。但在该解决方案中,手动开始和提交事务会有很多麻烦。 请帮帮忙。
当我更新Service Worker时,我关闭并重新打开页面,并获得新的Service Worker已安装并激活的控制台日志,旧的缓存已被删除。但是,列出要添加到缓存中的文件不会再次从服务器获取,它们是几小时前的旧版本。没有办法让它更新文件,除非清除Chrome开发工具中的存储。 安装新版本时,如何让我的服务人员使用新文件填充其缓存? 例如,当服务人员更新时,“stylesheet.css”仍然是