Setelah bekerja keras selama beberapa malam untuk men -debug program, menulis beberapa blog, dan akhirnya menetapkan mekanisme ekspansi untuk konfigurasi mybatis. Meskipun mekanisme ekstensi penting, setidaknya tidak begitu menginspirasi jika tidak ada fungsi ekstensi yang benar -benar praktis. Blog ini akan memberi Anda beberapa contoh ekstensi.
Alasan studi kode sumber ini adalah kompatibilitas antara database Oracle dan MySQL. Misalnya, menggunakan garis vertikal ganda sebagai konektor di Oracle, dan menggunakan fungsi CONDAT di MySQL; Misalnya, menggunakan fungsi decode di Oracle, sementara hanya menggunakan case standar saat di MySQL; Misalnya, hapus tabel bentuk di mana field1 in (pilih field1 tabel bentuk di mana field2 =?) dapat dieksekusi, tetapi pengecualian akan dilemparkan ke dalam mysql, dll.
Mari kita mulai dengan menyelesaikan masalah kompatibilitas ini. Pertama, Anda perlu menambahkan konfigurasi terkait identitas database ke konfigurasi:
<!-Bangun Objek Konfigurasi Sendiri-> <bean id = "mybatisconfig"/> <bean id = "sqlSessionFactory" p: dataSource-ref = "dataSource"> <!-menyuntikkan objek konfigurasi mybatis-> <name properten = "configuration" ref = "mybatacconfig"/<! name = "mapperlocations"> <rrray> <value> classpath*: **/*. sqlmapper.xml </ value> </r array> </property> <!-Konfigurasi identifikasi produk database-> <nama properti = "kata-kata kuncinya"> <bean> <properti nama = "Properties"> <wordsq, my-premain "> <bean> <properti name =" properties "> <katabase-my! MySQL digunakan sebagai databaseid dalam konfigurasi. Kata kunci implementasi asli Mybatis peka kasus. Saya tidak menguji oracle dan db2 -> <prop key = "mysql"> mysql </prop> <prop key = "oracle"> oracle </prop> <prop key = "h2"> h2 </prop> <prop key = "db2"> db2 </prop> </props> </properti> </bean>
1. Masalah konektor
1. Tulis kelas implementasi fungsi konfigurasi SQL
Kelas Publik ConcatsqlConfigFunction Memperluas AbstractSQLConfigFunction {// Level pesanan default diatur dalam kelas induk abstrak @Overridepublic string getName () {return "concat";} @overridepublic string eval (string databaseid, string [] args) {if (args.lengthy <2) {2) throwscepte. argumen. ");} if (" mysql ".equalSignorecase (databaseid)) {return" concat ("+tool.string.join (args,", ")+") ";} else {return tool.string.join (args," || ");}}}2. Daftarkan di blok kode statis kelas Schemahandlers, atau hubungi metode Schemahandlers di kelas inisialisasi startup.
static {// Register Pernyataan HiSlerRegister ("Cache-Ref", New CacherefStateMentHandler ()); register ("cache", cacheestatementhandler baru ()); register ("parameterMap", ParametermAptatementhandler baru (); daftarkan ("resultMap", hasil baru () () () (); "SUFRECTMAP", SUFACTMAPSTATEMENTERHANDHANDERLER () () (); Sqlstatementhandler ()); register ("pilih | masukkan | perbarui | hapus", crudstatementhandler baru ()); // daftarkan namespace skripthandlerregister ("trim", trimscripthandler ("setel (" di mana ", wherescripthandler (); register", "set", "set); Foreachscripthandler ()); register ("if | when", new ifscripthandler ()); register ("pilih", new choosescripthandler ()); // register ("when", new ifscripthandler ()); register ("sebaliknya", NewscripThandler (); regisor ("bind", newenscripthandler (); bind "terypripthandler (" bind "o nEWWISESCRIPTHANDLER (); registerextend ("db", dbstatementhandler baru (), dbscripthandler baru ()); // daftarkan sqlconfigfunctionRegister (decodesqlConfigFunction baru (); register (new concatsqlconfunction ()); // register sqlconfunctionfunction (needfactoryregister (); // register sqlconfunctionFunction (needfactoryregister ();Selain mendaftarkan ConcatsQLConfigFunction, kode di atas juga memiliki beberapa kode pendaftaran lainnya, yang diberikan di sini dan akan dihilangkan di bawah ini.
3. Ubah Konfigurasi SQLMapper
<pilih id = "selectString" resultType = "string"> pilih param_name, $ concat {param_code, param_name} sebagai code_name dari bf_param_enum_def <if test = "null! = paramname dan ''! = paramname"> di mana param_name seperti $ concat {'%', #parname = paramname = param_name like $ concat {'%', #parnam '%'} </if> </ pilih>4. Tulis kelas antarmuka
@RepositoryPublic Interface iExampledao {public String selectString (@param ("paramName") string paramName);}5. Tulis kelas tes
@Runwith (springjunit4classrunner.class) @contextConfiguration (locations = {"classpath: spring/applicationContext.xml"})@componentpublic class exampledaotest {@resourcePrivate IExampledao dao; @testpublic voidselSelSelStrivate {@testpUblic voidSelSelSelStrivate {@testpublic voidselSelSelSelStrivate {@testpublic voidSelSelSelStrivate {@testpublic voidSelSelSelRICTRIVATE ( dao.selectString ("show"); assert.assertequals ("show area", a);}}6. Jalankan sebagai berikut di MySQL dan H2 masing -masing (sesuaikan level log mybatis untuk dilacak)
(1) mysql
20161108 00: 12: 55.235 [main]-[debug] ==> mempersiapkan: pilih param_name, concat (param_code, param_name) sebagai code_name dari bf_param_enum_def di mana param_name seperti concat ('%',?, '%') 20161108 00: 12: 12 :12: 55: 55: 55: 55: 55: '%',? (String) 20161108 00: 12: 55.287 [Main]-[Trace] <== Kolom: Param_name, Code_Name20161108 00: 12: 55.287 [Utama]-[Trace] <== Baris: Area Tampilan, Display_area Display Area20161108 00: 12: 55.2: (Display_area,-Display_area, Area Display_area [Display.(2) H2
20161108 00: 23: 08.348 [main]-[debug] ==> mempersiapkan: pilih param_name, param_code || param_name as code_name dari bf_param_enum_def di mana param_name) (MaINGAN110 (MAINREG]-MAINREG / MAINREG / MAINREG / MAINREG / MAINREG / MAINREG / MAINREG / MAINREG / MAIN / PARAMAN (MAIN / PARAMAN (MAIN / PARAMAN (MAIN / PARAMAN (MAIN / PARAMAN. 00: 23: 08.411 [Utama]-[Trace] <== Kolom: param_name, code_name20161108 00: 23: 08.411 [Utama]-[jejak] <== Baris: Area Tampilan, Display_area Area20161108 00: 23: 08.411 [Main]-[Delayalaaaaa2 Area20161108 00: 23: 08.411 [Main]-[DEBUG] <== 00: 08: 08.411 [DEWUG] [DEWUG] <= 0: 08: 08: 08: 08: 08: 08: 08: 08: 08: 08: 08: 08: 08: 08: 08: 08: 08: 08: 08: 08: 08: 08: 08: 08: 08: 08: 08: 08: 08: 08: 08: 08: 08: 08: 08: 08:
Seperti yang Anda lihat, masalah kompatibilitas konektor telah dipecahkan.
Selain itu, kami juga menemukan bahwa menulis lebih merepotkan saat menggunakan kata kunci seperti, jadi mari kita berikan set baru fungsi konfigurasi SQL:
kelas publik likesqlConfigFunctionFactory mengimplementasikan isqlConfigFunctionFactory {@Overridepublic Collection <Sent iSqlConfunction> getSqlConfigFunctions () {getRightLon.aslist (getLeftLikesQlConfunction (), getRightLonCoigFunction (getLEFTLIKESQLConfunction () ISQLConfigFunction getLeftLikeSQLConfigFunction () {return New AbstractLikeSQLConfigFunction () {@overridepublic string getName () {return "l like";}@overridepublic string eval (string arg) {return "like $ concat {'%',"+arg+arg+";" getRightLikeSQLConfigFunction () {return New AbstractLikeSqlConfIgFunction () {@evertridepublic string getName () {return "r like";}@overrideprotected string eval (string arg) {return "like $ concat {"+arg+", '%'}; getLikeSQLConfigFunction () {return New AbstractLikeSQLConfIgFunction () {@overridepublic getName () {return "like";}@overrideprotected string eval (string arg) {return "like $ concat {'%',"+arg+", '%'}"; AbstractSQLConfigFunction {@Overridepublic String eval (string databaseid, string [] args) {if (args.length! = 1) {throw.throwexception ("Fungsi suka membutuhkan satu dan hanya satu argumen.");} Return eval (args [0]);} protected abstract eval (string eval););Di sini, satu set fungsi konfigurasi SQL didefinisikan, dengan kesamaan kiri, kesamaan kanan dan pencocokan kesamaan tengah, dan fungsi konfigurasi SQL juga dapat bersarang. Oleh karena itu, file konfigurasi SQLMapper disederhanakan untuk:
<pilih id = "selectString" resultType = "string"> pilih param_name, $ concat {param_code, param_name} sebagai code_name dari bf_param_enum_def <if test = "null! = Paramname dan ''! = paramname"> di mana param_name $ like {#{paramname, ''!Hasil menjalankan persis sama.
Jika Anda masih merasa merepotkan, karena param_name dan paramname adalah korespondensi seperti unta, Anda bahkan dapat menambahkan fungsi seperti bidang dan memodifikasi konfigurasi ke
di mana $ field like {#{param_name, jdbctype = varchar}}Jika dikombinasikan dengan kamus data, konfigurasi JDBCTYPE juga dapat secara otomatis dihasilkan:
Where $ field like {#{param_name}}Dalam hal ini, jika ada beberapa parameter, tidak akan ada ambiguitas (atau fungsi konfigurasi yang baru didefinisikan $ suka {} akan digunakan untuk menghilangkan ambiguitas), sehingga beberapa kondisi dapat disederhanakan untuk:
di mana $ likes {#{param_name, param_name2, param_name3}}Tentu saja, ada lebih banyak penyederhanaan yang dapat digali yang tidak lagi hanya dalam ruang lingkup kompatibilitas, jadi kami tidak akan melangkah lebih jauh di sini.
2. Fungsi/kasing decode ... kapan
Fungsi decode di Oracle sangat nyaman, dan sintaksnya adalah sebagai berikut:
Decode (kondisi, nilai 1, nilai pengembalian 1, nilai 2, nilai pengembalian 2, ... nilai n, nilai pengembalian n [, nilai default])
Penulisan standar yang setara:
Kondisi Kasus Saat Nilai 1 Lalu Nilai Pengembalian 1 Kapan Nilai 2 Lalu Nilai Pengembalian 2 ... Saat Nilai N Lalu Nilai Pengembalian N [lain Default] Akhir
Sekarang mari kita terapkan fungsi konfigurasi $ decode:
public class DecodeSqlConfigFunction extends AbstractSqlConfigFunction{@Overridepublic String getName() {return "decode";}@Overridepublic String eval(String databaseId, String[] args) {if(args.length < 3){Throw.throwException("the decode function requires at least three arguments.");}if("h2".equalsIgnoreCase(databaseId)){//When testing, use h2 instead of oracle, and modify it to oraclereturn in the official program "DECODE("+Tool.STRING.join(args, ",")+")";}else{StringBuffer sb = new StringBuffer();sb.append("CASE ") .Pelpend (args [0]); int i = 2, l = args.length; for (; i <l; i = i+2) {sb.append (" when "). lampiran (args [i-1]). Append (" lalu tidak ada (args [i]);} if (i == l) {"tidak ada. SB.Append ("else") .Append (args [l-1]);} sb.append ("end"); return sb.tostring ();}}}Kemudian gunakan Schemahandlers untuk mendaftar dan memodifikasi konfigurasi di SQLMapper:
<pilih id = "selectString" resultType = "string"> pilih param_name, $ decode {#{paramname}, '1', 'a', '2', 'b', 'c'} sebagai decode_test dari bf_param_enum_def <if test = "null! jdbctype = varchar}} </if> </select>Tesnya adalah sebagai berikut:
(1) di H2 (ganti oracle dengan H2)
20161108 06: 53: 29.747 [main]-[debug] ==> mempersiapkan: pilih param_name, decode (?, '1', 'a', '2', 'b', 'c') sebagai decode_test dari bf_param_enum_def di mana param_name seperti '%' ||
(2) Di MySQL
20161108 06: 50: 55.998 [Main]-[Debug] ==> Mempersiapkan: Pilih Param_Name, case? Kapan '1' lalu 'a' ketika '2' lalu 'b' else 'c' berakhir sebagai decode_test dari bf_param_enum_def di mana param_name seperti '%' ||? || '%'
Di atas adalah pengantar terperinci untuk ekstensi dan aplikasi konfigurasi SQLMapper di mybatis yang diperkenalkan kepada Anda oleh editor (1). Saya harap ini akan membantu Anda. Jika Anda memiliki pertanyaan, silakan tinggalkan saya pesan dan editor akan membalas Anda tepat waktu. Terima kasih banyak atas dukungan Anda ke situs web Wulin.com!