วิธีการในตัวสำหรับ Mapper
เลเยอร์โมเดลคือคลาสเอนทิตีซึ่งสอดคล้องกับตารางของฐานข้อมูล เลเยอร์คอนโทรลเลอร์เป็น servlet ซึ่งส่วนใหญ่รับผิดชอบในการควบคุมกระบวนการโมดูลธุรกิจการเรียกใช้วิธีการบริการอินเทอร์เฟซและใน struts2 เป็นการดำเนินการ ชั้นบริการส่วนใหญ่ทำการตัดสินเชิงตรรกะและเลเยอร์ DAO คือเลเยอร์การเข้าถึงข้อมูลซึ่งเชื่อมต่อกับฐานข้อมูล สำหรับ Mapper ไฟล์การแมป Mapper จะใช้ในชั้น DAO
นี่คือคำอธิบายของวิธีการของ Mapper ในตัว:
1. CountByExample ===> สอบถามปริมาณตามเงื่อนไข
int countByExample (ตัวอย่างตัวอย่าง); // ต่อไปนี้เป็นรายการเคสที่สมบูรณ์ ตัวอย่าง USEREXAMPLE = ใหม่ USEREXAMPLE (); เกณฑ์เกณฑ์ = example.createCriteria (); Criteria.andusernameequalto ("Joe"); int count = userdao.countByExample (ตัวอย่าง); เทียบเท่ากับ: เลือกนับ (*) จากผู้ใช้ที่ชื่อผู้ใช้ = 'Joe'
2. DELETEBYEXAMPLE ===> ลบหลายรายการตามเงื่อนไข
int deleteByExample (ตัวอย่าง Accountexample); // ต่อไปนี้เป็นกรณีตัวอย่างที่สมบูรณ์ตัวอย่างตัวอย่าง = new UserExample (); เกณฑ์เกณฑ์ = example.createCriteria (); Criteria.andusernameequalto ("Joe"); userdao.deleteByexample (ตัวอย่าง); เทียบเท่ากับ: ลบจากผู้ใช้ที่ชื่อผู้ใช้ = 'Joe' 3. DELETEBYPRIMARYKEY ===> ลบรายการเดียวตามเงื่อนไข
int deleteByPrimaryKey (ID จำนวนเต็ม); userdao.deleteByPrimaryKey (101);
เทียบเท่ากับ:
ลบจากผู้ใช้โดยที่ id = 101
4. แทรก ===> แทรกข้อมูล
int แทรก (บันทึกบัญชี); // ต่อไปนี้เป็นผู้ใช้กรณีที่สมบูรณ์ = ผู้ใช้ใหม่ (); //user.setid(101); user.setUserName ("ทดสอบ"); user.setPassword ("123456") user.setEmail ("[email protected]"); userdao.insert (ผู้ใช้);เทียบเท่ากับ:
แทรกลงในผู้ใช้ (รหัส, ชื่อผู้ใช้, รหัสผ่าน, อีเมล) ค่า (101, 'ทดสอบ', '123456', '[email protected]');
5. InsertSelective ===> แทรกข้อมูล
int insertselective (บันทึกบัญชี);
6. SelectByExample ===> ข้อมูลสอบถามตามเงื่อนไข
รายการ <account> SelectByExample (ตัวอย่าง Accountexample); // ต่อไปนี้เป็นกรณีตัวอย่างตัวอย่างที่สมบูรณ์ = new UserExample (); เกณฑ์เกณฑ์ = example.createCriteria (); Criteria.andusernameeQualto ("Joe"); Criteria.andusernameisnull (); set.set.set.set. userdao.selectByexample (ตัวอย่าง); เทียบเท่า: เลือก * จากผู้ใช้ที่ชื่อผู้ใช้ = 'Joe' และชื่อผู้ใช้เป็นคำสั่งซื้อตามชื่อผู้ใช้ ASC, อีเมล desc // หมายเหตุ: ไฟล์ userexample.java ที่สร้างโดย ibator มีเกณฑ์ชั้นเรียนภายในแบบคงที่ มีหลายวิธีในเกณฑ์ส่วนใหญ่เพื่อกำหนดเงื่อนไขการสืบค้นหลังจากคำสั่ง SQL ที่ไหน7. SELECTBYPRIMARYKEY ===> ข้อมูลสอบถามตามคีย์หลัก
บัญชี SelectByPrimaryKey (ID จำนวนเต็ม); // เทียบเท่ากับการเลือก * จากผู้ใช้ที่ id = ตัวแปร id
8. UpdateByExamplesElective ===> ฟิลด์อัปเดตที่มีค่าไม่เป็นโมฆะตามเงื่อนไข
intupterbyexampleselective (@param ("บันทึก") บันทึกบัญชี @param ("ตัวอย่าง") ตัวอย่าง Accountexample); // ต่อไปนี้เป็นรายการกรณีที่สมบูรณ์ตัวอย่างตัวอย่างตัวอย่าง = new UserExample (); เกณฑ์เกณฑ์ = example.createCriteria (); Criteria.andusernameequalto ("Joe"); ผู้ใช้ผู้ใช้ = ผู้ใช้ใหม่ (); user.setPassword ("123"); userdao.updateByPrimaryKeySelective (ผู้ใช้, ตัวอย่าง); เทียบเท่ากับ: อัปเดตรหัสผ่านผู้ใช้ = '123' โดยที่ชื่อผู้ใช้ = 'Joe'
9. UpdateByExamplesElective ===> อัปเดตตามเงื่อนไข
IntupertuedByExample (@Param ("บันทึก") บันทึกบัญชี @Param ("ตัวอย่าง") ตัวอย่าง Accountexample);10. UpdateByPrimaryKeySelective ===> อัปเดตตามเงื่อนไข
intupterbyPrimaryKeySelective (บันทึกบัญชี); // ต่อไปนี้เป็นผู้ใช้เคสผู้ใช้ที่สมบูรณ์ = ผู้ใช้ใหม่ (); user.setId (101); user.setPassword ("Joe"); userdao.updateByPrimaryKeySelective (ผู้ใช้);เทียบเท่ากับ:
อัปเดตชุดผู้ใช้รหัสผ่าน = 'Joe' โดยที่ id = 101
intupterbyPrimaryKeySelective (บันทึกบัญชี); // ต่อไปนี้เป็นผู้ใช้เคสผู้ใช้ที่สมบูรณ์ = ผู้ใช้ใหม่ (); user.setId (101); user.setPassword ("Joe"); userdao.updateByPrimaryKeySelective (ผู้ใช้);เทียบเท่ากับ: อัปเดตรหัสผ่านผู้ใช้ = 'Joe' โดยที่ id = 101
11. UpdateByPrimaryKey ===> กดปุ่มหลักเพื่ออัปเดต
intupterbyPrimaryKey (บันทึกบัญชี); // ต่อไปนี้เป็นผู้ใช้กรณีที่สมบูรณ์ = ผู้ใช้ใหม่ (); user.setId (101); user.setUserName ("Joe"); user.setPassword ("Joe"); user.setEmail ("[email protected]"); userdao.updateByPrimaryKey (ผู้ใช้);เทียบเท่ากับ:
อัปเดต SET USERNAME = 'Joe', password = 'Joe', email = '[email protected]' โดยที่ id = 101
IntupterbyPrimaryKey (บันทึกบัญชี); // ต่อไปนี้เป็นผู้ใช้เคสผู้ใช้ที่สมบูรณ์ = ผู้ใช้ใหม่ (); user.setId (101); user.setUserName ("Joe"); user.setPassword ("Joe"); user.setEmail ("[email protected]"); userdao.updateByPrimaryKey (ผู้ใช้);เทียบเท่ากับ:
อัปเดต SET USERNAME = 'Joe', password = 'Joe', email = '[email protected]' โดยที่ id = 101
แยกวิเคราะห์ไฟล์การกำหนดค่า XML ของ Mapper
ลองมาดูกันว่า mybatis อ่านไฟล์การกำหนดค่า XML ของ Mapper และแยกวิเคราะห์คำสั่ง SQL ในนั้นได้อย่างไร
เรายังจำการกำหนดค่า SQLSessionFactory เช่นนี้:
<bean id = "sqlsessionfactory"> <property name = "dataSource" ref = "dataSource"/> <property name = "configlocation" value = "classpath: configuration.xml"> </property> <property name = "mapperlocations" value = "classpath: com/xxx/mybatis value = "com.tiantian.mybatis.model" /> </ebean>
นี่คือคุณสมบัติ mapperlocations ซึ่งเป็นนิพจน์ SQLSessionFactory จะอ่านไฟล์รูปแบบ XML ทั้งหมดด้านล่างแพ็คเกจ com.xxx.mybaits.mapper ตามนิพจน์นี้ ดังนั้นคุณจะอ่านไฟล์กำหนดค่าตามแอตทริบิวต์นี้ได้อย่างไร
คำตอบคือในวิธีการ buildsqlsessionfactory ในคลาส SQLSessionFactoryBean:
if (! isempty (this.mapperlocations)) {สำหรับ (ทรัพยากร mapperlocation: this.mapperlocations) {ถ้า (mapperlocation == null) {ดำเนินการต่อ; } ลอง {xmlmapperbuilder xmlmapperbuilder = ใหม่ xmlmapperbuilder (mapperlocation.getInputStream (), การกำหนดค่า, mapperlocation.toString (), configuration.getSqlFragments (); xmlmapperbuilder.parse (); } catch (Exception e) {โยน nestedioexception ใหม่ ("ไม่สามารถแยกวิเคราะห์ทรัพยากรการแมป: '" + mapperlocation + "'", e); } ในที่สุด {errorContext.Instance (). รีเซ็ต (); } if (logger.isdebugenabled ()) {logger.debug ("ไฟล์ mapper ที่แยกวิเคราะห์: '" + mapperlocation + "'"); -MyBatis ใช้อินสแตนซ์ของคลาส XMLMapperBuilder เพื่อแยกวิเคราะห์ไฟล์การกำหนดค่า Mapper
สาธารณะ XMLMApperBuilder (เครื่องอ่านเครื่องอ่าน, การกำหนดค่าการกำหนดค่า, ทรัพยากรสตริง, แผนที่ <สตริง, xnode> sqlfragments) {this (ใหม่ XPathParser (ตัวอ่าน, true, configuration.getVariables (), XMLMApperEntityResolver (), การกำหนดค่า } ส่วนตัว XMLMApperBuilder (XPathParser Parser, การกำหนดค่าการกำหนดค่า, ทรัพยากรสตริง, แผนที่ <สตริง, xnode> SQLFragments) {super (การกำหนดค่า); this.builderassistant = ใหม่ mapperbuilderassistant (การกำหนดค่า, ทรัพยากร); this.parser = parser; this.sqlfragments = sqlfragments; this.resource = ทรัพยากร; -จากนั้นระบบจะเรียกวิธีการแยกวิเคราะห์ของ XMLMApperBuilder เพื่อแยกวิเคราะห์ MAPPER
Public Void Parse () {// ถ้าวัตถุการกำหนดค่าไม่ได้โหลดไฟล์การกำหนดค่า XML (หลีกเลี่ยงการโหลดซ้ำจริง ๆ แล้วมันเป็นการยืนยันว่าคุณสมบัติและเนื้อหาของโหนด Mapper ได้รับการแยกวิเคราะห์ // การเตรียมการแยกแยะโทนของลูกบาศก์ โหลด if (! configuration.isresourceLoaded (ทรัพยากร)) {configurationElement (parser.evalnode ("/mapper")); configuration.addloadedResource (ทรัพยากร); bindmappernamespace (); } // แยกวิเคราะห์โหนด <resultmap> ที่ไม่ได้ประมวลผลเมื่อการประมวลผลผลลัพธ์ในฟังก์ชันการกำหนดค่า ParsePendingResultMaps (); // วิเคราะห์โหนด <cache> ที่ไม่มีอยู่เมื่อประมวลผลแคช-รีฟในฟังก์ชันการกำหนดค่าการกำหนด (สิ่งนี้จะเกิดขึ้นหากแคช-รีฟถูกโหลดก่อนที่แคชโหนดมันชี้ไปที่) parsependingchacherefs (); // เช่นเดียวกับข้างต้นหากไม่ได้โหลดแคชข้อยกเว้นจะถูกโยนลงเมื่อคำสั่งประมวลผล parsePendingStatements (); -กระบวนการของ MyBatis แยกวิเคราะห์ไฟล์ XML ของ Mapper นั้นชัดเจนมากอยู่แล้ว ลองมาดูกันว่ามันแยกวิเคราะห์ Mapper:
Void ConfigurationElement ส่วนตัว (บริบท Xnode) {ลอง {// รับแอตทริบิวต์ namespace ของ mapper node string namespace = context.getStringattribute ("namespace"); if (namespace.equals ("")) {โยน builderException ใหม่ ("เนมสเปซของ Mapper ไม่สามารถว่างเปล่า"); } // ตั้งค่า Namespace BuilderAssistant.setCurrentNamespace (เนมสเปซ); // แยกวิเคราะห์ <cache-ref> โหนด cacherefelement (context.evalnode ("cache-ref")); // แยกวิเคราะห์ <แคช> โหนด cacheelement (context.evalnode ("cache")); // แยกวิเคราะห์ <parameterMap> Node ParameterMapelement (context.evalnodes ("/mapper/parameterMap")); // แยกวิเคราะห์ <resultmap> node resultmapelements (context.evalnodes ("/mapper/resultmap")); // แยกวิเคราะห์ Node SQLELEMENT ของ Mapper's Mapper (context.evalnodes ("/mapper/sql")); // ใช้วัตถุ XMLStatementBuilder เพื่อแยกวิเคราะห์ <Select>, <simert>, <update>, <Elete> โหนด, // myBaits จะใช้คลาส MappedStatement.builder เพื่อสร้างวัตถุ MappedStatement // SQL ใน mybaits buildStatementFromContext (context.evalnodes ("เลือก | แทรก | อัปเดต | ลบ")); } catch (exception e) {โยน builderException ใหม่ ("ข้อผิดพลาดแยกวิเคราะห์ mapper xml. สาเหตุ:" + e, e); -ฟังก์ชั่นการกำหนดค่าการแยกวิเคราะห์การวิเคราะห์โหนดเด็กเกือบทั้งหมดในโหนด MAPPER ณ จุดนี้ MyBaits จะแยกโหนดทั้งหมดในแผนที่และเพิ่มลงในวัตถุการกำหนดค่าสำหรับวัตถุ SQLSessionFactory ที่จะใช้เมื่อใดก็ได้ ที่นี่เราจำเป็นต้องเพิ่มคำอธิบายเกี่ยวกับวิธีที่ MyBaits ใช้ฟังก์ชั่น parsestatementNode ของวัตถุของคลาส XMLStatementBuilder เพื่อยืม addmappedStatement ของ mapperbuilderassistant buildererassistant เพื่อแยกวิเคราะห์ mapedstatement และเชื่อมโยงกับวัตถุคลาสการกำหนดค่า
โมฆะสาธารณะ parsestatementNode () {// id แอตทริบิวต์สตริง id = context.getStringAttribute ("id"); // databaseId attrribute string databaseId = context.getStringAttribute ("databaseId"); if (! databaseIdMatchescurrent (id, databaseId, this.RequiredDatabaseId)) {return; } // fetchSize แอตทริบิวต์จำนวนเต็ม fetchSize = context.getIntAttribute ("fetchSize"); // การหมดเวลาแอตทริบิวต์จำนวนเต็มหมดเวลา = context.getIntAttribute ("หมดเวลา"); // พารามิเตอร์แอตทริบิวต์สตริงพารามิเตอร์ = context.getStringAttribute ("parameterMap"); // พารามิเตอร์แอตทริบิวต์สตริงพารามิเตอร์ TYPE = context.getStringAttribute ("parameterType"); คลาส <s?> parameterTypeclass = REFORVECLASS (พารามิเตอร์); // resultmap แอตทริบิวต์สตริงผลลัพธ์ map = context.getStringAttribute ("resultmap"); // resultType แอตทริบิวต์สตริงผลลัพธ์ ttype = context.getStringAttribute ("resultType"); // lang แอตทริบิวต์สตริง lang = context.getStringAttribute ("lang"); languagedriver langdriver = getLanguagedRiver (Lang); คลาส <?> resultTyPeclass = RELEVECLASS (ResultType); // resultsetType สตริงแอตทริบิวต์ resultetType = context.getStringAttribute ("resultsetType"); คำแถลง attementType = attementtype.valueof (context.getStringAttribute ("stationalType", attementtype.prepared.toString ())); ResultsETTYPE RESUCTIONETTYPEENOM = REALVEREVERESULTSETTYPE (RESUCTIONSETTYPE); String nodename = context.getNode (). getNodeName (); sqlCommandType sqlCommandType = sqlCommandType.valueof (nodename.touppercase (locale.english)); // มันคือ <elect> โหนดบูลีน isselect = sqlCommandType == sqlCommandType.select; // flushcache แอตทริบิวต์บูลีน flushcache = context.getBooleanAttribute ("flushcache" ,! isselect); // usecache แอตทริบิวต์บูลีน usecache = context.getBooleanAttribute ("USECACHE", ISSELECT); // resultordered attribute boolean resultordered = context.getBooleanAttribute ("resultordered", false); // รวมชิ้นส่วนก่อนที่จะแยกวิเคราะห์ xmlincludetransformer includeparser = ใหม่ xmlincludetransformer (การกำหนดค่า, builderassistant); includeparser.applyincludes (context.getNode ()); // Parse SelectKey หลังจากรวมและลบออก ProcessSelectKeynodes (ID, ParameterTypeclass, Langdriver); // แยกวิเคราะห์ SQL (pre: <SelectKey> และ <รวม> ถูกแยกวิเคราะห์และลบออก) SQLSource SQLSource = LangDriver.CreatesQlSource (การกำหนดค่าบริบทพารามิเตอร์ ParameterTypeclass); // resultsets สตริงคุณสมบัติ Resultets = context.getStringAttribute ("Resultsets"); // KeyProperty String สตริง keyProperty = context.getStringAttribute ("keyProperty"); // สตริงคุณสมบัติ Keycolumn Keycolumn = context.getStringAttribute ("KeyColumn"); Keygenerator Keygenerator; สตริง keystatementId = id + selectKeyGenerator.select_key_suffix; KeyStatementId = BuilderAssistant.applyCurrentNamespace (KeyStatementId, TRUE); if (configuration.haskeyenerator (keystatementId)) {keygenerator = configuration.getKeyGenerator (keystatementId); } else {// useGeneratedKeys แอตทริบิวต์ keygenerator = context.getBooleanAttribute ("useGeneratedKeys", configuration.isuseGeneratedKeys () && sqlcommandtype.insert.equals (sqlcommandtype))? ใหม่ JDBC3KEYGENERATOR (): new KeyGenerator (); } BuilderAssistant.addmappedStatement (ID, SQLSource, StatementType, SQLCommandType, FetchSize, หมดเวลา, ParameterMap, Parametertypeclass, Keyprolty ชุดผลลัพธ์); - จากรหัสด้านบนเราจะเห็นว่า MyBaits ใช้ XPATH เพื่อแยกวิเคราะห์ไฟล์การกำหนดค่า Mapper จากนั้นสร้างผลลัพธ์, ParameterMap, แคช, คำสั่งและโหนดอื่น ๆ ในนั้นโดยใช้ตัวสร้างที่เกี่ยวข้องและเชื่อมโยงวัตถุที่ได้รับเข้ากับวัตถุการกำหนดค่า วัตถุการกำหนดค่านี้สามารถรับได้จาก SQLSession ซึ่งอธิบายถึงปัญหาของวิธีที่ MyBaits ได้รับ MAPPER และดำเนินการคำสั่ง SQL ในนั้นเมื่อเราใช้ SQLSession เพื่อใช้งานฐานข้อมูล