โดยทั่วไปแล้วการปรับเปลี่ยนซอร์สโค้ดของเฟรมเวิร์กนั้นมีความเสี่ยงอย่างยิ่งและไม่แก้ไขเว้นแต่จะจำเป็นอย่างยิ่ง แต่วันนี้ฉันได้สร้างคลาส SQLSessionFactoryBean อย่างระมัดระวังโดย MyBatis อย่างเป็นทางการซึ่งรวมเข้ากับฤดูใบไม้ผลิ ก่อนอื่นมีความคิดในการทดลองและข้อผิดพลาดและประการที่สองมันมีความต้องการที่สมจริง
ให้ฉันอธิบายสองจุดก่อน:
โดยทั่วไปแล้วการปรับโครงสร้างหมายถึงการเพิ่มประสิทธิภาพรหัสโดยไม่ต้องเปลี่ยนฟังก์ชั่น แต่การปรับโครงสร้างที่กล่าวถึงในบทความนี้ยังรวมถึงการเพิ่มฟังก์ชั่น
แพ็คเกจ Jar หลัก (เวอร์ชัน) ที่ใช้ในบทความนี้: ฤดูใบไม้ผลิ-*-4.3.3.release.jar, mybatis-3.4.1.jar, mybatis-spring-1.3.0.jar
เริ่มต้นด้วยการรวม Mybatis และฤดูใบไม้ผลิ
1. รวม mybatis และฤดูใบไม้ผลิ
<bean id = "sqlsessionfactory" p: dataSource-ref = "dataSource" p: configlocation = "classpath: mybatis/mybatis-config.xml"> <property name = "mapperlocations"
คลาสที่สำคัญของการรวมเป็น org.mybatis.spring.sqlsessionfactorybean ซึ่งเป็นถั่วโรงงานที่ใช้ในการสร้าง mybatis ทั่วโลกเซสชันโรงงาน SQLSessionFactory (นั่นคือถั่วที่สร้างขึ้นในโรงงาน เทียบเท่ากับการเชื่อมต่อ)
โดยที่คุณสมบัติ (กำหนดค่าโดยใช้ p namespace หรือองค์ประกอบของเด็กอสังหาริมทรัพย์):
DataSource เป็นแหล่งข้อมูลซึ่งสามารถกำหนดค่าได้โดยใช้ DBCP, C3P0, DRUID, JNDI-Lookup และวิธีอื่น ๆ
การกำหนดค่าเป็นการกำหนดค่าทั่วโลกของเอ็นจิ้น mybatis ที่ใช้ในการปรับเปลี่ยนพฤติกรรมของ mybatis
MapperLocations เป็นไฟล์การกำหนดค่าสคริปต์ SQLMapper (โหมด) ที่ MyBatis จำเป็นต้องโหลด
แน่นอนว่ามีคุณลักษณะอื่น ๆ อีกมากมายดังนั้นฉันจะไม่ยกตัวอย่างที่นี่
2. ทำไมต้องสร้างใหม่
1. การเพิ่มประสิทธิภาพซอร์สโค้ด
ฟังก์ชั่นของ SQLSessionFactoryBean คือการสร้าง SQLSessionFactory ลองดูที่วิธีนี้ (SQLSessionFactoryBean.java Line 384-538): /*** สร้างอินสแตนซ์ {@code sqlsessionfactory}} ** การใช้งานเริ่มต้นใช้ mybatis มาตรฐาน {@code xmlconfigbuilder ได้รับการระบุการกำหนดค่า {@link} โดยตรง (ไม่มีไฟล์ config) ** @return sqlsessionfactory* @throws ioexception หากโหลดไฟล์ config ล้มเหลว*/การป้องกัน sqlsessionfactory buildsqlsessionFactory () null) {configuration = this.configuration; if (configuration.getVariables () == null) {configuration.setVariables (this.configurationProperties);} อื่นถ้า (this.configurationProperties! null) {xmlconfigbuilder = ใหม่ xmlconfigbuilder (this.configlocation.getInputStream (), null, this.configurationProperties) การกำหนดค่า = xmlConfigBuilder.getConfiguration ()}} หรือ 'การกำหนดค่า' ไม่ได้ระบุโดยใช้การกำหนดค่า mybatis เริ่มต้น ");} การกำหนดค่า = การกำหนดค่าใหม่ (); configuration.setVariables (this.configurationProperties);} ถ้า (this.objectFactory! {configuration.setObjectWrapperFactory (this.ObjectWrapperFactory);} ถ้า (this.vfs! = null) {configuration.setvfsimpl (this.vfs);} ถ้า (haslength (this.typealiasespackage)) {string [] TokenizetOstringArray (this.typealiasespackage, configurableapplicationContext.config_location_delimiters); สำหรับ (String packagetoscan: typealiaspackageArray) {configuration.getTypealiasregistry (). registeraliases (packagetoscan, typealiasessupertype == null? object.class: typealiasessupertype); ถ้า (logger.isdebugenabled () นามแฝง ");}}} ถ้า (! isempty (this.typealiases)) {สำหรับ (คลาส <?> typealias: this.typealiases) {configuration.getTypealiasregistry (). registeralias (typealias); if (logger.isdebugenabled "" ");}}} ถ้า (! isempty (this.plugins)) {สำหรับ (ปลั๊กอิน interceptor: this.plugins) {configuration.addinterceptor (ปลั๊กอิน); ถ้า (logger.isdebugenabled () {logger.debug (haslength (this.typehandlerspackage)) {string [] typeHandlerspackageArray = tokenizetOstringArray (this.typehandlerspackage, configurableapplicationContext.config_location_delimiters); สำหรับ (String packagetoscan: typeHandlerspackageArray) {configuration.getTypeHandlerRegistry (). ลงทะเบียน (packagetoscan); ถ้า (logger.isdebugenabled ()) {logger.debug ("แพคเกจสแกน: '" + packagetoscan + " (! isempty (this.typehandlers)) {สำหรับ (typehandler <?> typeHandler: this.typehandlers) {configuration.getTypepehandlerRegistry (). register (typeHandler); ถ้า (logger.isdebugenabled ()) {logger.debug ( (this.databaseidprovider! = null) {// fix #64 ตั้งค่า databaseid ก่อนที่จะแยกวิเคราะห์ maplstry {configuration.setDatabaseid (this.databaseidprovider.getDatabaseid (this.datasource)); e);}} ถ้า (this.cache! = null) {configuration.addcache (this.cache);} ถ้า (xmlconfigbuilder! = null) {ลอง {xmlconfigbuilder.parse () (logger.isdebugenabled () "" ");}} catch (Exception Ex) {โยน nestedioexception ใหม่ (" ล้มเหลวในการแยกวิเคราะห์ทรัพยากรการกำหนดค่า: " + this.configlocation, ex);} ในที่สุด {errorcontext.instance (). reset ()}} ถ้า (this.transactionFactory == null) สิ่งแวดล้อม (สิ่งนี้สภาพแวดล้อม this.transactionFactory, this.datasource)); ถ้า (! isempty (this.mapperlocations)) {สำหรับ (ทรัพยากร mapperlocation: this.mapperlocations) {ถ้า (mapperlocation == null) {ดำเนินการต่อ; xmlmapperbuilder (mapperlocation.getInputStream (), การกำหนดค่า, mapperlocation.toString (), configuration.getSqlFragments ()); xmlmapperbuilder.parse ()} catch (ยกเว้น e) {errorContext.Instance (). reset ();} ถ้า (logger.isdebugenabled ()) {logger.debug ("ไฟล์ mapper ที่แยกวิเคราะห์: '" mapperlocation + "'");}}}}} พบ ");}} ส่งคืน this.sqlsessionfactorybuilder.build (การกำหนดค่า);}แม้ว่า mybatis เป็นกรอบการคงอยู่ของเลเยอร์ที่ยอดเยี่ยม แต่จริง ๆ แล้วรหัสนี้ไม่ค่อยดีนักและมีพื้นที่มากมายสำหรับการสร้างใหม่และการเพิ่มประสิทธิภาพ
2. การขยายการทำงาน
(1) ใช้สคีมาเพื่อตรวจสอบ sqlmapper
<!-โหมด dtd-> <? xml version = "1.0" การเข้ารหัส = "utf-8"?> <! doctype mapper สาธารณะ "-// mybatis.org//dtd mapper 3.0 // en" "http://mybatis.org/dtd/mybatis-3-mapper. namespace = "org.dysd.dao.mybatis.config.iexampledao"> </mapper> <!-โหมดสคีมา-> <? xml เวอร์ชัน = "1.0" การเข้ารหัส = "utf-8" xmlns = "http://dysd.org/schema/sqlmapper" xsi: schemalocation = "http://dysd.org/schema/sqlmapper http://dysd.org/schema/sqlmapper.xsd "namespace =" org.dysd.dao.mybatis.config.iexampledao "> </mapper>
เมื่อมองแวบแรกการใช้สคีมานั้นซับซ้อนกว่า แต่ถ้ารวมกับ IDE การแจ้งเตือนอัตโนมัติของการใช้สคีมานั้นเป็นมิตรมากขึ้นและข้อมูลการตรวจสอบจะชัดเจนขึ้น ในเวลาเดียวกันมันยังเปิดหน้าต่างสำหรับนักพัฒนาอื่น ๆ เพื่อให้พวกเขาสามารถปรับแต่งเนมสเปซตามเนมสเปซที่มีอยู่เช่นการแนะนำแท็ก <OGNL> โดยใช้การแสดงออกของ OGNL เพื่อกำหนดค่าคำสั่ง SQL ฯลฯ
(2) ปรับแต่งการกำหนดค่า SQLSessionFactoryBean ได้ให้พารามิเตอร์เพิ่มเติมสำหรับการกำหนดค่าที่กำหนดเอง แต่ก็ยังเป็นไปได้ที่จะต้องใช้การตั้งค่าส่วนบุคคลมากขึ้นเช่น:
A. ตั้งค่าประเภทผลลัพธ์เริ่มต้น สำหรับ <elect> องค์ประกอบที่ไม่ได้ตั้งค่า ResultType และ ResultMap คุณสามารถตั้งค่าประเภทผลตอบแทนเริ่มต้นเป็นแผนที่หลังจากการแยกวิเคราะห์ซึ่งทำให้การกำหนดค่าของ SQLMapper ง่ายขึ้น
<!-ก่อนเรียบง่าย-> <select id = "เลือก" resultType = "แผนที่"> เลือก * จาก table_name โดยที่ field1 = #{field1, jdbcType = varchar} </select> <!-หลังจาก simplified-> <select id = "เลือก"B. ขยายการวิเคราะห์พารามิเตอร์ดั้งเดิมของ MyBatis การใช้การแยกวิเคราะห์แบบดั้งเดิมคือ DefaultParameterHandler การใช้งานนี้สามารถสืบทอดและขยายได้ ตัวอย่างเช่นสำหรับนิพจน์คุณสมบัตินำหน้าโดย Spel: ใช้ Spel เพื่อประเมินค่า
(3) สำหรับส่วนขยายอื่น ๆ โปรดดูบล็อกก่อนหน้าของผู้แต่งเกี่ยวกับส่วนขยาย mybatis
3. ความเป็นไปได้ของการสร้างใหม่
(1) ในแง่ของขอบเขตของรหัสอิทธิพล
ด้านล่างนี้เป็นโครงสร้างการสืบทอดของ sqlsessionfactorybean
จากนี้เราจะเห็นได้ว่าระบบสืบทอด SQLSessionFactoryBean ไม่ซับซ้อนและไม่ได้รับมรดกคลาสแม่อื่น ๆ มันใช้เพียงสามอินเทอร์เฟซในฤดูใบไม้ผลิ (EventListener ใน JDK เป็นเพียงโลโก้) นอกจากนี้ SQLSessionFactoryBean มีจุดมุ่งหมายเพื่อผู้ใช้พัฒนาปลายทางโดยไม่มีคลาสย่อยและไม่มีคลาสอื่นที่เรียกมันดังนั้นจึงมีขนาดเล็กมากในแง่ของขอบเขตของผลกระทบของรหัส
(2) ในการใช้งานการสร้างใหม่คุณสามารถสร้าง schemasqlsessionfactorybean ใหม่จากนั้นรหัสคัดลอก SQLSessionFactoryBean ได้อย่างสมบูรณ์ในตอนต้นแก้ไขชื่อแพ็คเกจและชื่อคลาสแล้วใช้สิ่งนี้เป็นพื้นฐานสำหรับการสร้างใหม่ นี่ค่อนข้างง่าย
(3) ในแอปพลิเคชันแบบรวมคุณจะต้องแก้ไขแอตทริบิวต์คลาสในการกำหนดค่าและสปริงแบบรวม
ข้างต้นคือการปรับโครงสร้างของ SQLSessionFactoryBean ที่รวมเข้ากับ mybatis และฤดูใบไม้ผลิที่แนะนำให้คุณรู้จัก ฉันหวังว่ามันจะเป็นประโยชน์กับคุณ หากคุณมีคำถามใด ๆ โปรดฝากข้อความถึงฉันและบรรณาธิการจะตอบกลับคุณทันเวลา ขอบคุณมากสำหรับการสนับสนุนเว็บไซต์ Wulin.com!