Bu makale, İspirer'in finansal danışmanlık alanında faaliyet gösteren büyük bir şirket için yürüttüğü projeye dayanarak Microsoft SQL Server modernizasyonuna ayrılmıştır. Müşteri, müşterilerinin finansal bilgilerini verimli bir şekilde yönetmek, işlemek, erişmek ve denetlemek için SQL Server veritabanının gücünden yararlandı. Müşteri, sistem mimarisini ve bakım maliyetlerini optimize ederken SQL Server'ı bir buluta geçirmeyi hedefliyordu.
İspirer ekibi, veritabanının OLTP modunda kullanılması nedeniyle iş mantığını Java'ya aktarmayı teklif etti. Konuyu dikkatli bir şekilde analiz edeceğiz ve müşterinin SQL Server iş kurallarını Java'ya dönüştürmeyi içeren projesini inceleyeceğiz. Ayrıca şirketlerin SQL kodunu bir uygulama katmanına geçirmeyi tercih etmelerinin ardındaki nedenleri de araştıracağız. Bu, tüm sürecin kapsamlı bir incelemesini içerecektir.
Müşteri, bulut altyapısının maliyetlerini optimize etmek için tabloları ve verileri PostgreSQL'e taşımaya karar verdi. Veritabanı ve uygulama geçişi konusunda uzmanlaştığımız için müşteri aşağıdaki görevlerle ilgili olarak bize başvurdu:
Projenin önemli ölçeği nedeniyle müşteri, otomasyonu uygulayarak geçiş masraflarını en aza indirmeye çalıştı. İspirer Araç Takımının verimliliğini optimize etmek için özelleştirmenin önceden yapılması gerektiğine karar verdik. Bu yaklaşım, müşterinin ekibine T-SCL'den Java'ya dönüşüm oranı yaklaşık %90 olan bir araç sunmamızı sağladı.
Şimdi tabloların ve verilerin taşınması konusuna daha derinlemesine bakalım.
Müşterinin şirket içi SQL Server'dan buluta geçmeyi seçmesinin nedenlerini ele alalım. Bu geçişin bir takım yadsınamaz avantajları vardır:
Tasarruf. Bulutta SQL Server'dan PostgreSQL'e geçişin arkasındaki temel faktörlerden biri maliyet tasarrufudur. Müşteri, SQL Server veritabanlarını yerinde tutmanın pahalı olduğunu düşünüyordu. Bunun nedeni özel ekipmana, yazılım lisanslarına ve yetenekli veritabanı yöneticilerine duyulan ihtiyaçtı. Açık kaynaklı bir veritabanı olan PostgreSQL, uygun maliyetli bir alternatif sunuyor. Müşteriler bulutu kullanarak paradan tasarruf edebilirler. Büyük ön ödemeler yapmak yerine yalnızca kullandıkları kadar ödeme yapmak zorundalar. Ayrıca operasyonlara daha az harcama yapabilirler.
Ölçeklenebilirlik. Bulut bilişim, daha fazla iş yüküne ve daha fazla kullanıcıya hizmet vermek için şirket içi altyapıya göre daha kolay ölçeklenebilir. Şirket içi bir sistemin bir işletmenin ihtiyaçlarına göre ölçeklenebilmesi için kuruluşların, geleneksel BT ortamlarında iş hizmetlerinin ölçeğini genişletmek amacıyla fiziksel sunucular, yazılım lisansları, depolama ve ağ ekipmanı satın alması ve kurması gerekiyordu. Bulutta bu kaynakların çoğuna birkaç tıklamayla anında erişilebiliyor ve ihtiyaç duyulan kaynaklara göre otomatik olarak ölçeklendirilebiliyor. Buluttaki PostgreSQL, yüksek düzeyde ölçeklenebilirlik sağlayarak müşterimizin kaynakları talebe göre kolayca ayarlamasına olanak tanır.
Güvenlik. Bulut teknolojisini benimsemek, bulut sağlayıcıları tarafından sağlanan gelişmiş kimlik kontrolleri, erişim yönetimi ve kimlik doğrulama sistemleri sayesinde dikkate değer güvenlik avantajları sunar. Bulut sağlayıcıları genellikle şirket içi BT ekiplerinden veya yerel sistemlerden daha iyi güvenlik standartlarına sahiptir ve bu da veri ortamını daha güvenli hale getirir.
Buluttaki güçlü şifreleme, veri ihlali olasılığını azaltır. İşletmelerin kullanıcı erişimini etkili bir şekilde kontrol etmesine yardımcı olan katmanlı güvenlik, iyi anahtar yönetimi ve güvenli erişim kontrollerini içerir. Ayrıca bulut sağlayıcıları, veri korumasını güçlendirmek için anonimlik, çoğaltma ve şifreleme gibi önlemleri uygulayarak fiziksel erişimi titizlikle denetler. 2025 yılına kadar işletmelerin yaklaşık %80'inin fiziksel veri merkezlerinden bulut hizmetlerine geçiş yapacağı öngörülüyor. Bu değişim, bulutun sağladığı gelişmiş güvenlik avantajlarından kaynaklanmaktadır.
Bulutta SQL Server'dan PostgreSQL'e geçiş, belirli hususların göz önünde bulundurularak dikkatli bir planlama ve yürütme gerektirir. Müşterinin projesine dayanarak ekibimiz SQL Server'ı modernleştirmek için aşağıdaki adımları vurguladı:
Şema ve Veri Dönüşümü. Veriler PostgreSQL'in gereksinimlerine uyacak şekilde doğru bir şekilde dönüştürülmelidir. Bu, tarih formatları ve karakter kodlaması gibi nüansların ele alınmasını içerebilir.
Kısıtlamalar ve Tetikleyiciler. İki veritabanındaki kısıtlamaların ve tetikleyicilerin kullanımındaki farklılıkları anlamak çok önemlidir. Buna göre gerekli değişikliklerin yapılması gerekmektedir. Ayrıca tetikleyicilerin işlevleri uygulamaya taşınabilir. Ancak bu görev basit olmaktan çok uzaktır, bu nedenle artıları ve eksileri tartmak önemlidir.
Verim iyileştirmesi. Geçiş sürecinin optimizasyonu, kesinti süresinin ve veri aktarım süresinin en aza indirilmesine olanak tanır. Verimli geçiş için paralelleştirmeden yararlanmak, ağ bant genişliğini optimize etmek ve güçlü donanıma yatırım yapmak önemlidir.
Veri Doğrulama ve Test Etme. Veri bütünlüğünü ve işlevselliğini garanti etmek için taşınan verilerin sıkı bir şekilde doğrulanması gerekir. Kapsamlı testler, uygulamaların yeni PostgreSQL veritabanıyla sorunsuz bir şekilde çalışmasını sağlar.
Güvenlik ve İzinler. PostgreSQL'deki güvenlik ayarları, kullanıcı hesapları ve izinler, sorunsuz bir geçiş sağlayacak şekilde orijinal SQL Server kurulumuyla eşleşecek şekilde yapılandırılmalıdır.
Geçmişte müşterilerimiz iş mantıkları için performansı artıracağını düşünerek saklı prosedürleri kullanıyordu. Ancak dürüst olalım, SQL dili, uygulama katmanıyla karşılaştırıldığında iş mantığını barındırmak için en uygun seçim olmayabilir.
Aslında SQL yalnızca veritabanındaki verileri sorgular veya değiştirir. Burada pek çok kişi bize çürük domates fırlatabilir, çünkü SQL dili, bir sorgudan tam olarak ihtiyacınız olan verileri elde etmek için karmaşık birleştirmeler, filtreleme ve sıralama yapmada iyidir ve daha fazlasını yapmaz. O halde neden herhangi bir şeyi değiştirip iş mantığını uygulama düzeyine getirelim ki?
Soru mantıklı görünüyor. Daha ayrıntılı olarak cevaplayalım. Aşağıda, iş mantığını uygulamaya aktarmayı ciddi olarak düşünmeniz için 4 ana nedeni özetledik. Müşterinin iş mantığını uygulama katmanına taşıma kararı aşağıdaki nedenlerden kaynaklanmıştır:
Ölçeklenebilirlik açısından iş mantığını uygulama düzeyinde depolamak en iyi seçenektir. Neden? Çünkü genel olarak uygulama sunucusu kaynaklarınızı ölçeklendirmek, veritabanı sunucusu kaynaklarınızı ölçeklendirmekten çok daha kolaydır. Bu neredeyse evrensel olarak kabul edilmektedir. Çoğu web uygulaması için, yönetilecek çok fazla trafik olduğunda daha fazla sunucu eklemek genellikle kolaydır. Ancak veritabanınız artan talebi karşılayacak şekilde ölçeklenemediği sürece ekstra uygulama sunucularının değeri azalır. Bir veritabanı sunucusunu ölçeklendirmek, uygulama sunucularını eklemekten çok daha zordur.
İş mantığını bir veritabanında saklamak, sürdürülebilirlik konusunda zorluklar yaratabilir. Saklı yordamları değiştirmek birçok uygulamayı bozabilir, genişletilebilirliği sınırlayabilir ve "Kendinizi Tekrarlama" (KURUTMA) ilkesini takip etmeyi zorlaştırabilir. 100 satırı aşan SQL kodu genellikle karmaşıklıklara ve sorun giderme zorluklarına neden olur. İş mantığını uygulama katmanına ayırmak, yeni ekip üyelerinin girişini kolaylaştırabilir ve yeniden düzenleme için daha sezgisel bir platform sağlayabilir.
SQL, sisteminizin iş kurallarını kodlamak için kötü bir seçimdir. Esnek değildir ve uygun soyutlamalar oluşturamadığı için karmaşık modelleri temsil etme konusunda ona güvenemeyiz. Bu sınırlama, onu iş mantığı için kullanmaktan kaçınmanın temel nedenidir. Bu, araç kullanımı veya destekle ilgili değil, daha fazla fırsat sunan nesne yönelimli ve işlevsel tasarımın aksine, SQL'in basit ve etkileyici bir etki alanı modeli oluşturamamasıyla ilgili.
Yazılım geliştirmede kodu yeniden kullanmak, mevcut kodu yeni görevlere uyarlarken zamandan ve maliyetten tasarruf etmenin etkili bir yoludur. Nesneye Yönelik Programlama (OOP), kod geri dönüşümünü kolaylaştırarak onu çeşitli uygulamalara uygun hale getiren bir yöntemdir. Ancak veritabanlarında yaygın olarak kullanılan SQL, kodun yeniden kullanımı için sınırlı esneklik sunar. Seçenekler arasında "görünümler" ve "saklı prosedürler" kullanılması yer alır, ancak ikincisi çok sayıda parametreye yol açabilir. Projeniz için doğru seçimi sağlamak için her yöntemi iyice araştırmak önemlidir.
Transact-SQL'i Java'ya dönüştürmek çeşitli temel hususları içerir. Süreç, doğru veri temsilinin sağlanması için SQL veri türlerinin Java eşdeğerleriyle eşlenmesini içerir. Ayrıca, Java'nın veritabanı etkileşimlerini yönetmek için JDBC veya Hibernate gibi kitaplıklara güvendiği SQL sorgularının Java koduna çevrilmesini de kapsar. Ayrıca, bazı ESQL özelliklerinin Java'da doğrudan eşdeğerleri bulunmaması, otomatik dönüştürmenin verimsiz olduğu izlenimini verme potansiyeline sahiptir.
Projemizin kişiselleştirme aşamasında otomasyon oranını artıran bir dizi dönüşüm çözümü oluşturmayı başardık. Başlangıçta otomatikleştirilmesinin imkansız olduğuna inanılan bu çözümlerin sonuçta başarılı olduğu kanıtlandı. Bunlardan bazılarının ayrıntılarına bakalım.
Bir kimlik sütununa eklenen son kimlik değerini almak için bir INSERT ifadesini SCOPE_IDENTITY() ile birlikte dönüştürme.
Kaynak:
ALTER PROCEDURE example1 AS BEGIN Declare @idBit int Declare @c int Insert Into tab (c) Values (@c) Set @idBit = SCOPE_IDENTITY() End
Hedef:
@Service public class Example1 implements IExample1 { @Autowired private JdbcTemplate jdbcTemplate; private static final org.slf4j.Logger LOGGER = org.slf4j.LoggerFactory.getLogger(Example1.class); @Override public Integer spExample1() throws SQLException, Exception { Integer mStatus = 0; KeyHolder keyHolder = new GeneratedKeyHolder(); try { Integer idBit = null; Integer c = null; { final Integer tmpC = c; jdbcTemplate.update(connection-> { PreparedStatement ps = connection.prepareStatement("Insert Into tab(c) \r\n" + " Values(?)", new String[] { "" }); ps.setInt( 1, tmpC); return ps; }, keyHolder); } idBit = Tsqlutils.<Integer > strToNum(keyHolder.getKey().toString(), Integer.class); return mStatus; } catch (Exception e) { LOGGER.error(String.valueOf(e)); mStatus = -1; return mStatus; } } }
Kaynak:
ALTER PROCEDURE [returnSeveralResultSet] @p1 int, @p2 varchar(50) AS Begin select cob_ft, lower(buzon) from tab1 where cob_id = @p1 and cob_ft = @p2 select dep_ft, lower(fiton) from tab2 END
Hedef:
@Service public class Returnseveralresultset implements IReturnseveralresultset { @Autowired private JdbcTemplate jdbcTemplate; private static final org.slf4j.Logger LOGGER = org.slf4j.LoggerFactory.getLogger(Returnseveralresultset.class); private Integer errorCode = 0; private String sqlState = ""; @Override public Map<String, Object> spReturnseveralresultset(Integer p1, String p2) throws Exception { Integer mStatus = 0; Map<String, Object> outData = new HashMap<>(); List<SqlRowSet> outRsList = new ArrayList<>(); SqlRowSet rowSet; try { rowSet = jdbcTemplate.queryForRowSet("select cob_ft, lower(buzon) from tab1 \r\n" + " where cob_id = ? and cob_ft = ?", p1, p2); outRsList.add(rowSet); rowSet = jdbcTemplate.queryForRowSet("select dep_ft, lower(fiton) from tab2"); outRsList.add(rowSet); return outData; } catch (Exception e) { LOGGER.error(String.valueOf(e)); mStatus = -1; return outData; } finally { outData.put("status", mStatus); outData.put("rsList", outRsList); } } }
Kaynak:
create procedure datediffFn as declare @var1 int set @var1 = DATEDIFF(dd, '1999-01-01', '2000-02-01') set @var1 = DATEDIFF(mm, getdate(), '2000-02-01') set @var1 = DATEDIFF(week, '2005-12-31 23:59:59.9999999', '2006-01-01 00:00:00.0000000');
Hedef:
public Integer spDatedifffn() throws Exception { Integer mStatus = 0; try { Integer var1 = null; var1 = Tsqlutils.datediff("dd", Tsqlutils.toTimestamp("1999-01-01"), Tsqlutils.toTimestamp("2000-02-01")); var1 = Tsqlutils.datediff("mm", new Timestamp(new java.util.Date().getTime()), Tsqlutils.toTimestamp("2000-02-01")); var1 = Tsqlutils.datediff("week", Tsqlutils.toTimestamp("2005-12-31 23:59:59.9999999"), Tsqlutils.toTimestamp("2006-01-01 00:00:00.0000000")); return mStatus; } catch (Exception e) { LOGGER.error(String.valueOf(e)); mStatus = -1; return mStatus; } }
Kaynak:
create PROCEDURE spSendDbmail AS BEGIN EXEC msdb.dbo.sp_send_dbmail @profile_name = 'New DB Ispirer Profile', @recipients = '[email protected]', @body = '<h1>This is actual message embedded in HTML tags</h1>', @subject = 'Automated Success Message' , @file_attachments = 'C:\Temp\Attached.txt', @body_format='HTML', @copy_recipients = '[email protected]', @blind_copy_recipients = '[email protected]'; END
Hedef:
import java.util.*; import com.ispirer.mssql.mail.MailService; public class Spsenddbmail { private static final org.slf4j.Logger LOGGER = org.slf4j.LoggerFactory.getLogger(Spsenddbmail.class); public Integer spSpsenddbmail() throws Exception { Integer mStatus = 0; try { MailService.send("New DB Ispirer Profile", "Automated Success Message", "<h1>This is actual message embedded in HTML tags</h1>", "[email protected]", "[email protected]", "[email protected]", "C:\\Temp\\Attached.txt", "HTML"); return mStatus; } catch (Exception e) { LOGGER.error(String.valueOf(e)); mStatus = -1; return mStatus; } } }
Kaynak:
create procedure workWithXml AS begin declare @result bit, @myDoc XML, @myStr varchar(1000), @ProdID INT SET @myDoc = '<Root> <ProductDescription ProductID="1" ProductName="Road Bike"> <Features> <Warranty>1 year parts and labor</Warranty> <Maintenance>3 year parts and labor extended maintenance is available</Maintenance> </Features> </ProductDescription> </Root>' SET @result = @myDoc.exist('(/Root/ProductDescription/@ProductID)[1]') SET @myStr = cast(@myDoc.query('/Root/ProductDescription/Features') as varchar(max)) SET @ProdID = @myDoc.value('(/Root/ProductDescription/@ProductID)[1]', 'int' ) end;
Hedef:
import java.util.*; import com.ispirer.mssql.xml.XMLUtils; public class Workwithxml { private static final org.slf4j.Logger LOGGER = org.slf4j.LoggerFactory.getLogger(Workwithxml.class); public Integer spWorkwithxml() throws Exception { Integer mStatus = 0; try { Boolean result = null; String myDoc = null; String myStr = null; Integer prodID = null; myDoc = "<Root> " + "<ProductDescription ProductID=\"1\" ProductName=\"Road Bike\"> " + "<Features> " + "<Warranty>1 year parts and labor</Warranty> " + "<Maintenance>3 year parts and labor extended maintenance is available</Maintenance> " + "</Features> " + "</ProductDescription> " + " </Root>"; result = XMLUtils.exist(myDoc, "(/Root/ProductDescription/@ProductID)[1]"); myStr = XMLUtils.query(myDoc, "/Root/ProductDescription/Features"); prodID = XMLUtils.<Integer > value(myDoc, "(/Root/ProductDescription/@ProductID)[1]", Integer.class); return mStatus; } catch (Exception e) { LOGGER.error(String.valueOf(e)); mStatus = -1; return mStatus; } } }
Özelleştirme çabalarımız sayesinde ekibimiz, T-SQL'den Java'ya geçişi otomatikleştirmek için bir dizi tekniği başarıyla geliştirdi. Bu, tüm proje için genel geçiş süresini önemli ölçüde kısalttı ve potansiyel manuel geçişe kıyasla geçişi 4 kat hızlandırmamıza olanak sağladı. Araç Seti özelleştirmemiz yalnızca geçişi hızlandırmakla kalmadı, aynı zamanda özelleştirme girişimlerimizin değerli etkisini ortaya koyarak projenin genel verimliliğini de artırdı. Örneklerde belirtilen yöntemler, müşteriye dönüşüm sonuçlarıyla birlikte sunulur.
Sonuç olarak, iş mantığını Transact-SQL'den Java'ya geçirmek, her iki dilin ve bunların farklı özelliklerinin kapsamlı bir şekilde anlaşılmasını gerektiren çok yönlü bir süreçtir.
Bu makalede, iş mantığının uygulama katmanına geçişini kapsamlı bir şekilde araştırdık ve böyle bir geçişi planlayanlar için değerli bilgiler sunduk. Müşterimizin durumu, bu tür modernizasyon projelerinin otomatikleştirilebileceğini ve bunun da geçiş sırasında zamandan ve emekten önemli ölçüde tasarruf sağladığını kanıtlıyor. Müşterimizin projesi, otomasyonun dikkate değer potansiyelinin ikna edici bir kanıtıdır. Otomasyonun, başlangıçta yeteneklerinin ötesinde görünebilecek süreçleri başarılı bir şekilde kolaylaştırabileceği modernizasyon yönlerinin bulunduğunu göstermektedir.
Sonuçta Transact-SQL'den Java'ya geçişi benimsemek, daha fazla esneklik, platformlar arası uyumluluk ve ölçeklenebilirlik arayan kuruluşlar için stratejik bir hamledir. Zorluklarını ortaya koyarken, taşınabilirlik, performans ve modern yazılım mimarilerine uyarlanabilirlik açısından sağladığı faydalar, bu geçişi, veritabanı sistemlerini ve uygulamalarını modernleştirmek isteyenler için değerli bir çaba haline getiriyor.