

Lorsque vous essayez de démarrer deux tâches Spring Batch ou plus en même temps, une erreur est générée : ORA-08177 : Impossible de sérialiser l'accès pour cette transaction
L'éditeur php Xigua peut rencontrer un problème lors de l'utilisation de Spring Batch : lorsque vous essayez de démarrer deux ou plusieurs tâches Spring Batch en même temps, une erreur sera générée : ORA-08177 : Impossible de sérialiser l'accès à cette transaction. Cette erreur peut prêter à confusion, mais elle est en réalité causée par un problème de verrouillage de la base de données. Avant de résoudre ce problème, nous devons comprendre certaines connaissances de base sur Spring Batch et les transactions de base de données.
Contenu de la question
J'ai rencontré une erreur en essayant d'utiliser completablefuture pour exécuter deux tâches Spring Batch en parallèle. Le message d'erreur est le suivant :
originalsql = insert into batch_job_instance(job_instance_id, job_name, job_key, version) values (?, ?, ?, ?) , error msg = ora-08177: can't serialize access for this transaction
J'utilise Spring Batch 5.x, Spring Boot 3.1.6, JDK 17
Propriétés de l'application
spring.batch.repository.isolationlevelforcreate=isolation_read_committed spring.batch.isolationlevel=read_committed spring.batch.jdbc.table-prefix=batch_ spring.batch.job.enabled=false
batchconfig.java
@configuration public class batchconfig { @bean("simpletaskexecutor") public taskexecutor simpletaskexecutor() { simpleasynctaskexecutor asynctaskexecutor = new simpleasynctaskexecutor("simpletaskexecutor"); asynctaskexecutor.setconcurrencylimit(concurrencycount); return asynctaskexecutor; } @bean("joblauncherasync") @scope("prototype") public joblauncher joblauncherasync(datasource datasource, jobrepository jobrepository) throws exception { taskexecutorjoblauncher joblauncher = new taskexecutorjoblauncher(); joblauncher.setjobrepository(jobrepository); joblauncher.settaskexecutor(simpletaskexecutor()); joblauncher.afterpropertiesset(); return joblauncher; } @bean public jpatransactionmanager transactionmanager(entitymanagerfactory entitymanagerfactory) { return new jpatransactionmanager(entitymanagerfactory); } @bean public batchjobexecutionlistener batchjobexecutionlistener() { return new batchjobexecutionlistener(); } @bean public batchjobstepexecutionlistner batchjobstepexecutionlistner() { return new batchjobstepexecutionlistner(); }
}
employeejobconfig.java
@configuration @import(batchconfig.class) public class employeejobconfig{ @autowired employeestatuswritter employeestatuswritter; @autowired employeependingprocessor employeependingprocessor; @bean("employeependingreader") public jpapagingitemreader<employee> employeependingreader(datasource ds,entitymanagerfactory entitymanagerfactory) { jpapagingitemreader<employee> jpareader = new jpapagingitemreader<>(); jpareader.setentitymanagerfactory(entitymanagerfactory); jpareader.setquerystring("select e from employee e"); jpareader.setpagesize(5000); return jpareader; } @bean("employeespinvokestep") public step employeespinvokestep(@qualifier("employeependingreader") itemreader<employee> reader, @qualifier("employeestatuswritter") itemwriter<employee> writer, @qualifier("employeependingprocessor") itemprocessor<employee, employee> processor,jobrepository jobrepository, platformtransactionmanager transactionmanager,batchjobstepexecutionlistner batchjobstepexecutionlistner,taskexecutor simpletaskexecutor) { return new stepbuilder("employeespinvokestep",jobrepository) .<employee, employee>chunk(50,transactionmanager).reader(reader) .processor(processor).writer(writer) .listener(batchjobstepexecutionlistner) .taskexecutor(simpletaskexecutor) .build(); } @bean("employeespjob") public job employeespjob(@qualifier("employeespinvokestep") step employeespinvokestep,jobrepository jobrepository,batchjobexecutionlistener batchjobexecutionlistener) { return new jobbuilder("employeespjob",jobrepository) .incrementer(new runidincrementer()) .listener(batchjobexecutionlistener) .start(employeespinvokestep) .build(); } }
managerconfig.java
@configuration @import(batchconfig.class) public class managerconfig { @autowired managerstatuswritter managerstatuswritter; @autowired managerpendingprocessor managerpendingprocessor; @bean("managerpendingreader") public jpapagingitemreader<manager> managerpendingreader(datasource ds,entitymanagerfactory entitymanagerfactory) { jpapagingitemreader<manager> jpareader = new jpapagingitemreader<>(); jpareader.setentitymanagerfactory(entitymanagerfactory); jpareader.setquerystring("select m from manager m"); jpareader.setpagesize(5000); return jpareader; } @bean("managerspinvokestep") public step indvinvoiceconsctlspinvokestep(@qualifier("managerpendingreader") itemreader<manager> reader, @qualifier("managerstatuswritter") itemwriter<manager> writer, @qualifier("managerpendingprocessor") itemprocessor<manager, manager> processor,jobrepository jobrepository, platformtransactionmanager transactionmanager,batchjobstepexecutionlistner batchjobstepexecutionlistner,taskexecutor simpletaskexecutor) { return new stepbuilder("managerspinvokestep",jobrepository) .<manager, manager>chunk(5000,transactionmanager).reader(reader) .processor(processor).writer(writer) .listener(batchjobstepexecutionlistner) .taskexecutor(simpletaskexecutor) .build(); } @bean("managerspjob") public job managerspjob(@qualifier("managerspinvokestep") step indvinvoiceconsctlspinvokestep,jobrepository jobrepository,batchjobexecutionlistener batchjobexecutionlistener) { return new jobbuilder("managerspjob",jobrepository) .incrementer(new runidincrementer()) .listener(batchjobexecutionlistener) .start(indvinvoiceconsctlspinvokestep) .build(); } }
batchjobmanager.java
@service public class batchjobmanager { @autowired applicationcontext context; @autowired batchexecutorservice batchexecutorservice; @autowired batchjobrunner batchjobrunner; public void startjob() { try { system.out.println("batchjobmanager called .. "+new date()); string[] invoicenames={"employeespjob","managerspjob"}; list<string> invoicenameslist = arrays.aslist(invoicenames); launchasyn(getbatchjoblist(invoicenameslist)); } catch (exception e) { system.out.println("while loading job.."); e.printstacktrace(); } } public list<batchjob> getbatchjoblist(list<string> jobnames) throws exception{ list<batchjob> batchjoblist=new arraylist<batchjob>(); for(string job:jobnames) { batchjob batchjob= batchjob.builder().jobname(invoicejob).build(); batchjoblist.add(batchjob); } return batchjoblist; } public void launchasyn( list<batchjob> batchjoblist) throws exception{ list<completablefuture<batchjob>> batchjobfuturelist = new arraylist<completablefuture<batchjob>>(); for(batchjob batchjob:batchjoblist) { completablefuture<batchjob> jobfuture = batchexecutorservice.execute(batchjob, asynctaskexecutor); batchjobfuturelist.add(jobfuture); } completablefuture<void> jobfutureresult = completablefuture .allof(batchjobfuturelist.toarray(new completablefuture[batchjobfuturelist.size()])); completablefuture<list<canbatchjob>> allcompletablefuture = jobfutureresult.thenapply(future -> { return batchjobfuturelist.stream().map(completablefuture -> completablefuture.join()) .collect(collectors.tolist()); }); list<batchjob> resultfuturelist=allcompletablefuture.get(); for(batchjob batch:resultfuturelist) { system.out.println("status "+batch.getiscompleted()); } } }
batchexecutorservice.java
@service public class batchexecutorservice { @autowired batchjobrunner batchjobrunner; public completablefuture<canbatchjob> execute(canbatchjob canbatchjob,taskexecutor threadpooltaskexecutor){ return completablefuture.supplyasync(() -> batchjobrunner.execute(canbatchjob),threadpooltaskexecutor); } }
batchjobrunner.java
@service public class batchjobrunner { @autowired applicationcontext context; @autowired @qualifier("joblauncherasync") joblauncher joblauncherasync; /* * @autowired joblauncher joblauncherasync; */ public batchjob execute(batchjob batchjob) { try { system.out.println(" batchjob"+batchjob.getjobname()+" called ..."); joblauncherasync.run(getjob(batchjob.getjobname()), getjobparameters(batchjob.getjobname())); thread.sleep(15000); batchjob.setiscompleted(true); system.out.println(" batchjob"+batchjob.getjobname()+" completed ..."); } catch(exception e) { system.out.println("exception "+e.getmessage()); batchjob.seterrordesc(e.getmessage().tostring()); e.printstacktrace(); } return canbatchjob; } public job getjob(string jobname) { return (job) context.getbean(jobname); } public jobparameters getjobparameters(string jobname) { jobparameters jobparameters = new jobparametersbuilder() .addstring("unique_id", uuid.randomuuid().tostring(), true) .addstring("job_name", jobname, true) .adddate("execution_start_date", date.from(instant.now()), true).tojobparameters(); return jobparameters; } }
batchjob.java
public class BatchJob { private String jobName; private Boolean isCompleted; private String errorDesc; }
Les tâches s'exécutent avec succès lorsqu'elles sont exécutées une par une ou dans l'ordre. Cependant, lors de l'utilisation de completeablefuture, j'ai rencontré un problème. Est-ce que démarrer les travaux par lots de printemps en même temps est la bonne manière ?
Solution
1. Ajoutez les propriétés suivantes à application.properties
.spring.main.allow-bean-definition-overriding=true
2. Joblauncher() mis à jour, comme indiqué dans batchconfig.java ci-dessous
@bean("joblauncher") public joblauncher joblauncher(datasource datasource, jobrepository jobrepository) throws exception { taskexecutorjoblauncher joblauncher = new taskexecutorjoblauncher(); joblauncher.setjobrepository(jobrepository); joblauncher.settaskexecutor(simpletaskexecutor()); joblauncher.afterpropertiesset(); return joblauncher; }
Suppression de completeablefuture.
batchexecutorservice.java supprimé
Ajout des méthodes suivantes dans batchjobmanager.java pour appeler des tâches.
public void launchSync(List<BatchJob> batchJobList) throws Exception { for(BatchJob batchJob:batchJobList) { batchJobRunner.execute(batchJob); } }
Copier après la connexionCe qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

