โดยทั่วไปบทความบนอินเทอร์เน็ตมีแหล่งข้อมูลหลายแหล่งหรือแหล่งข้อมูลแบบไดนามิกเท่านั้นในขณะที่โครงการล่าสุดจำเป็นต้องใช้สองวิธีในเวลาเดียวกัน มาบันทึกวิธีการกำหนดค่าสำหรับการอ้างอิงของคุณ
สถานการณ์แอปพลิเคชัน
โครงการจำเป็นต้องเชื่อมต่อฐานข้อมูลที่แตกต่างกันสองฐาน A และ B ในเวลาเดียวกันและพวกเขาเป็นทั้งสถาปัตยกรรมสลาวต์หลักไลบรารีหนึ่งเขียนและไลบรารีอ่านหลายรายการ
แหล่งข้อมูลหลายแหล่ง
ก่อนอื่นคุณต้องปิดใช้งาน DataSourceAutoconFiguration ที่มาพร้อมกับ Spring Boot เนื่องจากจะอ่าน Spring.Datasource.* คุณสมบัติของแอปพลิเคชันไฟล์ Properties และกำหนดค่าแหล่งข้อมูลเดียวโดยอัตโนมัติ เพียงเพิ่มแอตทริบิวต์ยกเว้นในคำอธิบายประกอบ @SpringBootapplication:
@springbootapplication (exclude = {dataSourceAutoconFiguration.class}) คลาสสาธารณะ titanwebapplication {โมฆะคงที่สาธารณะหลัก (สตริง [] args) {springapplication.run (titanwebapplication.class, args); -จากนั้นกำหนดค่าข้อมูลการเชื่อมต่อแหล่งข้อมูลหลายข้อมูลใน Application.properties:
# Titan Library Spring.datasource.titan-master.url = jdbc: mysql: // xxxx: พอร์ต/ไททัน? sername = spring.datasource.titan-master.password = spring.datasource.titan-master.driver-class-name = com.mysql.jdbc.driver# การกำหนดค่าการเชื่อมต่อพูล# omit# ไลบรารีอื่น ๆ Spring.datasource.db2.url = jdbc: mysql: // xxxx: พอร์ต/titan2? ตัวละคร = UTF-8SPRING.DATASOURCE.DB2.USERNAME = Spring.Datasource.db2.DataSource
เนื่องจากเราได้ปิดการกำหนดค่าแหล่งข้อมูลอัตโนมัติเราจึงต้องสร้างแหล่งข้อมูลเหล่านี้ด้วยตนเองในขั้นตอนต่อไป:
@ConfigurationPublic คลาส DataSourceConfig {@Bean (name = "TitanMasterds") @configurationProperties (คำนำหน้า = "Spring.datasource.titan-Master") // คำนำหน้าของอสังหาริมทรัพย์ที่เกี่ยวข้อง } @Bean (name = "ds2") @configurationProperties (คำนำหน้า = "spring.datasource.db2") // คำนำหน้าของคุณสมบัติที่สอดคล้องกันในแอปพลิเคชัน properteis dataSource dataSource2 () {return dataSourceBuilder.create () -ถัดไปคุณจะต้องกำหนดค่าสอง mybatis sqlsessionfactory เพื่อใช้แหล่งข้อมูลที่แตกต่างกัน:
@configuration @mapperscan (basepackages = {"titan.mapper"}, sqlsessionfactoryref = "sqlsessionfactory1") คลาสสาธารณะ MyBatisdBaconfig {@autowired @qualifier ("Titanmasterds") @Bean สาธารณะ SQLSessionFactory SQLSessionFactory1 () โยนข้อยกเว้น {SQLSessionFactoryBean FactoryBean = ใหม่ SQLSessionFactoryBean (); FactoryBean.setDatasource (DS1); // ใช้แหล่งข้อมูล Titan เพื่อเชื่อมต่อกับ Titan Library Return FactoryBean.getObject (); } @Bean สาธารณะ SQLSessionTemplate SQLSessionTemplate1 () โยนข้อยกเว้น {SQLSessionTemplate แม่แบบ = ใหม่ SQLSessionTemplate (SQLSessionFactory1 ()); // ใช้โรงงานที่กำหนดค่าไว้ด้านบนเพื่อส่งคืนเทมเพลต -หลังจากการกำหนดค่าข้างต้นอินเทอร์เฟซ Mapper ภายใต้ Titan.Mapper จะใช้แหล่งข้อมูลไททัน ในทำนองเดียวกันคุณสามารถใช้ SQLSessionFactory ที่สอง:
@การกำหนดค่า @mapperscan (basepackages = {"อื่น ๆ mapper"}, sqlsessionfactoryref = "sqlsessionfactory2") คลาสสาธารณะ MyBatisDbbconfig {@autowired @qualifier ("DS2") @Bean สาธารณะ SQLSessionFactory SQLSessionFactory2 () โยนข้อยกเว้น {SQLSessionFactoryBean FactoryBean = ใหม่ SQLSessionFactoryBean (); FactoryBean.setDatasource (DS2); return FactoryBean.getObject (); } @Bean สาธารณะ SQLSessionTemplate SQLSessionTemplate2 () โยนข้อยกเว้น {SQLSessionTemplate แม่แบบ = ใหม่ SQLSessionTemplate (SQLSessionFactory2 ()); เทมเพลตกลับ; -หลังจากเสร็จสิ้นการกำหนดค่าเหล่านี้สมมติว่ามี 2 mapper titan.mapper.usermapper และอื่น ๆ mapper.rolemapper เมื่อใช้อดีตไลบรารีไททันจะเชื่อมต่อโดยอัตโนมัติและหลังจะเชื่อมต่อกับไลบรารี DS2
แหล่งข้อมูลแบบไดนามิก
ความตั้งใจดั้งเดิมของการใช้แหล่งข้อมูลแบบไดนามิกคือการแยกการอ่านและเขียนที่เลเยอร์แอปพลิเคชันนั่นคือเพื่อควบคุมวิธีการสืบค้นที่แตกต่างกันในรหัสโปรแกรมเพื่อเชื่อมต่อกับไลบรารีที่แตกต่างกัน นอกเหนือจากวิธีนี้มิดเดิลแวร์ฐานข้อมูลยังเป็นตัวเลือกที่ดีเช่นกัน ข้อได้เปรียบคือคลัสเตอร์ฐานข้อมูลสัมผัสกับไลบรารีเดียวสำหรับแอปพลิเคชันเท่านั้นและไม่จำเป็นต้องสลับลอจิกรหัสของแหล่งข้อมูล
เราตระหนักถึงการสลับแหล่งข้อมูลแบบไดนามิกผ่านคำอธิบายประกอบที่กำหนดเอง + AOP
ก่อนกำหนด contextholder เพื่อบันทึกชื่อแหล่งข้อมูลที่ใช้โดยเธรดปัจจุบัน:
Public Class DataSourceContextholder {logger สุดท้ายคงที่ logger log = loggerFactory.getLogger (DataSourceContextholder.class); / *** แหล่งข้อมูลเริ่มต้น*/ สตริงสุดท้ายคงที่สตริง default_ds = "Titan-Master"; Private Static Final ThreadLocal <String> ContexTholder = ใหม่ ThreadLocal <> (); // ตั้งค่าชื่อแหล่งข้อมูลเป็นโมฆะคงที่สาธารณะ setDB (สตริง dbType) {log.debug ("สลับเป็น {} แหล่งข้อมูล", dbType); contextholder.set (dbtype); } // รับชื่อแหล่งข้อมูลสตริงคงที่สาธารณะ getDB () {return (contextholder.get ()); } // ล้างชื่อแหล่งข้อมูลโมฆะสาธารณะคงที่ cleardb () {contextholder.remove (); -จากนั้นปรับแต่งการใช้งานอินเตอร์เฟส javax.sql.datasource ที่นี่คุณจะต้องสืบทอดคลาสแม่ AbstractroutingDataSource ที่ฤดูใบไม้ผลิได้ดำเนินการสำหรับเราล่วงหน้า:
Public Class DynamicDataSource ขยาย AbstractroutingDataSource {logger สุดท้ายคงที่ logger log = loggerFactory.getLogger (DynamicDataSource.class); @Override วัตถุที่ได้รับการป้องกัน DECINECURRENTLOOKUPKEY () {log.debug ("แหล่งข้อมูลคือ {}", dataSourceContextholder.getDb ()); ส่งคืน DataSourceContextholder.getDb (); -สร้างแหล่งข้อมูลแบบไดนามิก:
/ *** แหล่งข้อมูลแบบไดนามิก: การสลับแบบไดนามิกระหว่างแหล่งข้อมูลที่แตกต่างกันผ่าน AOP* @return*/ @Bean (name = "DynamicDS1") DataSource Public DataSource () {DynamicDataSource DynamicDataSource = new DynamicDataSource (); // แหล่งข้อมูลเริ่มต้น DynamicDataSource.setDefaultTargetDataSource (DataSource1 ()); // กำหนดค่าแผนที่แหล่งข้อมูลหลายแหล่ง <วัตถุวัตถุ> dsmap = ใหม่ hashmap (5); dsmap.put ("Titan-Master", dataSource1 ()); dsmap.put ("ds2", dataSource2 ()); DynamicDataSource.settargetDatasources (DSMAP); ส่งคืน DynamicDataSource; -คำอธิบายประกอบที่กำหนดเอง @DS ใช้เพื่อระบุแหล่งข้อมูลที่ใช้เมื่อใช้เมื่อเข้ารหัส:
@Retention (RetentionPolicy.Runtime) @Target ({ElementType.Method}) สาธารณะ @Interface ds {ค่าสตริง () ค่าเริ่มต้น "Titan-Master";}เขียนส่วน AOP เพื่อใช้ตรรกะการสลับ:
@ASPACT@ComponentPublic คลาส DynamicDataSourceAspect {@Before ("@Annotation (DS)") โมฆะสาธารณะ beforeswitchds (จุด Joinpoint) {// รับคลาสการเข้าถึงปัจจุบัน <?> className = point.getTarget (). getClass (); // รับเมธอดวิธีการเข้าถึงเมธอด name = point.getSignature (). getName (); // รับประเภทของพารามิเตอร์ของคลาสวิธี [] argclass = ((methodSignature) point.getSignature ()). getParameterTypes (); สตริง dataSource = dataSourceContextholder.default_ds; ลอง {// วิธีการที่เข้าถึงวัตถุเป็นเมธอด = className.getMethod (เมธอดชื่อ ArgClass); // ตรวจสอบว่ามีคำอธิบายประกอบ @DS หรือไม่ถ้า (method.isannotationpresent (ds.class)) {ds Annotation = method.getNanotation (ds.class); // นำชื่อแหล่งข้อมูลออกมาใน dataSource คำอธิบายประกอบ = Annotation.value (); }} catch (exception e) {e.printstacktrace (); } // สลับแหล่งข้อมูล DataSourceContextholder.setDb (DataSource); } @after (" @annotation (ds)") โมฆะสาธารณะ afterswitchds (จุด Joinpoint) {dataSourceContextholder.clearDb (); -หลังจากเสร็จสิ้นการกำหนดค่าข้างต้นการระบุ DynamicDataSource ในการกำหนดค่า SQLSessionFactory ก่อนหน้านี้เพื่อใช้ DynamicDataSource เพื่อสลับแหล่งข้อมูลอย่างมีความสุขในบริการ:
@AutoWired UserAmodelMapper UserAmapper; @DS ("Titan-Master") สตริงสาธารณะ ds1 () {return useramapper.selectbyprimarykey (1) .getName (); } @DS ("ds2") สตริงสาธารณะ ds2 () {return useramapper.selectbyprimarykey (1) .getName (); -สรุป
ด้านบนคือแหล่งสปริงบูต + mybatis หลายแหล่งข้อมูลและวิธีการกำหนดค่าแหล่งข้อมูลแบบไดนามิกที่แนะนำโดยตัวแก้ไข ฉันหวังว่ามันจะเป็นประโยชน์กับคุณ หากคุณมีคำถามใด ๆ โปรดฝากข้อความถึงฉันและบรรณาธิการจะตอบกลับคุณทันเวลา ขอบคุณมากสำหรับการสนับสนุนเว็บไซต์ Wulin.com!