หลังจากทำงานอย่างหนักเป็นเวลาหลายคืนในการดีบักโปรแกรมเขียนบล็อกหลายบล็อกและในที่สุดก็สร้างกลไกการขยายตัวสำหรับการกำหนดค่า MyBatis แม้ว่ากลไกการขยายจะมีความสำคัญอย่างน้อยก็ไม่ได้สร้างแรงบันดาลใจหากไม่มีฟังก์ชั่นการขยายที่ใช้งานได้จริง บล็อกนี้จะให้ตัวอย่างของส่วนขยาย
เหตุผลสำหรับการศึกษาซอร์สโค้ดนี้คือความเข้ากันได้ระหว่างฐานข้อมูล Oracle และ MySQL ตัวอย่างเช่นการใช้เส้นแนวตั้งคู่เป็นตัวเชื่อมต่อใน Oracle และใช้ฟังก์ชั่น concat ใน MySQL; ตัวอย่างเช่นการใช้ฟังก์ชั่นการถอดรหัสใน Oracle ในขณะที่ใช้กรณีมาตรฐานเมื่ออยู่ใน MySQL เท่านั้น ตัวอย่างเช่นการลบตารางฟอร์มที่ Field1 ใน (เลือกตารางฟิลด์ 1 ตารางที่ field2 =?) สามารถดำเนินการได้ แต่ข้อยกเว้นจะถูกโยนลงใน MySQL ฯลฯ
เริ่มต้นด้วยการแก้ปัญหาความเข้ากันได้เหล่านี้ ก่อนอื่นคุณต้องเพิ่มการกำหนดค่าที่เกี่ยวข้องกับข้อมูลประจำตัวฐานข้อมูลลงในการกำหนดค่า:
<!-สร้างวัตถุการกำหนดค่าด้วยตัวเอง-> <bean id = "mybatisconfig"/> <bean id = "sqlsessionfactory" p: dataSource-ref = "dataSource"> <! name = "mapperlocations"> <array> <value> classpath*: **/*. sqlmapper.xml </value> </array> </คุณสมบัติ> <!-การกำหนดค่าการระบุผลิตภัณฑ์ฐานข้อมูล-> <property name = "databaseidprovider"> <bean> MySQL ใช้เป็น databaseID ในการกำหนดค่า คำหลักในการใช้งาน MyBatis Native มีความละเอียดอ่อน ฉันไม่ได้ทดสอบ Oracle และ DB2 -> <prop key = "mysql"> mysql </prop> <prop key = "Oracle"> Oracle </prop> <prop key = "H2"> H2 </prop> <prop key = "db2"> db2 </prop>
1. ปัญหาตัวเชื่อมต่อ
1. การเขียนฟังก์ชั่นการกำหนดค่า SQL การกำหนดค่าคลาส
คลาสสาธารณะ concatsqlconfigfunction ขยายบทคัดย่อ abstractsqlconfigfunction {// ระดับคำสั่งเริ่มต้นถูกตั้งค่าในคลาส Parent Parent @OverridePublic String getName () {return "concat";} @verridepublic rever (String DatabaseId, String [] args) อาร์กิวเมนต์ ");} ถ้า (" mysql ".equalsignorecase (databaseid)) {return" concat ("+tool.string.join (args,", ",")+")";2. ลงทะเบียนในบล็อกรหัสแบบคงที่ของคลาส Schemahandlers หรือโทรหาวิธี Schemahandlers ในคลาสการเริ่มต้นเริ่มต้น
Static {// register attementLandlerRegister ("cache-ref", ใหม่ cacherefstatementhandler ()); ลงทะเบียน ("แคช", ใหม่ cachestatementhandler ()); ลงทะเบียน ("parametermap", parametermapstatementhandler (); sqlstatementhandler ()); ลงทะเบียน ("เลือก | แทรก | อัปเดต | ลบ", ใหม่ crudstatementhandler ()); // ลงทะเบียนเริ่มต้น Namespace ScripthandlerRegister ("trim", trimscripthandler (); foreachscripthandler ()); ลงทะเบียน ("ถ้า | เมื่อ", ใหม่ ifscripthandler ()); ลงทะเบียน ("เลือก", choosescripthandler ใหม่ ()); // register ("เมื่อ", ifscripthandler (); dbstatementhandler (), dbscripthandler ใหม่ ()); // ลงทะเบียน sqlconfigfunction register (decodesqlconfigfunction ()); ลงทะเบียน (ใหม่ concatsqlconfigfunction ());นอกเหนือจากการลงทะเบียน concatsqlconfigfunction แล้วรหัสข้างต้นยังมีรหัสการลงทะเบียนอื่น ๆ ซึ่งได้รับที่นี่และจะถูกละเว้นด้านล่าง
3. แก้ไขการกำหนดค่า SQLMapper
<select id = "selectString" resultType = "string"> เลือก param_name, $ concat {param_code, param_name} เป็น code_name จาก bf_param_enum_def <ถ้า test = "null! = paramname และ ''! = paramname"> '%'} </if> </select>4. คลาสอินเตอร์เฟสเขียน
@RepositoryPublic อินเตอร์เฟส iexampledao {สตริงสาธารณะ SelectString (@param ("paramname") สตริง paramname);}5. เขียนคลาสทดสอบ
@runwith (springjunit4classrunner.class) @contextconfiguration (locations = {"classpath: Spring/ApplicationContext.xml"})@componentPublic Class Exampledaotest {@ResourcePrivate IExampleDao dao; dao.selectstring ("show"); assert.assertequals ("พื้นที่แสดง", a);}}6. เรียกใช้ดังนี้ใน MySQL และ H2 ตามลำดับ (ปรับระดับบันทึก myBatis เป็นติดตาม)
(1) MySQL
20161108 00: 12: 55,235 [Main]-[debug] ==> การเตรียม: เลือก param_name, concat (param_code, param_name) เป็น code_name จาก bf_param_enum_def ที่ param_name ชอบ concat ('%',? (สตริง) 20161108 00: 12: 55,287 [Main]-[Trace] <== คอลัมน์: param_name, code_name20161108 00: 12: 55,287 [Main]-[trace] <== แถว: แสดงพื้นที่แสดงผล(2) H2
20161108 00: 23: 08,348 [Main]-[debug] ==> การเตรียม: เลือก param_name, param_code || param_name เป็น code_name จาก bf_param_enum_def ที่ param_name เช่น '%' || (สตริง) 20161108 00: 23: 08,411 [Main]-[Trace] <== คอลัมน์: param_name, code_name20161108 00: 23: 08,411 [Main]-[Trace] <== Row: Display area, Display_area พื้นที่แสดงผล
อย่างที่คุณเห็นปัญหาความเข้ากันได้ของตัวเชื่อมต่อได้รับการแก้ไขแล้ว
นอกจากนี้เรายังพบว่าการเขียนมีปัญหามากขึ้นเมื่อใช้คำหลักเช่นขอให้ชุดฟังก์ชันการกำหนดค่า SQL ใหม่:
คลาสสาธารณะ likesqlconfigfunctionfactory asqlconfigfunctionfactory {@overridepublic collection <isqlconfigfunction> getSqlconfigfunctions () {return array.aslist (getleflikesqlconfigfunction () getLikesqlConfigfunction ());} ส่วนตัว isqlconfigfunction getlefletlikesqlconfigfunction () {ส่งคืน AbstractLikesqlConfigFunction () {@@entridepublic string getName () {return llike "; $ concat {'%', "+arg+"} ";}};} ส่วนตัว isqlconfigfunction getriveLikesqlconfigfunction () {return abstractlikesqlconfigfunction (@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@rewant reving reving reving} $concat{"+arg+", '%'}";}};} private ISqlConfigFunction getLikeSqlConfigFunction(){return new AbstractLikeSqlConfigFunction(){@Overridepublic String getName() {return "like";}@Overrideprotected String eval(String arg) {return "LIKE $ concat {'%', "+arg+", '%'} ";}};} คลาสนามธรรมส่วนตัว Abstractlikesqlconfigfunction ขยายบทคัดย่อ abstractsqlconfigfunction {@overridepublic string eval อาร์กิวเมนต์ ");} return eval (args [0]);} การป้องกันสตริงนามธรรมการประเมิน (สตริง arg);}}ที่นี่ชุดของฟังก์ชั่นการกำหนดค่า SQL ถูกกำหนดโดยมีความคล้ายคลึงกันซ้ายความคล้ายคลึงกันขวาและการจับคู่ความคล้ายคลึงกันกลางและฟังก์ชั่นการกำหนดค่า SQL สามารถซ้อนกันได้ ดังนั้นไฟล์การกำหนดค่าของ SQLMapper จึงง่ายขึ้นถึง:
<select id = "selectString" resultType = "string"> เลือก param_name, $ concat {param_code, param_name} เป็น code_name จาก bf_param_enum_def <ถ้า test = "null! = paramname และ '! = paramname">ผลลัพธ์การรันเหมือนกันทุกประการ
หากคุณยังพบว่ามันลำบากเนื่องจาก param_name และ paramname เป็นจดหมายโต้ตอบเหมือนอูฐคุณยังสามารถเพิ่มฟังก์ชั่นที่เหมือนฟิลด์และแก้ไขการกำหนดค่าเป็น
โดยที่ $ fieldlike {#{param_name, jdbctype = varchar}}}หากรวมกับพจนานุกรมข้อมูลการกำหนดค่า JDBCType สามารถสร้างได้โดยอัตโนมัติ:
โดยที่ $ fieldlike {#{param_name}}ในกรณีนี้หากมีพารามิเตอร์หลายตัวจะไม่มีความคลุมเครือ (หรือฟังก์ชั่นการกำหนดค่าที่กำหนดใหม่ $ likes {} จะถูกใช้เพื่อกำจัดความคลุมเครือ) ดังนั้นหลายเงื่อนไขสามารถทำให้ง่ายขึ้น:
โดยที่ $ likes {#{param_name, param_name2, param_name3}}}แน่นอนว่ามีการทำให้เข้าใจง่ายมากขึ้นซึ่งไม่ได้อยู่ในขอบเขตของความเข้ากันได้อีกต่อไปดังนั้นเราจะไม่ไปที่นี่อีกต่อไป
2. ถอดรหัสฟังก์ชั่น/เคส ... เมื่อไหร่
ฟังก์ชั่นถอดรหัสใน Oracle นั้นสะดวกมากและไวยากรณ์มีดังนี้:
DECODE (เงื่อนไข, ค่า 1, ค่าส่งคืน 1, ค่า 2, ค่าส่งคืนค่า 2, ... ค่า n, ค่าส่งคืน n [, ค่าเริ่มต้น])
การเขียนมาตรฐานของเทียบเท่า:
เงื่อนไขกรณีเมื่อค่า 1 จากนั้นส่งคืนค่า 1 เมื่อค่า 2 จากนั้นส่งคืนค่า 2 ... เมื่อค่า n จากนั้นจะส่งคืนค่า n [อื่น ๆ เริ่มต้น] สิ้นสุด
ตอนนี้เรามาใช้ฟังก์ชันการกำหนดค่า $ Decode:
Public Class DecodesqlConfigfunction ขยายบทคัดย่อ abstractsqlconfigfunction {@overridepublic String getName () {return "decode";}@verridepublic string eval (สตริง databaseid, string [] args) {ถ้า args.length <3) อาร์กิวเมนต์ ");} ถ้า (" h2 ".equalsignorecase (databaseid)) {// เมื่อทำการทดสอบใช้ H2 แทน Oracle และแก้ไขเป็น oraclereturn ในโปรแกรมอย่างเป็นทางการ" ถอดรหัส ("+tool.string.oin (args,", ")+") "; ") .append (args [0]); int i = 2, l = args.length; สำหรับ (; i <l; i = i+2) {sb.append (" เมื่อ "). append (args [i-1]). ผนวก (" แล้ว " sb.append ("Else") .append (args [l-1]);} sb.append ("end"); return sb.toString ();}}}จากนั้นใช้ schemahandlers เพื่อลงทะเบียนและแก้ไขการกำหนดค่าใน SQLMapper:
<select id = "selectString" resultType = "string"> เลือก param_name, $ decode {#{paramname}, '1', 'a', '2', 'b', 'c'} เป็น decode_test จาก bf_param_enum_def <ถ้าทดสอบ = "null! = paramname jdbcType = varchar}} </if> </select>การทดสอบมีดังนี้:
(1) ใน H2 (แทนที่ Oracle ด้วย H2)
20161108 06: 53: 29,747 [Main]-[debug] ==> การเตรียม: เลือก param_name, decode (?, '1', 'a', '2', 'b', 'c') เป็น decode_test จาก bf_param_enum_def
(2) ใน mysql
20161108 06: 50: 55,998 [Main]-[debug] ==> การเตรียม: เลือก param_name, case? เมื่อ '1' จากนั้น 'เมื่อ' 2 'แล้ว' B 'ELSE' C 'สิ้นสุดเป็น decode_test จาก bf_param_enum_def โดยที่ param_name ชอบ'%'||? ||'%'
ข้างต้นเป็นการแนะนำรายละเอียดเกี่ยวกับการขยายและการประยุกต์ใช้การกำหนดค่า SQLMapper ใน MyBatis แนะนำให้คุณทราบโดย Editor (1) ฉันหวังว่ามันจะเป็นประโยชน์กับคุณ หากคุณมีคำถามใด ๆ โปรดฝากข้อความถึงฉันและบรรณาธิการจะตอบกลับคุณทันเวลา ขอบคุณมากสำหรับการสนับสนุนเว็บไซต์ Wulin.com!