I have a scanario where i have to make multiple stored procedure calls. If any one of the stored procedures fail, i have to roll back all the procedures.
May i please know how to achieve this using spring jdbc template. What i know is that i can call only one stored procedure using the spring jdbc template.
Is there any way to invoke a group of procedures in sequence using spring jdbc template?
One way of solving this problem is to create another new stored procedure and call all the procedures in this.
Is there any other efficient way to achieve this?
Following code will call multiple stored procedures within the same transaction.
#Transactional(rollbackFor=Exception.class)
public void callStoredProcedures(){
// Stored procedure 1
//....
// Stored procedure n
}
A transaction would be initialized at the method start. All the subsequent database calls within that method will take part in this transaction and any exception within the method context would rollback the transaction.
Note that the transaction rollback for this method is configured for any Exception. By default a transaction is marked for rollback on exceptions of type RuntimeException and JdbcTemplate methods throw DataAccessException which is its subclass. If no rollback is required for checked exceptions the (rollbackFor=Exception.class) can be removed.
Also , for #Transactional annotation to work , enable transaction management. Please go through #EnableTransactionManagement
Related
I would like your point of view about writing Oracle PL/SQL stored procedures and calling them in a Zend framework 3 controller.
If in my PL/SQL strored procedure I have a commit at the end of my procedure, and I use it in a controller with in proper transaction code, if there is an exception in my PHP code after calling the stored procedure, does the commit set in the database ? even if in my PHP code the rollback function is called ?
Once your PL/SQL procedure issues COMMIT, that's it. Any subsequent rollback won't have any influence on what you already committed.
We have a spring cloud stream app using Kafka. The requirement is that on the producer side the list of messages needs to be put in a topic in a transaction. There is no consumer for the messages in the same app. When i initiated the transaction using spring.cloud.stream.kafka.binder.transaction.transaction-id prefix, I am facing the error that there is no subscriber for the dispatcher and a total number of partitions obtained from the topic is less than the transaction configured. The app is not able to obtain the partitions for the topic in transaction mode. Could you please tell if I am missing anything. I will post detailed logs tomorrow.
Thanks
You need to show your code and configuration as well as the versions you are using.
Producer-only transactions are discussed in the documentation.
Enable transactions by setting spring.cloud.stream.kafka.binder.transaction.transactionIdPrefix to a non-empty value, e.g. tx-. When used in a processor application, the consumer starts the transaction; any records sent on the consumer thread participate in the same transaction. When the listener exits normally, the listener container will send the offset to the transaction and commit it. A common producer factory is used for all producer bindings configured using spring.cloud.stream.kafka.binder.transaction.producer.* properties; individual binding Kafka producer properties are ignored.
If you wish to use transactions in a source application, or from some arbitrary thread for producer-only transaction (e.g. #Scheduled method), you must get a reference to the transactional producer factory and define a KafkaTransactionManager bean using it.
#Bean
public PlatformTransactionManager transactionManager(BinderFactory binders) {
ProducerFactory<byte[], byte[]> pf = ((KafkaMessageChannelBinder) binders.getBinder(null,
MessageChannel.class)).getTransactionalProducerFactory();
return new KafkaTransactionManager<>(pf);
}
Notice that we get a reference to the binder using the BinderFactory; use null in the first argument when there is only one binder configured. If more than one binder is configured, use the binder name to get the reference. Once we have a reference to the binder, we can obtain a reference to the ProducerFactory and create a transaction manager.
Then you would just normal Spring transaction support, e.g. TransactionTemplate or #Transactional, for example:
public static class Sender {
#Transactional
public void doInTransaction(MessageChannel output, List<String> stuffToSend) {
stuffToSend.forEach(stuff -> output.send(new GenericMessage<>(stuff)));
}
}
If you wish to synchronize producer-only transactions with those from some other transaction manager, use a ChainedTransactionManager.
I'm calling a java stored procedure from oracle. After i called execute() method it is never coming out of SP execution and locking the tables. But after i stop the server, the records are getting inserted into tables. Any one face similar issue?
Got the solution. Before calling the SP, i'm doing many insert and update statements and they are locking 5 to 6 tables. I committed the transaction before calling the SP and after that my SP is running fine.
I am new to Spring framework and trying to implement a simple CRUD application in spring boot with MySQL as database. Everything is working fine.
I have the Auto Increment enabled on Id field in the database. I am using EntityManager.persist() method to save the data in database and it is working fine. Now I want to return the auto generatedId back to the client as response of POST method but EntityManager.persist()return type is void.
Can anyone help me that how I can return the Id back?
the id is guaranteed after flush operation or when the transaction is completed.
em.persist(employee)
em.flush();
long id = employee.getId();
for more details read
What's the advantage of persist() vs save() in Hibernate?
I was wondering if there is a way for Flyway to accept an actual SQL migration as a string or a stream instead of searching for it on a classpath?
I'm constructing the SQL migration in Java on the fly and would like to call Flyway API and pass the migration as a paramter.
Please, let me know if this is possible.
Thank you
Not entirely what you are asking for, but looks like Java-based migrations might be a solution.
Basically instead of V1_0__script.sql you write V1_0__script.java class implementing JdbcMigration. Inside that class you have access to JDBC Connection:
class V1_0__script implements JdbcMigration {
public void migrate(Connection connection) throws Exception {
//...
}
}
In migrate() you are free to run your custom SQL queries.
There is no API available for this.
However, if you construct your SQL on the fly, it surely must be possible to construct it one statement at a time. Each statement can then be executed using the Connection parameter you get in a JdbcMigration