Video Face Swap
Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Sujets chauds





RedmiNote13RPro est un nouveau modèle avec de très bonnes performances et configuration. Ce téléphone dispose d'une fonction d'album photo caché très utile. Il peut aider les utilisateurs à masquer leurs albums photo afin que les autres ne puissent pas voir vos albums photo. Ensuite, l'éditeur vous expliquera comment masquer l'album photo sur Redmi Note13R Pro pour vous aider à protéger votre vie privée. Comment cacher un album photo sur Redmi Note13RPro ? 1. Entrez les paramètres de votre téléphone Xiaomi. 2. Cliquez ensuite sur Confidentialité et protection. 3. Cliquez à nouveau sur Protéger la confidentialité ici. 4. Cliquez sur le coffre-fort. 5. Enfin, vous pouvez créer ici un album photo privé. Questions fréquemment posées : connectez Bluetooth, modifiez le thème de la méthode de saisie, modifiez les paramètres d'usine, masquez les applications, mettez en miroir le téléviseur, NFC, activez l'installation double SIM, l'heure d'activation

Ne changez pas la signification du contenu original, affinez le contenu, réécrivez le contenu, ne continuez pas. Redmi Note13RPro a non seulement d'excellentes performances, mais offre également une expérience utilisateur encore meilleure afin de donner à chacun une expérience plus confortable. , Redmi Note13RPro est équipé d'une fonction de réglage des polices pour permettre aux utilisateurs de pouvoir ajuster les polices de votre téléphone. Si vous voulez savoir comment ajuster la taille de la police du Redmi Note13R Pro, jetez-y un œil. Comment ajuster la taille de la police sur Redmi Note13RPro ? 1. Ouvrez l'application Paramètres. 2. Faites défiler vers le bas et sélectionnez « Affichage ». 3. Cliquez sur "Taille du texte". 4. Sur cet écran, vous pouvez ajuster la taille de la police en faisant glisser le curseur ou en sélectionnant une taille de police prédéfinie. 5. Une fois le réglage terminé, appuyez sur "OK" pour enregistrer

