{"id":38729,"date":"2026-02-06T12:40:56","date_gmt":"2026-02-06T09:40:56","guid":{"rendered":"https:\/\/fatihsoysal.com\/blog\/?p=38729"},"modified":"2026-02-06T12:40:56","modified_gmt":"2026-02-06T09:40:56","slug":"spring-jdbc-ile-islem-yonetimi-kapsamli-bir-rehber-ve-ornek-uygulama","status":"publish","type":"post","link":"https:\/\/fatihsoysal.com\/blog\/spring-jdbc-ile-islem-yonetimi-kapsamli-bir-rehber-ve-ornek-uygulama\/","title":{"rendered":"Spring JDBC ile \u0130\u015flem Y\u00f6netimi: Kapsaml\u0131 Bir Rehber ve \u00d6rnek Uygulama"},"content":{"rendered":"<p><body><\/p>\n<h2>Spring JDBC ile \u0130\u015flem Y\u00f6netimi: Kapsaml\u0131 Bir Rehber ve \u00d6rnek Uygulama<\/h2>\n<h2>Giri\u015f<\/h2>\n<p>Modern yaz\u0131l\u0131m uygulamalar\u0131, veri tutarl\u0131l\u0131\u011f\u0131 ve g\u00fcvenilirli\u011fi sa\u011flamak i\u00e7in veritabanlar\u0131yla yo\u011fun bir \u015fekilde etkile\u015fim kurar. Bu etkile\u015fimlerde, birden fazla veritaban\u0131 i\u015fleminin tek bir mant\u0131ksal birim olarak ele al\u0131nmas\u0131 hayati \u00f6neme sahiptir. \u0130\u015fte bu noktada &#8220;i\u015flem y\u00f6netimi&#8221; (transaction management) devreye girer. \u0130\u015flem y\u00f6netimi, bir dizi operasyonun ya tamamen ba\u015far\u0131l\u0131 bir \u015fekilde tamamlanmas\u0131n\u0131 (commit) ya da herhangi bir hata durumunda t\u00fcm de\u011fi\u015fikliklerin geri al\u0131nmas\u0131n\u0131 (rollback) garanti eden mekanizmad\u0131r. Bu, \u00f6zellikle bankac\u0131l\u0131k, e-ticaret veya envanter y\u00f6netimi gibi kritik sistemlerde veri b\u00fct\u00fcnl\u00fc\u011f\u00fcn\u00fc koruman\u0131n temelidir.<\/p>\n<p>Spring Framework, Java ekosisteminde i\u015flem y\u00f6netimini basitle\u015ftiren ve standartla\u015ft\u0131ran g\u00fc\u00e7l\u00fc bir soyutlama katman\u0131 sunar. Geli\u015ftiricilerin do\u011frudan JDBC API&#8217;sinin karma\u015f\u0131k ve tekrarlayan i\u015flem y\u00f6netimi kodlar\u0131yla u\u011fra\u015fmak yerine, daha temiz ve deklaratif y\u00f6ntemlerle i\u015flem s\u0131n\u0131rlar\u0131n\u0131 belirlemesine olanak tan\u0131r. Bu makalede, Spring&#8217;in JDBC tabanl\u0131 uygulamalarda i\u015flem y\u00f6netimini nas\u0131l sa\u011flad\u0131\u011f\u0131n\u0131, temel kavramlar\u0131, programatik ve deklaratif yakla\u015f\u0131mlar\u0131 detayl\u0131 bir \u015fekilde inceleyecek ve pratik bir \u00f6rnek uygulama ile konuyu peki\u015ftirece\u011fiz. Amac\u0131m\u0131z, Spring ile sa\u011flam ve hataya dayan\u0131kl\u0131 veritaban\u0131 i\u015flemleri geli\u015ftirmek isteyen okuyuculara kapsaml\u0131 bir rehber sunmakt\u0131r.<\/p>\n<h2>Temel Kavramlar<\/h2>\n<p>Spring ile i\u015flem y\u00f6netimine dalmadan \u00f6nce, bir veritaban\u0131 i\u015fleminin temelini olu\u015fturan kavramlar\u0131 anlamak \u00f6nemlidir. Bu kavramlar, herhangi bir i\u015flem y\u00f6netim sisteminin temelini olu\u015fturur ve Spring&#8217;in sundu\u011fu soyutlamalar\u0131 daha iyi kavramam\u0131z\u0131 sa\u011flar.<\/p>\n<h3>\u0130\u015flem (Transaction)<\/h3>\n<p>\u0130\u015flem, bir veya daha fazla veritaban\u0131 operasyonunun mant\u0131ksal olarak tek bir birim olarak kabul edildi\u011fi bir dizidir. Bu operasyonlar, ya hepsi ba\u015far\u0131l\u0131 bir \u015fekilde tamamlan\u0131r ve kal\u0131c\u0131 hale gelir (commit) ya da herhangi bir ad\u0131mda bir hata meydana gelirse, daha \u00f6nce yap\u0131lan t\u00fcm de\u011fi\u015fiklikler geri al\u0131n\u0131r (rollback). Bir i\u015flemin temel amac\u0131, veritaban\u0131n\u0131n tutarl\u0131 bir durumda kalmas\u0131n\u0131 sa\u011flamakt\u0131r. \u00d6rne\u011fin, bir banka uygulamas\u0131nda bir hesaptan di\u011ferine para transferi, iki ayr\u0131 operasyon (bir hesaptan para \u00e7ekme, di\u011ferine para yat\u0131rma) i\u00e7erir. Bu iki operasyonun da ba\u015far\u0131l\u0131 olmas\u0131 veya ikisinin de ba\u015far\u0131s\u0131z olmas\u0131 gerekir; aksi takdirde veritaban\u0131 tutars\u0131z bir duruma d\u00fc\u015fer.<\/p>\n<h3>ACID \u00d6zellikleri<\/h3>\n<p>Veritaban\u0131 i\u015flemlerinin g\u00fcvenilirli\u011fini ve tutarl\u0131l\u0131\u011f\u0131n\u0131 sa\u011flamak i\u00e7in d\u00f6rt temel \u00f6zellik seti kullan\u0131l\u0131r. Bunlara ACID \u00f6zellikleri denir:<\/p>\n<p>*   <strong>Atomicity (B\u00fct\u00fcnl\u00fck):<\/strong> Bir i\u015flemdeki t\u00fcm operasyonlar ya tamamen ba\u015far\u0131l\u0131 olur ya da hi\u00e7biri olmaz. K\u0131smi bir ba\u015far\u0131 s\u00f6z konusu de\u011fildir. Yukar\u0131daki banka transferi \u00f6rne\u011finde, para \u00e7ekme ba\u015far\u0131l\u0131 olup para yat\u0131rma ba\u015far\u0131s\u0131z olursa, \u00e7ekilen para geri yat\u0131r\u0131lmal\u0131d\u0131r.<br \/>\n*   <strong>Consistency (Tutarl\u0131l\u0131k):<\/strong> Bir i\u015flem ba\u015flad\u0131\u011f\u0131nda ve bitti\u011finde veritaban\u0131 tutarl\u0131 bir durumda olmal\u0131d\u0131r. \u0130\u015flem, veritaban\u0131 k\u0131s\u0131tlamalar\u0131n\u0131 (constraints), tetikleyicileri (triggers) ve i\u015f kurallar\u0131n\u0131 ihlal etmemelidir.<br \/>\n*   <strong>Isolation (\u0130zolasyon):<\/strong> E\u015fzamanl\u0131 olarak y\u00fcr\u00fct\u00fclen i\u015flemler birbirini etkilememelidir. Her i\u015flem, sanki sistemde tek ba\u015f\u0131na \u00e7al\u0131\u015f\u0131yormu\u015f gibi g\u00f6r\u00fcnmelidir. Bu \u00f6zellik, farkl\u0131 izolasyon seviyeleri ile kontrol edilir ve karma\u015f\u0131k bir konudur.<br \/>\n*   <strong>Durability (Kal\u0131c\u0131l\u0131k):<\/strong> Ba\u015far\u0131l\u0131 bir \u015fekilde tamamlanan (commit edilen) bir i\u015flemin sonu\u00e7lar\u0131, sistem ar\u0131zalar\u0131 (g\u00fc\u00e7 kesintisi, sistem \u00e7\u00f6kmesi vb.) durumunda bile kal\u0131c\u0131 olmal\u0131d\u0131r. Veritaban\u0131, commit edilmi\u015f veriyi kal\u0131c\u0131 depolama birimlerine yazmay\u0131 garanti etmelidir.<\/p>\n<h3>\u0130\u015flem \u0130zolasyon Seviyeleri (Isolation Levels)<\/h3>\n<p>\u0130zolasyon, e\u015fzamanl\u0131 i\u015flemlerin birbirini ne \u00f6l\u00e7\u00fcde etkileyece\u011fini belirler. Daha y\u00fcksek izolasyon seviyeleri, veri tutarl\u0131l\u0131\u011f\u0131n\u0131 art\u0131r\u0131rken, e\u015fzamanl\u0131l\u0131k (concurrency) ve performans\u0131 d\u00fc\u015f\u00fcrebilir. ANSI SQL standard\u0131 d\u00f6rt ana izolasyon seviyesi tan\u0131mlar:<\/p>\n<p>*   <strong>READ UNCOMMITTED:<\/strong> En d\u00fc\u015f\u00fck izolasyon seviyesidir. Bir i\u015flem, ba\u015fka bir i\u015flem taraf\u0131ndan hen\u00fcz commit edilmemi\u015f verileri (dirty reads) okuyabilir. Bu, ciddi veri tutars\u0131zl\u0131klar\u0131na yol a\u00e7abilir ve genellikle tavsiye edilmez.<br \/>\n*   <strong>READ COMMITTED:<\/strong> Bir i\u015flem, yaln\u0131zca ba\u015fka bir i\u015flem taraf\u0131ndan commit edilmi\u015f verileri okuyabilir. Dirty reads&#8217;i \u00f6nler. Ancak, ayn\u0131 i\u015flem i\u00e7inde ayn\u0131 veriyi birden fazla okuma durumunda farkl\u0131 sonu\u00e7lar alabilir (non-repeatable reads), \u00e7\u00fcnk\u00fc ba\u015fka bir i\u015flem arada veriyi g\u00fcncelleyip commit edebilir.<br \/>\n*   <strong>REPEATABLE READ:<\/strong> Bir i\u015flem, kendi s\u00fcresi boyunca okudu\u011fu t\u00fcm verilerin de\u011ferlerinin de\u011fi\u015fmeden kalmas\u0131n\u0131 sa\u011flar. Non-repeatable reads&#8217;i \u00f6nler. Ancak, bir sorgunun ilk \u00e7al\u0131\u015ft\u0131r\u0131ld\u0131\u011f\u0131nda g\u00f6rmedi\u011fi ancak daha sonra ba\u015fka bir i\u015flem taraf\u0131ndan eklenen yeni sat\u0131rlar\u0131 (phantom reads) g\u00f6rebilir.<br \/>\n*   <strong>SERIALIZABLE:<\/strong> En y\u00fcksek izolasyon seviyesidir. T\u00fcm i\u015flemler, sanki birbiri ard\u0131na s\u0131rayla \u00e7al\u0131\u015f\u0131yormu\u015f gibi g\u00f6r\u00fcn\u00fcr. Dirty reads, non-repeatable reads ve phantom reads&#8217;i tamamen \u00f6nler. Ancak, e\u015fzamanl\u0131l\u0131k \u00fczerinde \u00f6nemli bir performans etkisi vard\u0131r ve genellikle sadece \u00e7ok kritik tutarl\u0131l\u0131k gerektiren durumlar i\u00e7in kullan\u0131l\u0131r.<\/p>\n<h3>\u0130\u015flem Yay\u0131l\u0131m\u0131 (Propagation Behaviors)<\/h3>\n<p>Spring&#8217;de, bir metodun i\u015flem kapsam\u0131nda nas\u0131l davranaca\u011f\u0131n\u0131 belirten &#8220;yay\u0131l\u0131m davran\u0131\u015f\u0131&#8221; (propagation behavior) kavram\u0131 vard\u0131r. Bu, i\u00e7 i\u00e7e ge\u00e7mi\u015f i\u015flem \u00e7a\u011fr\u0131lar\u0131n\u0131n nas\u0131l ele al\u0131naca\u011f\u0131n\u0131 kontrol eder.<\/p>\n<p>*   <strong>REQUIRED (Default):<\/strong> Mevcut bir i\u015flem varsa, bu i\u015flemi kullan\u0131r. Yoksa, yeni bir i\u015flem ba\u015flat\u0131r. \u00c7o\u011fu durum i\u00e7in uygun olan varsay\u0131lan davran\u0131\u015ft\u0131r.<br \/>\n*   <strong>SUPPORTS:<\/strong> Mevcut bir i\u015flem varsa, bu i\u015flemi kullan\u0131r. Yoksa, i\u015flemsiz (non-transactional) bir \u015fekilde \u00e7al\u0131\u015f\u0131r.<br \/>\n*   <strong>MANDATORY:<\/strong> Mevcut bir i\u015flem varsa, bu i\u015flemi kullan\u0131r. Yoksa, bir istisna f\u0131rlat\u0131r. \u0130\u015flemin kesinlikle var olmas\u0131 gereken durumlar i\u00e7in.<br \/>\n*   <strong>REQUIRES_NEW:<\/strong> Her zaman yeni bir i\u015flem ba\u015flat\u0131r. Mevcut bir i\u015flem varsa, onu ask\u0131ya al\u0131r ve yeni i\u015flemi ba\u015flat\u0131r. Yeni i\u015flem kendi ba\u015f\u0131na commit veya rollback yapar.<br \/>\n*   <strong>NOT_SUPPORTED:<\/strong> Mevcut bir i\u015flem varsa, onu ask\u0131ya al\u0131r ve i\u015flemsiz bir \u015fekilde \u00e7al\u0131\u015f\u0131r.<br \/>\n*   <strong>NEVER:<\/strong> Mevcut bir i\u015flem varsa, bir istisna f\u0131rlat\u0131r. \u0130\u015flemin kesinlikle olmamas\u0131 gereken durumlar i\u00e7in.<br \/>\n*   <strong>NESTED:<\/strong> Mevcut bir i\u015flem varsa, i\u00e7 i\u00e7e ge\u00e7mi\u015f bir i\u015flem (savepoint) ba\u015flat\u0131r. Bu i\u00e7 i\u015flem kendi ba\u015f\u0131na geri al\u0131nabilir (rollback) ancak ana i\u015flemden ba\u011f\u0131ms\u0131z commit edilemez. Ana i\u015flem rollback yaparsa, i\u00e7 i\u015flem de rollback olur. JDBC savepoint&#8217;leri gerektirir.<\/p>\n<h3>Rollback Kurallar\u0131 (Rollback Rules)<\/h3>\n<p>Spring, bir i\u015flem s\u0131ras\u0131nda hangi istisnalar\u0131n (exceptions) i\u015flemin geri al\u0131nmas\u0131na (rollback) yol a\u00e7aca\u011f\u0131n\u0131 ve hangilerinin i\u015flemin devam etmesine (commit) izin verece\u011fini belirleme esnekli\u011fi sunar. Varsay\u0131lan olarak, Spring, \u00e7al\u0131\u015fma zaman\u0131 istisnalar\u0131 (runtime exceptions &#8211; <code>RuntimeException<\/code> ve alt s\u0131n\u0131flar\u0131) ve hatalar (<code>Error<\/code> ve alt s\u0131n\u0131flar\u0131) i\u00e7in rollback yapar. Kontroll\u00fc istisnalar (checked exceptions) i\u00e7in ise varsay\u0131lan olarak rollback yapmaz. Bu davran\u0131\u015f, <code>@Transactional<\/code> anotasyonunun <code>rollbackFor<\/code> ve <code>noRollbackFor<\/code> parametreleri ile \u00f6zelle\u015ftirilebilir. \u00d6rne\u011fin, belirli bir kontroll\u00fc istisna durumunda rollback yapmak veya belirli bir \u00e7al\u0131\u015fma zaman\u0131 istisnas\u0131 durumunda rollback yapmamak m\u00fcmk\u00fcnd\u00fcr.<\/p>\n<h2>Spring \u0130\u015flem Y\u00f6netimine Giri\u015f<\/h2>\n<p>Spring Framework, i\u015flem y\u00f6netimini Java uygulamalar\u0131nda kolayla\u015ft\u0131rmak i\u00e7in g\u00fc\u00e7l\u00fc bir soyutlama katman\u0131 sa\u011flar. Bu soyutlama, temel JDBC, Hibernate, JPA veya JMS gibi farkl\u0131 i\u015flem teknolojileri \u00fczerinde \u00e7al\u0131\u015fabilir. Spring&#8217;in i\u015flem y\u00f6netimini kullanman\u0131n temel avantajlar\u0131 \u015funlard\u0131r:<\/p>\n<p>*   <strong>Basitle\u015ftirme:<\/strong> Geli\u015ftiricilerin do\u011frudan veritaban\u0131 ba\u011flant\u0131s\u0131, commit, rollback gibi d\u00fc\u015f\u00fck seviyeli API \u00e7a\u011fr\u0131lar\u0131yla u\u011fra\u015fmas\u0131n\u0131 engeller. Bu &#8220;boilerplate&#8221; kodunu ortadan kald\u0131r\u0131r.<br \/>\n*   <strong>Tutarl\u0131l\u0131k:<\/strong> Farkl\u0131 i\u015flem teknolojileri i\u00e7in tutarl\u0131 bir programlama modeli sunar.<br \/>\n*   <strong>Deklaratif Yakla\u015f\u0131m:<\/strong> \u0130\u015flem s\u0131n\u0131rlar\u0131n\u0131 kod i\u00e7inde belirlemek yerine, metotlar veya s\u0131n\u0131flar \u00fczerinde anotasyonlar veya XML konfig\u00fcrasyonu arac\u0131l\u0131\u011f\u0131yla tan\u0131mlamaya olanak tan\u0131r. Bu, i\u015f mant\u0131\u011f\u0131n\u0131 i\u015flem y\u00f6netiminden ay\u0131r\u0131r.<br \/>\n*   <strong>AOP Entegrasyonu:<\/strong> Spring&#8217;in AOP (Aspect-Oriented Programming) yeteneklerini kullanarak i\u015flem y\u00f6netimi gibi \u00e7apraz kesen endi\u015feleri (cross-cutting concerns) kolayca uygulayabilir.<\/p>\n<p>Spring&#8217;de iki ana i\u015flem y\u00f6netimi yakla\u015f\u0131m\u0131 vard\u0131r: programatik ve deklaratif.<\/p>\n<h2>Programatik \u0130\u015flem Y\u00f6netimi<\/h2>\n<p>Programatik i\u015flem y\u00f6netimi, i\u015flem s\u0131n\u0131rlar\u0131n\u0131 kod i\u00e7inde a\u00e7\u0131k\u00e7a tan\u0131mlad\u0131\u011f\u0131n\u0131z yakla\u015f\u0131md\u0131r. Bu, daha fazla kontrol sa\u011flar ancak daha fazla kod yazmay\u0131 gerektirir ve i\u015f mant\u0131\u011f\u0131 ile i\u015flem y\u00f6netiminin birbirine kar\u0131\u015fmas\u0131na neden olabilir. Spring, programatik i\u015flem y\u00f6netimi i\u00e7in iki temel soyutlama sunar:<\/p>\n<p>*   <strong><code>PlatformTransactionManager<\/code> aray\u00fcz\u00fc:<\/strong> Bu aray\u00fcz, Spring&#8217;in t\u00fcm i\u015flem stratejileri i\u00e7in merkezi bir bile\u015fendir. <code>getTransaction()<\/code>, <code>commit()<\/code>, <code>rollback()<\/code> gibi metotlar\u0131 tan\u0131mlar. JDBC i\u00e7in <code>DataSourceTransactionManager<\/code>, JPA i\u00e7in <code>JpaTransactionManager<\/code> gibi farkl\u0131 implementasyonlar\u0131 vard\u0131r.<br \/>\n*   <strong><code>TransactionDefinition<\/code> aray\u00fcz\u00fc:<\/strong> Bir i\u015flemin \u00f6zelliklerini (yay\u0131l\u0131m, izolasyon, salt okunur olup olmad\u0131\u011f\u0131, zaman a\u015f\u0131m\u0131) tan\u0131mlar.<br \/>\n*   <strong><code>TransactionStatus<\/code> aray\u00fcz\u00fc:<\/strong> Devam eden bir i\u015flemin durumunu temsil eder ve <code>setRollbackOnly()<\/code> gibi metotlar i\u00e7erir.<\/p>\n<p>Programatik i\u015flem y\u00f6netiminin en yayg\u0131n ve temiz yolu, <code>TransactionTemplate<\/code> s\u0131n\u0131f\u0131n\u0131 kullanmakt\u0131r. <code>TransactionTemplate<\/code>, <code>PlatformTransactionManager<\/code>&#8216;\u0131 sarmalar ve <code>execute()<\/code> metodu arac\u0131l\u0131\u011f\u0131yla bir geri \u00e7a\u011f\u0131rma (callback) mekanizmas\u0131 sunar. Bu, i\u015flem y\u00f6netiminin temel ad\u0131mlar\u0131n\u0131 (i\u015flem ba\u015flatma, commit\/rollback, kaynak temizleme) sizin yerinize otomatik olarak halleder.<\/p>\n<pre><code class=\"language-java\">\/\/ \u00d6rnek: TransactionTemplate ile programatik i\u015flem y\u00f6netimi\npublic class AccountServiceProgrammatic {\n\n    private final TransactionTemplate transactionTemplate;\n    private final JdbcTemplate jdbcTemplate;\n\n    public AccountServiceProgrammatic(PlatformTransactionManager transactionManager, JdbcTemplate jdbcTemplate) {\n        this.transactionTemplate = new TransactionTemplate(transactionManager);\n        this.jdbcTemplate = jdbcTemplate;\n    }\n\n    public void transferMoney(long fromAccountId, long toAccountId, double amount) {\n        transactionTemplate.execute(status -> {\n            try {\n                \/\/ Hesaptan para \u00e7ekme\n                jdbcTemplate.update(\"UPDATE accounts SET balance = balance - ? WHERE id = ?\", amount, fromAccountId);\n                System.out.println(\"Hesap \" + fromAccountId + \" den \" + amount + \" \u00e7ekildi.\");\n\n                \/\/ Hata sim\u00fclasyonu i\u00e7in\n                \/\/ if (true) throw new RuntimeException(\"Sim\u00fcle edilmi\u015f hata!\");\n\n                \/\/ Hesaba para yat\u0131rma\n                jdbcTemplate.update(\"UPDATE accounts SET balance = balance + ? WHERE id = ?\", amount, toAccountId);\n                System.out.println(\"Hesap \" + toAccountId + \" ye \" + amount + \" yat\u0131r\u0131ld\u0131.\");\n\n                return null; \/\/ Ba\u015far\u0131l\u0131ysa null d\u00f6ner\n            } catch (Exception e) {\n                status.setRollbackOnly(); \/\/ \u0130\u015flemi geri al\n                throw new RuntimeException(\"Para transferi ba\u015far\u0131s\u0131z oldu: \" + e.getMessage(), e);\n            }\n        });\n    }\n}<\/code><\/pre>\n<p>Yukar\u0131daki \u00f6rnekte, <code>transferMoney<\/code> metodu <code>transactionTemplate.execute()<\/code> i\u00e7ine al\u0131nm\u0131\u015ft\u0131r. Bu, i\u00e7indeki t\u00fcm JDBC operasyonlar\u0131n\u0131n tek bir i\u015flem kapsam\u0131nda y\u00fcr\u00fct\u00fclmesini sa\u011flar. Herhangi bir <code>Exception<\/code> f\u0131rlat\u0131ld\u0131\u011f\u0131nda, <code>status.setRollbackOnly()<\/code> \u00e7a\u011fr\u0131l\u0131r ve i\u015flem geri al\u0131n\u0131r. Bu yakla\u015f\u0131m, i\u015flem kontrol\u00fcn\u00fc do\u011frudan kodda tutar, ancak daha az tercih edilir \u00e7\u00fcnk\u00fc deklaratif yakla\u015f\u0131m genellikle daha temiz ve s\u00fcrd\u00fcr\u00fclebilirdir.<\/p>\n<h2>Deklaratif \u0130\u015flem Y\u00f6netimi<\/h2>\n<p>Deklaratif i\u015flem y\u00f6netimi, Spring&#8217;in en g\u00fc\u00e7l\u00fc \u00f6zelliklerinden biridir ve genellikle tercih edilen y\u00f6ntemdir. Bu yakla\u015f\u0131m, i\u015f mant\u0131\u011f\u0131n\u0131 i\u015flem y\u00f6netiminden tamamen ay\u0131r\u0131r. \u0130\u015flem s\u0131n\u0131rlar\u0131, metotlar veya s\u0131n\u0131flar \u00fczerinde <code>@Transactional<\/code> anotasyonu kullan\u0131larak veya XML konfig\u00fcrasyonu arac\u0131l\u0131\u011f\u0131yla tan\u0131mlan\u0131r. Spring, bu tan\u0131mlamalar\u0131 kullanarak \u00e7al\u0131\u015fma zaman\u0131nda gerekli i\u015flem y\u00f6netimini otomatik olarak uygular.<\/p>\n<h3>Nas\u0131l \u00c7al\u0131\u015f\u0131r?<\/h3>\n<p>Spring, deklaratif i\u015flem y\u00f6netimini AOP (Aspect-Oriented Programming &#8211; Y\u00f6nelim Odakl\u0131 Programlama) prensipleri arac\u0131l\u0131\u011f\u0131yla ger\u00e7ekle\u015ftirir. Bir <code>@Transactional<\/code> anotasyonuna sahip bir metot \u00e7a\u011fr\u0131ld\u0131\u011f\u0131nda, Spring bir proxy nesnesi olu\u015fturur. Bu proxy, ger\u00e7ek metot \u00e7a\u011fr\u0131lmadan \u00f6nce ve sonra i\u015flem y\u00f6netimi mant\u0131\u011f\u0131n\u0131 (i\u015flem ba\u015flatma, commit etme, geri alma) ekler. Bu sayede, geli\u015ftiricinin i\u015f mant\u0131\u011f\u0131 koduna i\u015flemle ilgili herhangi bir kod yazmas\u0131 gerekmez.<\/p>\n<h3><code>@Transactional<\/code> Anotasyonunun Parametreleri<\/h3>\n<p><code>@Transactional<\/code> anotasyonu, bir i\u015flemin davran\u0131\u015f\u0131n\u0131 \u00f6zelle\u015ftirmek i\u00e7in \u00e7e\u015fitli parametreler sunar:<\/p>\n<p>*   <strong><code>propagation<\/code>:<\/strong> \u0130\u015flem yay\u0131l\u0131m davran\u0131\u015f\u0131n\u0131 belirler (\u00f6rn: <code>Propagation.REQUIRED<\/code>, <code>Propagation.REQUIRES_NEW<\/code>). Varsay\u0131lan <code>REQUIRED<\/code>&#8216;dir.<br \/>\n*   <strong><code>isolation<\/code>:<\/strong> \u0130\u015flem izolasyon seviyesini belirler (\u00f6rn: <code>Isolation.READ_COMMITTED<\/code>, <code>Isolation.SERIALIZABLE<\/code>). Varsay\u0131lan, veritaban\u0131n\u0131n varsay\u0131lan izolasyon seviyesidir.<br \/>\n*   <strong><code>readOnly<\/code>:<\/strong> \u0130\u015flemin salt okunur olup olmad\u0131\u011f\u0131n\u0131 belirtir (<code>true<\/code> veya <code>false<\/code>). <code>true<\/code> olarak ayarland\u0131\u011f\u0131nda, veritaban\u0131 performans optimizasyonlar\u0131 yapabilir ve yazma operasyonlar\u0131na izin vermez.<br \/>\n*   <strong><code>timeout<\/code>:<\/strong> \u0130\u015flemin saniye cinsinden zaman a\u015f\u0131m\u0131 s\u00fcresini belirler. Varsay\u0131lan olarak -1 (zaman a\u015f\u0131m\u0131 yok) de\u011ferindedir.<br \/>\n*   <strong><code>rollbackFor<\/code>:<\/strong> Belirtilen istisna tipleri f\u0131rlat\u0131ld\u0131\u011f\u0131nda i\u015flemin geri al\u0131nmas\u0131n\u0131 sa\u011flar. Bir <code>Class[]<\/code> dizisi al\u0131r.<br \/>\n*   <strong><code>noRollbackFor<\/code>:<\/strong> Belirtilen istisna tipleri f\u0131rlat\u0131ld\u0131\u011f\u0131nda i\u015flemin geri al\u0131nmamas\u0131n\u0131 sa\u011flar. Bir <code>Class[]<\/code> dizisi al\u0131r.<br \/>\n*   <strong><code>value<\/code> veya <code>transactionManager<\/code>:<\/strong> Birden fazla <code>PlatformTransactionManager<\/code> bean&#8217;i tan\u0131mland\u0131\u011f\u0131nda, hangi i\u015flem y\u00f6neticisinin kullan\u0131laca\u011f\u0131n\u0131 belirtmek i\u00e7in kullan\u0131l\u0131r.<\/p>\n<pre><code class=\"language-java\">\/\/ \u00d6rnek: @Transactional ile deklaratif i\u015flem y\u00f6netimi\n@Service\npublic class AccountServiceDeclarative {\n\n    private final JdbcTemplate jdbcTemplate;\n\n    public AccountServiceDeclarative(JdbcTemplate jdbcTemplate) {\n        this.jdbcTemplate = jdbcTemplate;\n    }\n\n    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED, rollbackFor = {RuntimeException.class, CustomBusinessException.class})\n    public void transferMoney(long fromAccountId, long toAccountId, double amount) throws CustomBusinessException {\n        \/\/ Hesaptan para \u00e7ekme\n        int updatedRows = jdbcTemplate.update(\"UPDATE accounts SET balance = balance - ? WHERE id = ?\", amount, fromAccountId);\n        if (updatedRows == 0) {\n            throw new CustomBusinessException(\"Kaynak hesap bulunamad\u0131 veya bakiye yetersiz.\");\n        }\n        System.out.println(\"Hesap \" + fromAccountId + \" den \" + amount + \" \u00e7ekildi.\");\n\n        \/\/ Hata sim\u00fclasyonu i\u00e7in\n        \/\/ if (true) throw new RuntimeException(\"Sim\u00fcle edilmi\u015f hata!\");\n\n        \/\/ Hesaba para yat\u0131rma\n        updatedRows = jdbcTemplate.update(\"UPDATE accounts SET balance = balance + ? WHERE id = ?\", amount, toAccountId);\n        if (updatedRows == 0) {\n            throw new CustomBusinessException(\"Hedef hesap bulunamad\u0131.\");\n        }\n        System.out.println(\"Hesap \" + toAccountId + \" ye \" + amount + \" yat\u0131r\u0131ld\u0131.\");\n    }\n}<\/code><\/pre>\n<p>Bu \u00f6rnekte, <code>transferMoney<\/code> metodu <code>@Transactional<\/code> anotasyonu ile i\u015faretlenmi\u015ftir. Bu sayede, metot \u00e7a\u011fr\u0131ld\u0131\u011f\u0131nda Spring otomatik olarak bir i\u015flem ba\u015flat\u0131r, metot ba\u015far\u0131yla tamamland\u0131\u011f\u0131nda commit eder ve herhangi bir <code>RuntimeException<\/code> veya <code>CustomBusinessException<\/code> f\u0131rlat\u0131ld\u0131\u011f\u0131nda rollback yapar.<\/p>\n<h2>Spring JDBC ile \u0130\u015flem Y\u00f6netimi Uygulama \u00d6rne\u011fi<\/h2>\n<p>\u015eimdi, Spring JDBC kullanarak deklaratif i\u015flem y\u00f6netimini pratik bir \u00f6rnek \u00fczerinde g\u00f6sterelim. Bir banka uygulamas\u0131nda hesaplar aras\u0131 para transferi senaryosunu ele alaca\u011f\u0131z.<\/p>\n<h3>Proje Yap\u0131s\u0131 ve Ba\u011f\u0131ml\u0131l\u0131klar<\/h3>\n<p>Maven tabanl\u0131 bir proje i\u00e7in <code>pom.xml<\/code> dosyan\u0131za a\u015fa\u011f\u0131daki ba\u011f\u0131ml\u0131l\u0131klar\u0131 eklemeniz gerekir:<\/p>\n<pre><code class=\"language-xml\"><?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http:\/\/maven.apache.org\/POM\/4.0.0\"\n         xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"\n         xsi:schemaLocation=\"http:\/\/maven.apache.org\/POM\/4.0.0 http:\/\/maven.apache.org\/xsd\/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0<\/modelVersion>\n\n    <groupId>com.example<\/groupId>\n    <artifactId>spring-jdbc-transaction-example<\/artifactId>\n    <version>1.0-SNAPSHOT<\/version>\n\n    <properties>\n        <maven.compiler.source>17<\/maven.compiler.source>\n        <maven.compiler.target>17<\/maven.compiler.target>\n        <spring.version>6.1.5<\/spring.version> <!-- G\u00fcncel Spring s\u00fcr\u00fcm\u00fcn\u00fc kullan\u0131n -->\n    <\/properties>\n\n    <dependencies>\n        <!-- Spring Core ve Context -->\n        <dependency>\n            <groupId>org.springframework<\/groupId>\n            <artifactId>spring-context<\/artifactId>\n            <version>${spring.version}<\/version>\n        <\/dependency>\n        <!-- Spring JDBC -->\n        <dependency>\n            <groupId>org.springframework<\/groupId>\n            <artifactId>spring-jdbc<\/artifactId>\n            <version>${spring.version}<\/version>\n        <\/dependency>\n        <!-- H2 Database (In-memory database for example) -->\n        <dependency>\n            <groupId>com.h2database<\/groupId>\n            <artifactId>h2<\/artifactId>\n            <version>2.2.224<\/version>\n        <\/dependency>\n        <!-- Connection Pool (HikariCP recommended) -->\n        <dependency>\n            <groupId>com.zaxxer<\/groupId>\n            <artifactId>HikariCP<\/artifactId>\n            <version>5.1.0<\/version>\n        <\/dependency>\n        <!-- JUnit for testing (optional) -->\n        <dependency>\n            <groupId>org.junit.jupiter<\/groupId>\n            <artifactId>junit-jupiter-api<\/artifactId>\n            <version>5.10.0<\/version>\n            <scope>test<\/scope>\n        <\/dependency>\n        <dependency>\n            <groupId>org.junit.jupiter<\/groupId>\n            <artifactId>junit-jupiter-engine<\/artifactId>\n            <version>5.10.0<\/version>\n            <scope>test<\/scope>\n        <\/dependency>\n    <\/dependencies>\n\n<\/project><\/code><\/pre>\n<h3>Veritaban\u0131 Yap\u0131land\u0131rmas\u0131<\/h3>\n<p>Spring konfig\u00fcrasyon s\u0131n\u0131f\u0131m\u0131zda <code>DataSource<\/code>, <code>JdbcTemplate<\/code> ve <code>PlatformTransactionManager<\/code> bean&#8217;lerini tan\u0131mlayaca\u011f\u0131z. <code>@EnableTransactionManagement<\/code> anotasyonu, Spring&#8217;in <code>@Transactional<\/code> anotasyonunu taramas\u0131n\u0131 ve i\u015flem proxy&#8217;lerini olu\u015fturmas\u0131n\u0131 sa\u011flar.<\/p>\n<pre><code class=\"language-java\">import com.zaxxer.hikari.HikariConfig;\nimport com.zaxxer.hikari.HikariDataSource;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.ComponentScan;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.jdbc.core.JdbcTemplate;\nimport org.springframework.jdbc.datasource.DataSourceTransactionManager;\nimport org.springframework.transaction.PlatformTransactionManager;\nimport org.springframework.transaction.annotation.EnableTransactionManagement;\n\nimport javax.sql.DataSource;\n\n@Configuration\n@ComponentScan(basePackages = \"com.example.springjdbctransaction\") \/\/ Servis ve DAO s\u0131n\u0131flar\u0131m\u0131z\u0131 tarar\n@EnableTransactionManagement \/\/ @Transactional anotasyonunu etkinle\u015ftirir\npublic class AppConfig {\n\n    @Bean\n    public DataSource dataSource() {\n        \/\/ H2 in-memory veritaban\u0131 i\u00e7in HikariCP konfig\u00fcrasyonu\n        HikariConfig config = new HikariConfig();\n        config.setJdbcUrl(\"jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;INIT=RUNSCRIPT FROM 'classpath:schema.sql'\");\n        config.setUsername(\"sa\");\n        config.setPassword(\"\");\n        return new HikariDataSource(config);\n    }\n\n    @Bean\n    public JdbcTemplate jdbcTemplate(DataSource dataSource) {\n        return new JdbcTemplate(dataSource);\n    }\n\n    @Bean\n    public PlatformTransactionManager transactionManager(DataSource dataSource) {\n        return new DataSourceTransactionManager(dataSource);\n    }\n}<\/code><\/pre>\n<p><code>schema.sql<\/code> dosyas\u0131 <code>src\/main\/resources<\/code> alt\u0131nda bulunmal\u0131d\u0131r ve veritaban\u0131 \u015femas\u0131n\u0131 olu\u015fturur:<\/p>\n<pre><code class=\"language-sql\">CREATE TABLE accounts (\n    id INT PRIMARY KEY AUTO_INCREMENT,\n    account_holder VARCHAR(255) NOT NULL,\n    balance DECIMAL(10, 2) NOT NULL\n);\n\nINSERT INTO accounts (account_holder, balance) VALUES ('Alice', 1000.00);\nINSERT INTO accounts (account_holder, balance) VALUES ('Bob', 500.00);<\/code><\/pre>\n<h3>DAO Katman\u0131<\/h3>\n<p>DAO (Data Access Object) katman\u0131, veritaban\u0131 i\u015flemlerini soyutlar. <code>AccountDao<\/code> aray\u00fcz\u00fc ve <code>AccountDaoImpl<\/code> implementasyonu, hesap verilerine eri\u015fim sa\u011flar.<\/p>\n<pre><code class=\"language-java\">\/\/ com.example.springjdbctransaction.dao.Account.java\npackage com.example.springjdbctransaction.dao;\n\npublic class Account {\n    private long id;\n    private String accountHolder;\n    private double balance;\n\n    \/\/ Constructors, getters, setters, toString\n    public Account() {}\n\n    public Account(long id, String accountHolder, double balance) {\n        this.id = id;\n        this.accountHolder = accountHolder;\n        this.balance = balance;\n    }\n\n    public long getId() { return id; }\n    public void setId(long id) { this.id = id; }\n    public String getAccountHolder() { return accountHolder; }\n    public void setAccountHolder(String accountHolder) { this.accountHolder = accountHolder; }\n    public double getBalance() { return balance; }\n    public void setBalance(double balance) { this.balance = balance; }\n\n    @Override\n    public String toString() {\n        return \"Account{\" +\n               \"id=\" + id +\n               \", accountHolder='\" + accountHolder + '\\'' +\n               \", balance=\" + balance +\n               '}';\n    }\n}<\/code><\/pre>\n<pre><code class=\"language-java\">\/\/ com.example.springjdbctransaction.dao.AccountDao.java\npackage com.example.springjdbctransaction.dao;\n\nimport java.util.Optional;\n\npublic interface AccountDao {\n    Optional<Account> findById(long id);\n    void updateBalance(long id, double amount);\n}<\/code><\/pre>\n<pre><code class=\"language-java\">\/\/ com.example.springjdbctransaction.dao.AccountDaoImpl.java\npackage com.example.springjdbctransaction.dao;\n\nimport org.springframework.jdbc.core.JdbcTemplate;\nimport org.springframework.stereotype.Repository;\n\nimport java.util.Optional;\n\n@Repository\npublic class AccountDaoImpl implements AccountDao {\n\n    private final JdbcTemplate jdbcTemplate;\n\n    public AccountDaoImpl(JdbcTemplate jdbcTemplate) {\n        this.jdbcTemplate = jdbcTemplate;\n    }\n\n    @Override\n    public Optional<Account> findById(long id) {\n        String sql = \"SELECT id, account_holder, balance FROM accounts WHERE id = ?\";\n        try {\n            return Optional.ofNullable(jdbcTemplate.queryForObject(sql,\n                    (rs, rowNum) -> new Account(rs.getLong(\"id\"), rs.getString(\"account_holder\"), rs.getDouble(\"balance\")),\n                    id));\n        } catch (org.springframework.dao.EmptyResultDataAccessException e) {\n            return Optional.empty();\n        }\n    }\n\n    @Override\n    public void updateBalance(long id, double amount) {\n        String sql = \"UPDATE accounts SET balance = ? WHERE id = ?\";\n        jdbcTemplate.update(sql, amount, id);\n    }\n}<\/code><\/pre>\n<h3>Servis Katman\u0131<\/h3>\n<p>Servis katman\u0131, i\u015f mant\u0131\u011f\u0131n\u0131 i\u00e7erir ve <code>@Transactional<\/code> anotasyonunu kullanarak i\u015flem y\u00f6netimini sa\u011flar. <code>transferMoney<\/code> metodu, iki <code>AccountDao<\/code> operasyonunu tek bir i\u015flem alt\u0131nda birle\u015ftirir.<\/p>\n<pre><code class=\"language-java\">\/\/ com.example.springjdbctransaction.service.CustomBusinessException.java\npackage com.example.springjdbctransaction.service;\n\npublic class CustomBusinessException extends Exception {\n    public CustomBusinessException(String message) {\n        super(message);\n    }\n}<\/code><\/pre>\n<pre><code class=\"language-java\">\/\/ com.example.springjdbctransaction.service.AccountService.java\npackage com.example.springjdbctransaction.service;\n\nimport com.example.springjdbctransaction.dao.Account;\nimport com.example.springjdbctransaction.dao.AccountDao;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Isolation;\nimport org.springframework.transaction.annotation.Propagation;\nimport org.springframework.transaction.annotation.Transactional;\n\n@Service\npublic class AccountService {\n\n    private final AccountDao accountDao;\n\n    public AccountService(AccountDao accountDao) {\n        this.accountDao = accountDao;\n    }\n\n    @Transactional(propagation = Propagation.REQUIRED,\n                   isolation = Isolation.READ_COMMITTED,\n                   rollbackFor = CustomBusinessException.class) \/\/ CustomBusinessException durumunda da rollback yap\n    public void transferMoney(long fromAccountId, long toAccountId, double amount) throws CustomBusinessException {\n        System.out.println(\"--------------------------------------------------\");\n        System.out.println(\"Para transferi ba\u015flat\u0131l\u0131yor: \" + fromAccountId + \" -> \" + toAccountId + \", Miktar: \" + amount);\n\n        Account fromAccount = accountDao.findById(fromAccountId)\n                .orElseThrow(() -> new CustomBusinessException(\"Kaynak hesap bulunamad\u0131: \" + fromAccountId));\n        Account toAccount = accountDao.findById(toAccountId)\n                .orElseThrow(() -> new CustomBusinessException(\"Hedef hesap bulunamad\u0131: \" + toAccountId));\n\n        if (fromAccount.getBalance() < amount) {\n            throw new CustomBusinessException(\"Kaynak hesapta yetersiz bakiye: \" + fromAccount.getBalance());\n        }\n\n        \/\/ Kaynak hesaptan para \u00e7ek\n        accountDao.updateBalance(fromAccountId, fromAccount.getBalance() - amount);\n        System.out.println(\"Hesap \" + fromAccountId + \" den \" + amount + \" \u00e7ekildi. Yeni bakiye: \" + (fromAccount.getBalance() - amount));\n\n        \/\/ Hata sim\u00fclasyonu: Bu sat\u0131r\u0131n yorumunu kald\u0131r\u0131rsan\u0131z, i\u015flem rollback olur.\n        \/\/ if (true) throw new RuntimeException(\"Sim\u00fcle edilmi\u015f \u00e7al\u0131\u015fma zaman\u0131 hatas\u0131!\");\n        \/\/ if (true) throw new CustomBusinessException(\"Sim\u00fcle edilmi\u015f i\u015f mant\u0131\u011f\u0131 hatas\u0131!\");\n\n        \/\/ Hedef hesaba para yat\u0131r\n        accountDao.updateBalance(toAccountId, toAccount.getBalance() + amount);\n        System.out.println(\"Hesap \" + toAccountId + \" ye \" + amount + \" yat\u0131r\u0131ld\u0131. Yeni bakiye: \" + (toAccount.getBalance() + amount));\n\n        System.out.println(\"Para transferi ba\u015far\u0131l\u0131.\");\n        System.out.println(\"--------------------------------------------------\");\n    }\n\n    @Transactional(readOnly = true)\n    public Account getAccount(long id) {\n        return accountDao.findById(id).orElse(null);\n    }\n}<\/code><\/pre>\n<h3>Ana Uygulama (Main Application)<\/h3>\n<p>Ana uygulamam\u0131zda Spring context'i ba\u015flatacak ve <code>AccountService<\/code>'i kullanarak para transferi senaryolar\u0131n\u0131 test edece\u011fiz.<\/p>\n<pre><code class=\"language-java\">\/\/ com.example.springjdbctransaction.MainApplication.java\npackage com.example.springjdbctransaction;\n\nimport com.example.springjdbctransaction.dao.Account;\nimport com.example.springjdbctransaction.service.AccountService;\nimport com.example.springjdbctransaction.service.CustomBusinessException;\nimport org.springframework.context.annotation.AnnotationConfigApplicationContext;\n\npublic class MainApplication {\n\n    public static void main(String[] args) {\n        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);\n        AccountService accountService = context.getBean(AccountService.class);\n\n        \/\/ Ba\u015flang\u0131\u00e7 bakiyelerini g\u00f6ster\n        printAccountBalances(accountService);\n\n        \/\/ Senaryo 1: Ba\u015far\u0131l\u0131 para transferi\n        System.out.println(\"\\n--- Senaryo 1: Ba\u015far\u0131l\u0131 Transfer (100 -> 200) ---\");\n        try {\n            accountService.transferMoney(1, 2, 100.00);\n        } catch (CustomBusinessException e) {\n            System.err.println(\"Transfer ba\u015far\u0131s\u0131z oldu: \" + e.getMessage());\n        }\n        printAccountBalances(accountService);\n\n        \/\/ Senaryo 2: Hatal\u0131 para transferi (yetersiz bakiye)\n        System.out.println(\"\\n--- Senaryo 2: Yetersiz Bakiye (1 -> 2, 1500) ---\");\n        try {\n            accountService.transferMoney(1, 2, 1500.00);\n        } catch (CustomBusinessException e) {\n            System.err.println(\"Transfer ba\u015far\u0131s\u0131z oldu: \" + e.getMessage());\n        }\n        printAccountBalances(accountService);\n\n        \/\/ Senaryo 3: Hatal\u0131 para transferi (sim\u00fcle edilmi\u015f RuntimeException)\n        \/\/ AccountService'deki \"if (true) throw new RuntimeException(...)\" sat\u0131r\u0131n\u0131 a\u00e7\u0131n.\n        \/\/ Bu durumda, ilk hesapta yap\u0131lan de\u011fi\u015fiklik de geri al\u0131nacakt\u0131r.\n        System.out.println(\"\\n--- Senaryo 3: Runtime Hatas\u0131 Sim\u00fclasyonu (1 -> 2, 50) ---\");\n        \/\/ accountService.transferMoney metodu i\u00e7indeki hata sim\u00fclasyonunu etkinle\u015ftirin\n        try {\n            accountService.transferMoney(1, 2, 50.00);\n        } catch (CustomBusinessException e) {\n            System.err.println(\"Transfer ba\u015far\u0131s\u0131z oldu: \" + e.getMessage());\n        } catch (RuntimeException e) {\n            System.err.println(\"Transfer Runtime hatas\u0131 nedeniyle ba\u015far\u0131s\u0131z oldu: \" + e.getMessage());\n        }\n        printAccountBalances(accountService);\n\n\n        context.close();\n    }\n\n    private static void printAccountBalances(AccountService accountService) {\n        System.out.println(\"\\n--- Mevcut Hesap Bakiyeleri ---\");\n        Account account1 = accountService.getAccount(1);\n        Account account2 = accountService.getAccount(2);\n        System.out.println(\"Hesap 1: \" + (account1 != null ? account1.getBalance() : \"Bulunamad\u0131\"));\n        System.out.println(\"Hesap 2: \" + (account2 != null ? account2.getBalance() : \"Bulunamad\u0131\"));\n        System.out.println(\"-------------------------------\\n\");\n    }\n}<\/code><\/pre>\n<p><strong>\u00c7\u0131kt\u0131 Analizi:<\/strong><br \/>\n*   <strong>Senaryo 1:<\/strong> Alice'den Bob'a 100.00 birim para ba\u015far\u0131l\u0131 bir \u015fekilde transfer edilir. Her iki hesab\u0131n bakiyesi de do\u011fru \u015fekilde g\u00fcncellenir.<br \/>\n*   <strong>Senaryo 2:<\/strong> Alice'in hesab\u0131nda yetersiz bakiye oldu\u011fu i\u00e7in <code>CustomBusinessException<\/code> f\u0131rlat\u0131l\u0131r. <code>@Transactional<\/code> anotasyonu sayesinde, <code>transferMoney<\/code> metodu i\u00e7indeki hi\u00e7bir de\u011fi\u015fiklik (e\u011fer yap\u0131lm\u0131\u015f olsayd\u0131) veritaban\u0131na yans\u0131maz; t\u00fcm i\u015flem geri al\u0131n\u0131r ve bakiyeler de\u011fi\u015fmez kal\u0131r.<br \/>\n*   <strong>Senaryo 3:<\/strong> <code>AccountService<\/code> i\u00e7indeki sim\u00fcle edilmi\u015f <code>RuntimeException<\/code> etkinle\u015ftirildi\u011finde, para \u00e7ekme i\u015flemi ba\u015far\u0131l\u0131 olsa bile, sonraki hata nedeniyle t\u00fcm i\u015flem geri al\u0131n\u0131r. Alice'in bakiyesi ba\u015flang\u0131\u00e7taki haline d\u00f6ner.<\/p>\n<p>Bu \u00f6rnek, Spring'in <code>@Transactional<\/code> anotasyonu ile deklaratif i\u015flem y\u00f6netiminin ne kadar g\u00fc\u00e7l\u00fc ve kullan\u0131m\u0131 kolay oldu\u011funu g\u00f6stermektedir. Geli\u015ftirici, veritaban\u0131 i\u015flemlerinin detaylar\u0131yla u\u011fra\u015fmak yerine do\u011frudan i\u015f mant\u0131\u011f\u0131na odaklanabilir.<\/p>\n<h2>\u0130\u015flem Y\u00f6netiminde Dikkat Edilmesi Gerekenler<\/h2>\n<p>Spring'in i\u015flem y\u00f6netimi olduk\u00e7a g\u00fc\u00e7l\u00fc olsa da, do\u011fru kullan\u0131m\u0131 i\u00e7in baz\u0131 \u00f6nemli noktalar\u0131 g\u00f6z \u00f6n\u00fcnde bulundurmak gerekir:<\/p>\n<p>*   <strong><code>@Transactional<\/code> Anotasyonunun S\u0131n\u0131rlamalar\u0131:<\/strong><br \/>\n    *   <strong>Public Metotlar:<\/strong> <code>@Transactional<\/code> anotasyonu yaln\u0131zca public metotlar \u00fczerinde etkilidir. Spring AOP, metot \u00e7a\u011fr\u0131lar\u0131n\u0131 yakalamak i\u00e7in proxy'leri kullan\u0131r ve proxy'ler genellikle yaln\u0131zca public metotlar\u0131 ve aray\u00fcz metotlar\u0131n\u0131 sarabilir.<br \/>\n    *   <strong>Self-invocation (Ayn\u0131 S\u0131n\u0131f \u0130\u00e7i \u00c7a\u011fr\u0131lar):<\/strong> Bir <code>@Transactional<\/code> metot, ayn\u0131 s\u0131n\u0131f i\u00e7indeki ba\u015fka bir metodu (yine <code>@Transactional<\/code> olsa bile) \u00e7a\u011f\u0131rd\u0131\u011f\u0131nda, bu i\u00e7 \u00e7a\u011fr\u0131 i\u00e7in i\u015flem proxy'si atlan\u0131r. Bu durumda, i\u00e7 metot i\u00e7in yeni bir i\u015flem ba\u015flat\u0131lmaz veya mevcut i\u015flem kullan\u0131lmaz; \u00e7a\u011fr\u0131 basit\u00e7e do\u011frudan yap\u0131l\u0131r. Bu, genellikle yay\u0131l\u0131m davran\u0131\u015flar\u0131n\u0131n beklendi\u011fi gibi \u00e7al\u0131\u015fmamas\u0131na neden olur. Bu durumu a\u015fmak i\u00e7in, \u00e7a\u011fr\u0131lar\u0131 farkl\u0131 bir servis bean'ine ta\u015f\u0131mak veya <code>ApplicationContext<\/code>'ten servis bean'ini almak gerekebilir (ancak bu son y\u00f6ntem genellikle \u00f6nerilmez).<br \/>\n*   <strong>Performans Etkileri:<\/strong> Y\u00fcksek izolasyon seviyeleri (\u00f6zellikle <code>SERIALIZABLE<\/code>), e\u015fzamanl\u0131l\u0131k \u00fczerinde \u00f6nemli bir k\u0131s\u0131tlama getirerek performans\u0131 d\u00fc\u015f\u00fcrebilir. \u0130\u015flem kapsam\u0131n\u0131 \u00e7ok geni\u015f tutmak da performans\u0131 olumsuz etkileyebilir \u00e7\u00fcnk\u00fc veritaban\u0131 kaynaklar\u0131 daha uzun s\u00fcre kilitli kal\u0131r. \u0130htiya\u00e7 duyulan en d\u00fc\u015f\u00fck izolasyon seviyesini ve en dar i\u015flem kapsam\u0131n\u0131 kullanmaya \u00f6zen g\u00f6sterin.<br \/>\n*   <strong>Veritaban\u0131 Kilitlenmeleri (Deadlocks):<\/strong> E\u015fzamanl\u0131 i\u015flemlerin birbirini beklemesi sonucu olu\u015fan kilitlenmeler, i\u015flem y\u00f6netiminin karma\u015f\u0131k bir y\u00f6n\u00fcd\u00fcr. Spring'in kendisi kilitlenmeleri \u00e7\u00f6zmez, ancak i\u015flem zaman a\u015f\u0131m\u0131 (<code>timeout<\/code>) gibi \u00f6zelliklerle uzun s\u00fcren i\u015flemleri sonland\u0131rabilir. Kilitlenmeleri \u00f6nlemek i\u00e7in veritaban\u0131 tasar\u0131m\u0131n\u0131, sorgu optimizasyonlar\u0131n\u0131 ve kilitlenme stratejilerini (optimistik\/pesimistik kilitlenme) iyi anlamak gerekir.<br \/>\n*   <strong>\u0130\u015flem Kapsam\u0131n\u0131 Do\u011fru Belirleme:<\/strong> Bir i\u015flemin kapsam\u0131, sadece ilgili veritaban\u0131 operasyonlar\u0131n\u0131 i\u00e7ermelidir. Uzun s\u00fcren hesaplamalar, d\u0131\u015f sistem \u00e7a\u011fr\u0131lar\u0131 (\u00f6rne\u011fin, bir REST API'sine \u00e7a\u011fr\u0131) veya kullan\u0131c\u0131 giri\u015fi bekleyen operasyonlar i\u015flem d\u0131\u015f\u0131nda tutulmal\u0131d\u0131r. Aksi takdirde, veritaban\u0131 ba\u011flant\u0131lar\u0131 gereksiz yere a\u00e7\u0131k kal\u0131r, kilitler uzun s\u00fcre tutulur ve sistem performans\u0131 d\u00fc\u015fer.<br \/>\n*   <strong>Test Edilebilirlik:<\/strong> \u0130\u015flem y\u00f6netimini do\u011fru bir \u015fekilde test etmek \u00f6nemlidir. Spring, <code>@Transactional<\/code> test anotasyonu ve test ba\u011flam\u0131 y\u00f6netimi ile entegrasyon testlerini kolayla\u015ft\u0131r\u0131r. Testlerde <code>rollbackFor<\/code> ve <code>noRollbackFor<\/code> davran\u0131\u015flar\u0131n\u0131, farkl\u0131 yay\u0131l\u0131m ve izolasyon seviyelerini test etmek, uygulaman\u0131n sa\u011flaml\u0131\u011f\u0131n\u0131 art\u0131r\u0131r.<br \/>\n*   <strong><code>DataSource<\/code> ve <code>PlatformTransactionManager<\/code> Se\u00e7imi:<\/strong> Kullan\u0131lan veritaban\u0131 ve ORM\/JDBC teknolojisine uygun <code>DataSource<\/code> (\u00f6rn: <code>HikariCP<\/code>, <code>Apache Commons DBCP2<\/code>) ve <code>PlatformTransactionManager<\/code> (\u00f6rn: <code>DataSourceTransactionManager<\/code>, <code>JpaTransactionManager<\/code>) implementasyonlar\u0131n\u0131 se\u00e7mek \u00f6nemlidir.<\/p>\n<h2>Sonu\u00e7<\/h2>\n<p>Spring Framework, JDBC tabanl\u0131 uygulamalarda i\u015flem y\u00f6netimini inan\u0131lmaz derecede basitle\u015ftiren ve standartla\u015ft\u0131ran g\u00fc\u00e7l\u00fc bir soyutlama katman\u0131 sunar. Bu makalede, i\u015flem y\u00f6netiminin temel kavramlar\u0131n\u0131 (ACID, izolasyon, yay\u0131l\u0131m), Spring'in programatik ve deklaratif yakla\u015f\u0131mlar\u0131n\u0131 detayl\u0131 bir \u015fekilde inceledik. \u00d6zellikle <code>@Transactional<\/code> anotasyonunun sa\u011flad\u0131\u011f\u0131 deklaratif modelin, i\u015f mant\u0131\u011f\u0131n\u0131 i\u015flem y\u00f6netimi detaylar\u0131ndan ay\u0131rarak kodu daha temiz, okunabilir ve s\u00fcrd\u00fcr\u00fclebilir hale getirdi\u011fini g\u00f6rd\u00fck.<\/p>\n<p>Sa\u011flad\u0131\u011f\u0131m\u0131z pratik \u00f6rnek uygulama, bir banka transferi senaryosu \u00fczerinden Spring JDBC ve <code>@Transactional<\/code> anotasyonunun nas\u0131l birlikte \u00e7al\u0131\u015ft\u0131\u011f\u0131n\u0131 somut bir \u015fekilde g\u00f6sterdi. Ba\u015far\u0131l\u0131 transferler, yetersiz bakiye ve \u00e7al\u0131\u015fma zaman\u0131 hatalar\u0131 gibi farkl\u0131 senaryolarda i\u015flemlerin nas\u0131l y\u00f6netildi\u011fini, commit ve rollback mekanizmalar\u0131n\u0131n nas\u0131l devreye girdi\u011fini g\u00f6zlemledik.<\/p>\n<p>Spring'in i\u015flem y\u00f6netimi yetenekleri sayesinde geli\u015ftiriciler, veri tutarl\u0131l\u0131\u011f\u0131 ve g\u00fcvenilirli\u011fi sa\u011flama gibi kritik g\u00f6revleri \u00e7ok daha az \"boilerplate\" kodu ile ger\u00e7ekle\u015ftirebilirler. Ancak, bu g\u00fcc\u00fc etkili bir \u015fekilde kullanmak i\u00e7in izolasyon seviyeleri, yay\u0131l\u0131m davran\u0131\u015flar\u0131 ve <code>@Transactional<\/code> anotasyonunun s\u0131n\u0131rlamalar\u0131 gibi temel kavramlar\u0131 iyi anlamak esast\u0131r. Do\u011fru yap\u0131land\u0131rma ve dikkatli bir tasar\u0131m ile Spring JDBC, sa\u011flam ve y\u00fcksek performansl\u0131 veritaban\u0131 uygulamalar\u0131 geli\u015ftirmek i\u00e7in vazge\u00e7ilmez bir ara\u00e7t\u0131r. Gelecekte, Spring Boot'un otomatik yap\u0131land\u0131rma \u00f6zellikleriyle bu kurulumlar\u0131n daha da basitle\u015ftirilebilece\u011fini unutmamak gerekir.<\/body><\/p>\n","protected":false},"excerpt":{"rendered":"Spring JDBC ile \u0130\u015flem Y\u00f6netimi: Kapsaml\u0131 Bir Rehber ve \u00d6rnek Uygulama\nGiri\u015f\nModern yaz\u0131l\u0131m uygulamalar\u0131, veri tutarl\u0131l\u0131\u011f\u0131 ve g\u00fcvenilirl","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"csco_page_header_type":"","csco_page_load_nextpost":"","csco_page_subscribe_form":"","csco_page_contact_form":"","footnotes":""},"categories":[1],"tags":[],"class_list":{"0":"post-38729","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-genel","7":"cs-entry","8":"cs-video-wrap"},"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.5 (Yoast SEO v25.3.1) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Spring JDBC ile \u0130\u015flem Y\u00f6netimi: Kapsaml\u0131 Bir Rehber ve \u00d6rnek Uygulama - Kodlar\u0131n Gizemli D\u00fcnyas\u0131<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/fatihsoysal.com\/blog\/spring-jdbc-ile-islem-yonetimi-kapsamli-bir-rehber-ve-ornek-uygulama\/\" \/>\n<meta property=\"og:locale\" content=\"tr_TR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Spring JDBC ile \u0130\u015flem Y\u00f6netimi: Kapsaml\u0131 Bir Rehber ve \u00d6rnek Uygulama\" \/>\n<meta property=\"og:description\" content=\"Spring JDBC ile \u0130\u015flem Y\u00f6netimi: Kapsaml\u0131 Bir Rehber ve \u00d6rnek Uygulama Giri\u015f Modern yaz\u0131l\u0131m uygulamalar\u0131, veri tutarl\u0131l\u0131\u011f\u0131 ve g\u00fcvenilirl\" \/>\n<meta property=\"og:url\" content=\"https:\/\/fatihsoysal.com\/blog\/spring-jdbc-ile-islem-yonetimi-kapsamli-bir-rehber-ve-ornek-uygulama\/\" \/>\n<meta property=\"og:site_name\" content=\"Kodlar\u0131n Gizemli D\u00fcnyas\u0131\" \/>\n<meta property=\"article:published_time\" content=\"2026-02-06T09:40:56+00:00\" \/>\n<meta name=\"author\" content=\"Fatih Soysal\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Yazan:\" \/>\n\t<meta name=\"twitter:data1\" content=\"Fatih Soysal\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tahmini okuma s\u00fcresi\" \/>\n\t<meta name=\"twitter:data2\" content=\"22 dakika\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/spring-jdbc-ile-islem-yonetimi-kapsamli-bir-rehber-ve-ornek-uygulama\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/spring-jdbc-ile-islem-yonetimi-kapsamli-bir-rehber-ve-ornek-uygulama\/\"},\"author\":{\"name\":\"Fatih Soysal\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"headline\":\"Spring JDBC ile \u0130\u015flem Y\u00f6netimi: Kapsaml\u0131 Bir Rehber ve \u00d6rnek Uygulama\",\"datePublished\":\"2026-02-06T09:40:56+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/spring-jdbc-ile-islem-yonetimi-kapsamli-bir-rehber-ve-ornek-uygulama\/\"},\"wordCount\":3075,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/spring-jdbc-ile-islem-yonetimi-kapsamli-bir-rehber-ve-ornek-uygulama\/#respond\"]}],\"copyrightYear\":\"2026\",\"copyrightHolder\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/spring-jdbc-ile-islem-yonetimi-kapsamli-bir-rehber-ve-ornek-uygulama\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/spring-jdbc-ile-islem-yonetimi-kapsamli-bir-rehber-ve-ornek-uygulama\/\",\"name\":\"Spring JDBC ile \u0130\u015flem Y\u00f6netimi: Kapsaml\u0131 Bir Rehber ve \u00d6rnek Uygulama - Kodlar\u0131n Gizemli D\u00fcnyas\u0131\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\"},\"datePublished\":\"2026-02-06T09:40:56+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/spring-jdbc-ile-islem-yonetimi-kapsamli-bir-rehber-ve-ornek-uygulama\/#breadcrumb\"},\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/spring-jdbc-ile-islem-yonetimi-kapsamli-bir-rehber-ve-ornek-uygulama\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/spring-jdbc-ile-islem-yonetimi-kapsamli-bir-rehber-ve-ornek-uygulama\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Anasayfa\",\"item\":\"https:\/\/fatihsoysal.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Spring JDBC ile \u0130\u015flem Y\u00f6netimi: Kapsaml\u0131 Bir Rehber ve \u00d6rnek Uygulama\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/\",\"name\":\"Fatihsoysal.com\",\"description\":\"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim\",\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"tr\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\",\"name\":\"Fatih Soysal\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"tr\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"contentUrl\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"width\":512,\"height\":512,\"caption\":\"Fatih Soysal\"},\"logo\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\"},\"description\":\"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Spring JDBC ile \u0130\u015flem Y\u00f6netimi: Kapsaml\u0131 Bir Rehber ve \u00d6rnek Uygulama - Kodlar\u0131n Gizemli D\u00fcnyas\u0131","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/fatihsoysal.com\/blog\/spring-jdbc-ile-islem-yonetimi-kapsamli-bir-rehber-ve-ornek-uygulama\/","og_locale":"tr_TR","og_type":"article","og_title":"Spring JDBC ile \u0130\u015flem Y\u00f6netimi: Kapsaml\u0131 Bir Rehber ve \u00d6rnek Uygulama","og_description":"Spring JDBC ile \u0130\u015flem Y\u00f6netimi: Kapsaml\u0131 Bir Rehber ve \u00d6rnek Uygulama Giri\u015f Modern yaz\u0131l\u0131m uygulamalar\u0131, veri tutarl\u0131l\u0131\u011f\u0131 ve g\u00fcvenilirl","og_url":"https:\/\/fatihsoysal.com\/blog\/spring-jdbc-ile-islem-yonetimi-kapsamli-bir-rehber-ve-ornek-uygulama\/","og_site_name":"Kodlar\u0131n Gizemli D\u00fcnyas\u0131","article_published_time":"2026-02-06T09:40:56+00:00","author":"Fatih Soysal","twitter_card":"summary_large_image","twitter_misc":{"Yazan:":"Fatih Soysal","Tahmini okuma s\u00fcresi":"22 dakika"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/fatihsoysal.com\/blog\/spring-jdbc-ile-islem-yonetimi-kapsamli-bir-rehber-ve-ornek-uygulama\/#article","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/spring-jdbc-ile-islem-yonetimi-kapsamli-bir-rehber-ve-ornek-uygulama\/"},"author":{"name":"Fatih Soysal","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"headline":"Spring JDBC ile \u0130\u015flem Y\u00f6netimi: Kapsaml\u0131 Bir Rehber ve \u00d6rnek Uygulama","datePublished":"2026-02-06T09:40:56+00:00","mainEntityOfPage":{"@id":"https:\/\/fatihsoysal.com\/blog\/spring-jdbc-ile-islem-yonetimi-kapsamli-bir-rehber-ve-ornek-uygulama\/"},"wordCount":3075,"commentCount":0,"publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"inLanguage":"tr","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/fatihsoysal.com\/blog\/spring-jdbc-ile-islem-yonetimi-kapsamli-bir-rehber-ve-ornek-uygulama\/#respond"]}],"copyrightYear":"2026","copyrightHolder":{"@id":"https:\/\/fatihsoysal.com\/blog\/#organization"}},{"@type":"WebPage","@id":"https:\/\/fatihsoysal.com\/blog\/spring-jdbc-ile-islem-yonetimi-kapsamli-bir-rehber-ve-ornek-uygulama\/","url":"https:\/\/fatihsoysal.com\/blog\/spring-jdbc-ile-islem-yonetimi-kapsamli-bir-rehber-ve-ornek-uygulama\/","name":"Spring JDBC ile \u0130\u015flem Y\u00f6netimi: Kapsaml\u0131 Bir Rehber ve \u00d6rnek Uygulama - Kodlar\u0131n Gizemli D\u00fcnyas\u0131","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/#website"},"datePublished":"2026-02-06T09:40:56+00:00","breadcrumb":{"@id":"https:\/\/fatihsoysal.com\/blog\/spring-jdbc-ile-islem-yonetimi-kapsamli-bir-rehber-ve-ornek-uygulama\/#breadcrumb"},"inLanguage":"tr","potentialAction":[{"@type":"ReadAction","target":["https:\/\/fatihsoysal.com\/blog\/spring-jdbc-ile-islem-yonetimi-kapsamli-bir-rehber-ve-ornek-uygulama\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/fatihsoysal.com\/blog\/spring-jdbc-ile-islem-yonetimi-kapsamli-bir-rehber-ve-ornek-uygulama\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Anasayfa","item":"https:\/\/fatihsoysal.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Spring JDBC ile \u0130\u015flem Y\u00f6netimi: Kapsaml\u0131 Bir Rehber ve \u00d6rnek Uygulama"}]},{"@type":"WebSite","@id":"https:\/\/fatihsoysal.com\/blog\/#website","url":"https:\/\/fatihsoysal.com\/blog\/","name":"Fatihsoysal.com","description":"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim","publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"tr"},{"@type":["Person","Organization"],"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1","name":"Fatih Soysal","image":{"@type":"ImageObject","inLanguage":"tr","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","contentUrl":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","width":512,"height":512,"caption":"Fatih Soysal"},"logo":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/"},"description":"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.","url":"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/"}]}},"yoast_meta":{"yoast_wpseo_title":"","yoast_wpseo_metadesc":"","yoast_wpseo_canonical":""},"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/38729","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/comments?post=38729"}],"version-history":[{"count":1,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/38729\/revisions"}],"predecessor-version":[{"id":38730,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/38729\/revisions\/38730"}],"wp:attachment":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/media?parent=38729"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/categories?post=38729"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/tags?post=38729"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}