我有一个主要的 DB 处理程序方法,它调用其他方法,这些方法也与 BD 事物一起工作。
我为 main 方法添加了 @Transactional 注释,因为如果出现问题,我想回滚所有内容。
我的问题是:我是否应该也为子方法添加此注释,或者它会知道子方法是从事务性方法调用的。
比如删除方法中出现异常,如何保证写入部分也会回滚:
@Transactional
public void maintDbTings() {
writing();
deleting();
}
@Transactional //do I need this?
public void writing() {
//no exceptions
}
@Transactional //do I need this?
public void deleting() {
//exception occurs
}
Run Code Online (Sandbox Code Playgroud) 我在使用Spring(3.0.5),Hibernate(3.6.0)和Wicket(1.4.14)开发应用程序时遇到了奇怪的问题.问题是:我无法将任何对象保存或修改为数据库.通过'不能',我的意思是对象的所有更改或对EntityManager.persist(foo)的调用都被简单地,默默地忽略.选择工作.
示例案例很简单 - 在一些wicket页面上我尝试将对象保存到数据库中,如下所示
public class ComicDetailsPage extends PublicBasePage {
@Override
protected void onConfigure() {
System.out.println("In onConfigure");
super.onConfigure();
comicDAO.insert("abc");
}
@SpringBean(name="comicDAO")
private ComicDAO comicDAO;
(....)
Run Code Online (Sandbox Code Playgroud)
这是comicDAO
@Service
public class ComicDAO {
@PersistenceContext
private EntityManager em;
(...)
@Transactional
public void insert(String title) {
Comic c = new Comic();
c.setTitle(title);
em.persist(c);
}
@Transactional
public Comic add1toTitle(int pk) {
System.out.println("Beginning fetching");
Comic c = em.find(Comic.class, pk);
System.out.println("Fetched updating");
c.setTitle(c.getTitle()+"1");
System.out.println("Updated persisting");
em.persist(c);
System.out.println("Persisted returning");
return c;
}
Run Code Online (Sandbox Code Playgroud)
我打开了日志记录,这里是日志的相关部分(Hibernate和Spring都设置为TRACE).我将**添加到我认为在这里很重要的行.
In onConfigure
01:53:19.330 [qtp2119047503-15] DEBUG …Run Code Online (Sandbox Code Playgroud) 作为网络应用程序的一部分,我正在尝试构建一个注册过程。验证流程后,需要执行三个 sql 语句。如果任何失败,那么它们都应该回滚。但是,如果我故意编写第三条sql失败(使用不存在的表名)。我看到抛出异常,但第一个和第二个 swl 语句没有回滚。
有人可以告诉我应该如何做吗?
来自我的 application-context.xml
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="userDAO" class="com.doyleisgod.golf.database.JdbcUserDao">
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="registration" class="com.doyleisgod.golf.services.Registration"/>
<tx:annotation-driven />
Run Code Online (Sandbox Code Playgroud)
我的注册服务班
public class Registration implements IRegistration {
@Autowired JdbcUserDao userDAO;
@Override
@Transactional (rollbackFor = Exception.class)
public boolean registerUser(Object command) {
return userDAO.registerUser(command);
}
}
Run Code Online (Sandbox Code Playgroud)
我的userDAO注册方法
public boolean registerUser(Object command) {
try {
setUserCommand(command);
sql = "INSERT INTO users (USERNAME,PASSWORD, ENABLED)VALUES ('"+username+"', '"+EncryptedPassword+"', TRUE);";
getSimpleJdbcTemplate().update(sql);
sql = "INSERT INTO user_roles (USERNAME,AUTHORITY)VALUES ('"+username+"', 'ROLE_USER');";
getSimpleJdbcTemplate().update(sql); …Run Code Online (Sandbox Code Playgroud) 我使用的是Spring 3.0.5,Hibernate 3.6.7和Vaadin.
我有一个像这样的简单实体
@Entity
public class Foo {
@OneToMany(fetch = FetchType.LAZY)
private Collection<Bar> bars;
...
}
Run Code Online (Sandbox Code Playgroud)
我有一个对话窗口,我从上下文中得到它应该显示'foo'中的'bars'.
@Component
@Scope("prototype")
public class FooBarDialogImp extends Window implements FooBarDialog {
@Transactional(readOnly = true)
public void populate(Foo foo) {
...
for (Bar bar : foo.getBars()) {
// populate the dialog with bar information
...
}
}
}
Run Code Online (Sandbox Code Playgroud)
当用户要求显示foo栏时,我会做这样的事情
public class FooController {
...
public void showFooBars(Foo foo) {
FooBarDialog dialog = context.getBean(FooBarDialog.class);
dialog.populate(foo);
showDialog(dialog);
}
}
Run Code Online (Sandbox Code Playgroud)
但问题是我从hibernate获得了"无会话"异常.我更改了代码以注入会话工厂并查看是否存在绑定会话.我不知道我做错了什么.有人有想法吗?
事务性注释是在它工作的DAO层中,如果我将它移动到服务层,我会得到异常:
Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.adam.czibere.RestAPIController]: Illegal arguments for constructor; nested exception is java.lang.IllegalArgumentException: argument type mismatch
Run Code Online (Sandbox Code Playgroud)
这是我的代码:
CatalogDAOInterface:
public interface CatalogDAOInterface {
public List<Product> getAllProduct();
public List<Category> getAllCategories() ;
public List<Media> getAllMedias();
}
Run Code Online (Sandbox Code Playgroud)
CatalogDAO的:
@Repository
@SuppressWarnings({"unchecked", "rawtypes"})
public class CatalogDAO implements CatalogDAOInterface {
@Autowired private SessionFactory sessionFactory;
@Override
public List<Product> getAllProduct() {
Session session = sessionFactory.getCurrentSession();
List products = session.createQuery("from Product").list();
return products;
}
@Override
public List<Category> getAllCategories() {
Session …Run Code Online (Sandbox Code Playgroud) 我有一个迭代事件列表并将它们保存到表中的进程.如果某个特定事件抛出异常,我需要能够使用数据库回滚该事件的事务,而不会影响其他事件的流程.
为此,我有以下设置:
public class EventService
{
public void processEvents()
{
List<Event> events = getEvents();
foreach(Event event : events)
{
try
{
processEvent(event);
}
catch(Exception e)
{
// log the exception and continue processing additional events
}
}
}
@Transactional
public void processEvent(Event event)
{
// Process event and insert rows into database
// Some event will throw a runtime exception
}
}
Run Code Online (Sandbox Code Playgroud)
但是,如果抛出异常,则不会回滚事件.
有没有办法实现我在这里要做的事情?
我有一个如下代码
public abstract class AffltTransactionService implements IAffltTransactionService {
....
@Override
@Transactional
public void processTransactions(List<? extends AffltTransaction> transactions) {
for (AffltTransaction transaction : transactions) {
if (transaction != null) {
processTransaction(transaction);
}
}
}
private void processTransaction(AffltTransaction transaction) {
try {
processTransactionInternal(transaction);
} catch (Exception exception) {
affltTransactionError = new AffltTransactionError(null, null, "error", new Date());
saveAffltTransactionError(affltTransactionError);
log.error(exception.getLocalizedMessage());
}
}
@Transactional(readOnly=false, rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
public void processTransactionInternal(AffltTransaction transaction) {
Run Code Online (Sandbox Code Playgroud)
processTransactionInternal抛出ServiceUnAvailableException,它扩展了RuntimeException
但是,尽管有rollbackFor = Exception.class,事务仍未回滚.你能帮忙吗?
我们一直在测试一种不同的储蓄方式。然而,结果并不像我们预期的那样。我们有创建调查的方法,每个调查都有多个问题。我们测试了几个案例,它们都以相同的方式提交查询。
@Transactional class Service {
Survey createNewSurvey(NewSurveyCommand command) {
Survey survey = new Survey()
survey.properties[] = command.properties
survey.save(flush: true, failOnError: true) //save survey and flush
for (NewQuestionCommand questionCommand : command.questions) {
Question question = new Question()
question.properties[] = questionCommand.properties
question.save(flush: true, failOnError: true) // save each questions and flush
}
return survey } }
Run Code Online (Sandbox Code Playgroud)
第二个删除事务性并保存而不刷新
class Service {
Survey createNewSurvey(NewSurveyCommand command) {
Survey survey = new Survey()
survey.properties[] = command.properties
survey.save() //save survey and flush
for (NewQuestionCommand questionCommand : command.questions) …Run Code Online (Sandbox Code Playgroud) 问题 1:删除查询是否作为 mysql/mariadb 中的整个事务运行。因此,如果我们有 100 万行要删除,mysql/mqriadb 服务器是否会将其作为一个整体删除,或者如果在删除某些行后出现问题,已删除的行将被恢复。
Q2:我们是需要在单个删除查询中删除行(无论需要删除多少行)还是需要在删除查询中设置限制并批量执行删除。如果需要以多少(要删除的行数)进行批处理,我们应该考虑一下。
我正在使用以下方法安装 spring boot 应用程序:
@Transactional(rollbackOn = Exception.class)
private void saveAndUpdatepMSTAndRollUpEntries(pMST newpMSTEntry,
pMST existingpMSTEntry,
List<sPTrans> sPTranss,
List<sPTrans> sPTransUpdatedFlagList) {
if(!ObjectUtils.isEmpty(existingpMSTEntry))
databaseService.deleteProcessedpMST(existingpMSTEntry);
if(!CollectionUtils.isEmpty(sPTransUpdatedFlagList))
databaseService.saveProcessedsPTransFeedWithUpdatedFlag(sPTransUpdatedFlagList);
if(!ObjectUtils.isEmpty(newpMSTEntry))
databaseService.saveProcessedpMSTTableEntry(newpMSTEntry);
}
Run Code Online (Sandbox Code Playgroud)
我的数据库服务包含如下代码:
public class DatabaseService {
private PosMonthlyStRepository posMonthlyStRepository;
private ScmsaPosTransRollupRepository scmsaPosTransRollupRepository;
public DatabaseService(PosMonthlyStRepository posMonthlyStRepository) {
this.posMonthlyStRepository = posMonthlyStRepository;
}
public void deleteProcessedpMST(pMST objpMST){
posMonthlyStRepository.delete(objpMST);
}
public void saveProcessedsPTransFeedWithUpdatedFlag(List<sPTrans> sPTransssPTransUpdatedFlagList) {
scmsaPosTransRollupRepository.save(sPTransUpdatedFlagList);
}
public void saveProcessedpMSTTableEntry((pMST objpMST) {
posMonthlyStRepository.save(objpMST);
}
}
Run Code Online (Sandbox Code Playgroud)
但是每当发生异常时,事务都不会回滚,任何人都可以建议我在这里做错了什么。
java spring exception-handling transactional spring-transactions
transactional ×10
spring ×8
java ×6
hibernate ×3
transactions ×3
rollback ×2
commit ×1
grails ×1
groovy ×1
hql ×1
jpa ×1
mariadb ×1
mysql ×1
performance ×1
spring-mvc ×1
sql-delete ×1