Redmi Note13RPro est un téléphone mobile très populaire récemment. De nombreux consommateurs ont acheté ce téléphone. Cependant, de nombreux utilisateurs utilisent ce téléphone pour la première fois et ne savent donc pas comment connecter Redmi Note13RPro à l'ordinateur. L'éditeur est là pour vous expliquer. Une introduction détaillée du didacticiel est fournie. Comment connecter Redmi Note13RPro à l’ordinateur ? 1. Utilisez un câble de données USB pour connecter le téléphone Redmi à l'interface USB de l'ordinateur. 2. Ouvrez les paramètres du téléphone, cliquez sur Options et activez le débogage USB. 3. Ouvrez le gestionnaire de périphériques sur votre ordinateur et recherchez l'option de périphérique mobile. 4. Cliquez avec le bouton droit sur le périphérique mobile, sélectionnez Mettre à jour le pilote, puis sélectionnez Rechercher automatiquement les pilotes mis à jour. 5. Si l'ordinateur ne recherche pas automatiquement le pilote,

La fonction appareil photo du Redmi Note13RPro est très simple à utiliser, notamment lors de la prise de photos, elle simulera le son de l'obturateur de l'appareil photo. Cependant, cette fonction peut déranger les autres dans des situations calmes comme les bibliothèques, c'est pourquoi de nombreux utilisateurs veulent savoir comment tourner. désactiver le son de la caméra de Redmi Note13RPro, laissez l'éditeur vous le dire ci-dessous. Comment désactiver le son de la caméra sur Redmi Note13RPro ? 1. Pour la première méthode, vous devez d’abord ouvrir les paramètres de votre téléphone. 2. Recherchez ensuite les applications système dans le menu des paramètres. 3. Ensuite, nous trouvons l’option caméra sous l’interface de l’application système. 4. Enfin, nous pouvons définir s'il faut désactiver le son de la caméra dans l'interface de la caméra. Il nous suffit d'éteindre l'interrupteur sur le côté droit du son de la caméra. 5. La deuxième méthode, la première étape, ouvrez

