เมื่อเพื่อนร่วมงานของฉันกำลังศึกษา mybatis เขาพบปัญหาที่เมื่อใช้ฟิลด์ประเภทถ่านเป็นเงื่อนไขการสืบค้นเขาไม่สามารถหาข้อมูลและประเภทอื่น ๆ ของพวกเขาก็โอเค
ฐานข้อมูลที่ใช้คือ Oracle ประเภทฟิลด์เงื่อนไขการสืบค้นคือ Char (50) และรหัส Java สอดคล้องกับประเภทสตริง
ต่อมาหลังจากการสอบสวนมันเป็นเพราะใน Oracle หากความยาวเนื้อหาของฟิลด์ประเภทถ่านไม่เพียงพอความยาวจะถูกกรอกในอวกาศโดยอัตโนมัติ หากชื่อฟิลด์ Char (5) ถ้าค่าเป็น SGL ดังนั้น Oracle จะเติมความยาวด้วยช่องว่างโดยอัตโนมัติและค่าสุดท้ายคือ SGL
1. โซลูชัน:
วิธีที่ 1: ก่อนอื่นใช้ฟังก์ชัน TRIM () เพื่อลบช่องว่างทั้งสองด้านของค่าแล้วใช้เป็นแบบสอบถามแบบมีเงื่อนไขเช่น:
เลือก * จากข้อมูลที่ data.name =#{ชื่อ}เปลี่ยนเป็น:
เลือก * จากข้อมูลที่ trim (data.name) =#{ชื่อ}วิธีที่ 2: เปลี่ยนประเภทของฟิลด์ char () เป็นประเภท varchar2 () โดยทั่วไปประเภทของถ่าน () จะใช้เฉพาะเมื่อค่าทั้งหมดมีความยาวเท่ากัน ตัวอย่างเช่นเมื่อใช้ฟิลด์เพศเพื่อเป็นตัวแทนของชายและ 1 ใช้เพื่อเป็นตัวแทนของผู้หญิงถ่าน (1) สามารถใช้งานได้ หากความยาวของค่าไม่ได้รับการแก้ไขจะมีความยาวและสั้นมันจะเป็นการดีที่สุดที่จะไม่ใช้ประเภทถ่าน ()
2. เข้าใจอย่างลึกซึ้ง mybatis ส่งคืนโมฆะ
วางกรอบ MyBatis กลับไปที่แบบสอบถาม JDBC ดั้งเดิมเมื่อใช้ประเภทถ่านของ Oracle เป็นเงื่อนไขในการสืบค้นข้อมูลข้อมูลสามารถพบได้เมื่อค่าเท่ากัน
ตัวอย่างเช่นสร้างตารางทดสอบ:
สร้างตาราง t_user (user_name char (5)); แทรกลงในค่า t_user (user_name) ('sgl'); select '"'||user_name||'"' from t_user ; - ผลลัพธ์การสืบค้นคือ "SGL" จะเห็นได้ว่า Oracle เติมเต็มสองช่องว่างโดยอัตโนมัติ
ข้อมูลสอบถามผ่านวิธีการเตรียมการของ JDBC:
conn = getConnection (); ps = conn.preparestatement ("เลือก * จาก t_user โดยที่ user_name =?"); ps.setstring (1, "sgl"); resultet rs = ps.executeQuery ();ข้อมูลไม่สามารถพบได้ผ่านวิธีการข้างต้นเนื่องจากค่าเงื่อนไขการสืบค้น "SGL" และค่าฐานข้อมูล "SGL" ไม่เท่ากัน
หากค่าคือ "SGL" คุณสามารถค้นหาข้อมูล:
conn = getConnection (); ps = conn.preparestatement ("เลือก * จาก t_user โดยที่ user_name =?"); ps.setstring (1, "sgl"); - เพิ่มสองช่องว่างน้อยกว่า 5 บิตความยาวผลลัพธ์ RS = PS.ExecuteQuery ();หากคุณใช้วิธีการ TRIM () คุณสามารถสอบถามข้อมูลได้เช่น:
conn = getConnection (); ps = conn.prepareStatement ("เลือก * จาก t_user ที่ trim (user_name) =?"); - แรก despace user_name ในฐานข้อมูลจากนั้นเปรียบเทียบ ps.setstring (1, "sgl"); resultet rs = ps.executeQuery ();ตอนนี้กลับไปที่ MyBatis ไฟล์ Mapper ของเพื่อนร่วมงานมีดังนี้:
<select id = "selectByName" resultType = "com.entity.data" parameterType = "java.lang.string"> เลือก * จาก data ที่ data.name =#{ชื่อ} </select>เนื้อหาวิธีหลักคือ:
โมฆะคงที่สาธารณะหลัก (สตริง [] args) {applicationcontext ctx = ใหม่ classpathxmlapplicationContext ("applicationcontext.xml"); DataService D = (DataService) ctx.getBean ("DataServiceImpl"); ข้อมูลข้อมูล = d.selectByName ("SGL"); System.out.println (ข้อมูล);}ในความเป็นจริงโดยการดูซอร์สโค้ดหรือเปลี่ยนบันทึกเป็นระดับการดีบักจะเห็นได้ว่าที่ด้านล่างของ mybatis คำสั่งการสืบค้นจะถูกคอมไพล์ล่วงหน้าโดยใช้การเตรียมการและจากนั้นพารามิเตอร์จะถูกตั้งค่าดังต่อไปนี้บันทึกที่พิมพ์โดย mybatis:
==> การเตรียม: เลือก * จากข้อมูลที่ data.name =?
==> พารามิเตอร์: SGL (สตริง)
จากการค้นหา JDBC ก่อนหน้านี้เรารู้เหตุผลดังนั้นจึงเป็นเรื่องง่ายที่จะเข้าใจปัญหาใน mybatis
นอกจากนี้ภายใต้ MySQL เมื่อค่าของฟิลด์ประเภทถ่านไม่เพียงพอดูเหมือนว่าค่าจะไม่เต็มไปด้วยช่องว่างโดยอัตโนมัติ แม้จะมีสิ่งนี้เมื่อความยาวของค่าไม่ได้รับการแก้ไขก็ไม่แนะนำให้ใช้ประเภทถ่าน
รหัสที่สมบูรณ์สำหรับการสืบค้น JDBC มีดังนี้:
คลาสเครื่องมือ JDBC:
แพ็คเกจ com.songguoliang.url; นำเข้า java.sql.connection; นำเข้า java.sql.drivermanager; นำเข้า java.sql.preparedStatement; นำเข้า java.sql.resultset; นำเข้า java.sql.resultsetmetadata java.util.arraylist; นำเข้า java.util.list; นำเข้า java.util.resourceBundle;/** * คลาสข้อมูลการเชื่อมต่อ JDBC บริสุทธิ์ * @author sgl */คลาสสาธารณะ Purejdbcdao INT Static Private Int Recount = 0; / *** รับการเชื่อมต่อ* @return*/ การเชื่อมต่อแบบคงที่ส่วนตัว getConnection () {การเชื่อมต่อ conn = null; ลอง {class.forName (bundle.getString ("driverclassname")); conn = drivermanager.getConnection (bundle.getString ("url"), bundle.getString ("ชื่อผู้ใช้"), bundle.getString ("รหัสผ่าน")); } catch (classnotFoundException e) {e.printStackTrace (); } catch (sqlexception e) {e.printstacktrace (); } ในที่สุด {ถ้า (null == conn && อีกครั้ง <5) {ลอง {thread.sleep (10,000); } catch (interruptedException e) {e.printStackTrace (); } ใหม่ ++; System.out.println ("ฐานข้อมูล"+ใหม่+"การเชื่อมต่อครั้งที่สอง"); conn = getConnection (); }} return conn; } / ** * ข้อมูลการสืบค้น * @param sql * @return * / รายการคงที่สาธารณะ <String []> Query (String SQL) {list <String []> result = new ArrayList <String []> (); การเชื่อมต่อ conn = null; คำสั่ง stmt = null; ลอง {//system.out.println("lypurejdbcdao] คำสั่งค้นหา: " + sql); conn = getConnection (); stmt = conn.createstatement (); resultset rs = stmt.executeQuery (SQL); ResultsEtMetAdata rsmeta = rs.getMetAdata (); ในขณะที่ (rs.next ()) {int columnnum = rsmeta.getColumnCount (); สตริง [] ฟิลด์ = สตริงใหม่ [columnNum]; สตริง fieldValue = null; สำหรับ (int i = 1; i <= columnNum; i ++) {fieldValue = rs.getString (i); if (fieldValue == null) {fieldValue = ""; } ฟิลด์ [I-1] = FieldValue; } result.add (ฟิลด์); }} catch (sqlexception e) {e.printstacktrace (); } ในที่สุด {ลอง {ถ้า (stmt! = null) {stmt.close (); } if (conn! = null) {conn.close (); }} catch (sqlexception e) {e.printstacktrace (); }} ผลการส่งคืน; } รายการคงที่สาธารณะ <String []> Query (String SQL, รายการ <String> params) {list <String []> result = new ArrayList <String []> (); การเชื่อมต่อ conn = null; PreparedStatement PS = NULL; ลอง {conn = getConnection (); ps = conn.prepareStatement (SQL); สำหรับ (int i = 0; i <params.size (); i ++) {ps.setstring (i+1, params.get (i)); } resultset rs = ps.executeQuery (); ResultsEtMetAdata rsmeta = rs.getMetAdata (); ในขณะที่ (rs.next ()) {int columnnum = rsmeta.getColumnCount (); สตริง [] ฟิลด์ = สตริงใหม่ [columnNum]; สตริง fieldValue = null; สำหรับ (int i = 1; i <= columnNum; i ++) {fieldValue = rs.getString (i); if (fieldValue == null) {fieldValue = ""; } ฟิลด์ [I-1] = FieldValue; } result.add (ฟิลด์); }} catch (sqlexception e) {e.printstacktrace (); } ในที่สุด {ลอง {ถ้า (ps! = null) {ps.close (); } if (conn! = null) {conn.close (); }} catch (sqlexception e) {e.printstacktrace (); }} ผลการส่งคืน; } / ** * เรียกใช้คำสั่ง SQL * @Param SQL * / โมฆะคงที่สาธารณะ Execute (String SQL) {Connection Conn = null; คำสั่ง stmt = null; ลอง {//system.out.println("lypurejdbcdao imptixsql คำสั่ง: " + sql); conn = getConnection (); conn.setautocommit (เท็จ); stmt = conn.createstatement (); stmt.execute (SQL); Conn.Commit (); } catch (sqlexception e) {ลอง {conn.rollback (); } catch (sqlexception e1) {e1.printstacktrace (); } E.PrintStackTrace (); } ในที่สุด {ลอง {ถ้า (stmt! = null) {stmt.close (); } if (conn! = null) {conn.close (); }} catch (sqlexception e) {e.printstacktrace (); -คลาสทดสอบ:
แพ็คเกจ com.songguoliang; นำเข้า java.util.arrays; นำเข้า java.util.list; นำเข้า com.songguoliang.url.purejdbcdao; user_name =? ", array.aslist (" sgl ")); // จำนวนรายการที่พบ: 0 //list<string [string having >list=purejdbcdao.query("Select * จาก t_user ที่ user_name =? ", array.aslist (" sgl ")); // สอบถามจำนวนรายการ: 1 รายการ <string []> list = purejdbcdao.query ("เลือก * จาก t_user ที่ trim (user_name) =?", array.aslist ("sgl")); // สอบถามจำนวนรายการ: 1 System.out.println ("สอบถามจำนวนรายการ:"+list.size ()); -สรุป
ด้านบนเป็นวิธีการแก้ปัญหาที่แนะนำโดยตัวแก้ไขเพื่อแก้ปัญหาของ null เมื่อ mybatis ใช้ฟิลด์ประเภทถ่านเพื่อสอบถามฐานข้อมูล Oracle ฉันหวังว่ามันจะเป็นประโยชน์กับทุกคน หากคุณมีคำถามใด ๆ โปรดฝากข้อความถึงฉันและบรรณาธิการจะตอบกลับทุกคนในเวลา ขอบคุณมากสำหรับการสนับสนุนเว็บไซต์ Wulin.com!