Le téléphone mobile Redmi Note13RPro intègre un certain nombre d'outils intelligents en termes de fonctions logicielles, parmi lesquels l'extraction rapide et précise du contenu du texte des images. L'éditeur suivant vous présentera comment Redmi Note13RPro extrait le texte des images. Comment extraire le texte des images sur Redmi Note13RPro ? Utilisez la fonction de numérisation de code QR Xiaomi, ouvrez l'application de numérisation de code QR sur votre téléphone, cliquez sur l'icône d'image, sélectionnez une image, puis cliquez sur l'option « Reconnaître le texte » à droite pour extraire avec succès le texte de l'image. Fonctionner via l'album du téléphone mobile. Recherchez l'image dont le texte doit être extrait dans l'album du téléphone mobile, cliquez sur « Plus » sous l'image et sélectionnez « Extraire le texte ». Après une reconnaissance réussie, vous pouvez copier ou enregistrer le texte selon vos besoins. Utilisez les mini-programmes WeChat. Micro ouvert

Whole Huoba est un jeu de réflexion décontracté très amusant que tout le monde peut découvrir sur plusieurs plateformes ! Le jeu propose d'innombrables niveaux passionnants qui attendent d'être débloqués. Chaque niveau est plein de nouveautés et de défis, vous permettant de vivre une aventure intéressante en répondant à des questions et en déverrouillant du nouveau contenu de jeu. Alors comment effacer tout le niveau de Huoba ? Aujourd'hui je vous propose un guide complet de tous les niveaux de "Whole Life". Si vous rencontrez des problèmes pour réussir le niveau, vous pouvez vous y référer ! "The Whole Life" guide complet pour tous les niveaux de "The Whole Life" Le guide complet pour tous les niveaux de "The Whole Life" Aidez-la à regarder le réveillon du Nouvel An, aidez la petite sœur à identifier le salaud de loup et la grand-mère aide la petite fille à échapper au danger pour une aventure en plein air, en faisant semblant de ne pas voir Ah Piao et en se transformant. L'humanoïde a aidé l'orang-outan à devenir un humanoïde. Quelqu'un sur la banquette arrière est resté calme et s'est occupé du fantôme féminin. calmez-vous et traitez le fantôme féminin.

RedmiNote13RPro est un téléphone mobile apprécié par la majorité des utilisateurs. Ce téléphone fournit une méthode spéciale pour afficher le trafic sur le téléphone. Si vous ne savez toujours pas comment configurer RedmiNote13RPro pour afficher le trafic, suivez l'éditeur pour le savoir. Comment paramétrer l’affichage du trafic sur Redmi Note13RPro ? 1. Entrez « Paramètres » et cliquez sur « Réseau mobile double SIM ». 2. Faites défiler vers le bas pour sélectionner l'option « Paramètres du package de données ». 3. Activez les commutateurs de fonction sur le côté droit de « Afficher les informations routières dans la barre de notification » et « Afficher la vitesse actuelle du réseau dans la barre d'état ». 4. Une fois le réglage réussi, déroulez la barre d'état pour voir l'affichage de la vitesse du réseau et des informations routières en temps réel. FAQ Connecter Bluetooth Modifier le thème de la méthode de saisie Modifier les paramètres d'usine Masquer la diffusion de l'application

Whole Huoba est un jeu de niveau amusant très populaire sur Douyin. Il existe de nombreux niveaux dans le jeu qui attendent que tout le monde les défie ! Dans le niveau de jeu « Journey to the West Beauty », tout le monde doit aider le personnage féminin de « Journey to the West » à revenir à son poste. Comment passer le niveau ? Ce qui suit est un guide pour vous permettre de terminer le niveau de "Vie entière" dans "Journey to the West" où les beautés aident les personnages féminins de "Journey to the West" à retourner à leur place. passez le niveau, jetons un oeil. J'espère que cela pourra vous aider. La beauté de "Whole Life" Journey to the West aide le personnage féminin de Journey to the West à revenir à sa place. La beauté de Journey to the West aide le personnage féminin de Journey to the West à revenir à sa place. 1. Cliquez sur le parchemin pour faire apparaître le personnage féminin. 2. L'esprit des os blancs et l'esprit du paon doivent cliquer pour changer d'action. 3. La réponse est celle indiquée dans la figure ci-dessous : "Toute la vie". Live" a un guide complet pour tous les niveaux, l'aidant à être l'observatrice de l'année, aidant la petite sœur à identifier le salaud et le loup, et la grand-mère à aider la petite fille à échapper au danger et à vivre des aventures en plein air.