ฉันยังไม่ได้ทำโครงการเมื่อเร็ว ๆ นี้ดังนั้นฉันจึงได้จัดระเบียบไฟล์การกำหนดค่าที่สมบูรณ์ที่สุดสำหรับเครื่องกำเนิด mybatis ที่สมบูรณ์ที่สุด (MBG สำหรับระยะสั้น) พร้อมคำอธิบายโดยละเอียดและฉันไม่ต้องดูคู่มือผู้ใช้ของ EN อีกต่อไป
<? xml version = "1.0" การเข้ารหัส = "utf-8"?> <! doctype generatoronconfigurationPublic "-// mybatis.org//dtd mybatis generation 1.0 // en" "http://mybatis.org/dtd/mybatis-gatis Generator-> <GeneratorConfiguration> <!-สามารถใช้ในการโหลดรายการการกำหนดค่าหรือไฟล์การกำหนดค่า ในไฟล์การกำหนดค่าทั้งหมดคุณสามารถใช้ $ {PropertyKey} เพื่ออ้างอิงทรัพยากรรายการการกำหนดค่า: กำหนดค่าที่อยู่การโหลดทรัพยากรใช้ทรัพยากรและ MBG เริ่มต้นจาก classPath เช่น com/myProject/generatorConfig.properties URL: กำหนดค่าธรณีวิทยาการโหลดทรัพยากร โปรดทราบว่าสามารถเลือกคุณสมบัติหนึ่งในสองคุณสมบัติได้ นอกจากนี้หากใช้ mybatis-generator-maven-plugin คุณสมบัติที่กำหนดใน pom.xml สามารถใช้โดยตรงใน generatorconfig.xml <properties resource = "" url = ""/>-> <! ไฟล์/ibm/sqllib/java/db2java.zip "/>-> <!-บริบท: ID สภาพแวดล้อมสำหรับการสร้างกลุ่มวัตถุ: จำเป็น, รหัสบริบท, ใช้เพื่อแจ้งเมื่อสร้างข้อผิดพลาดเริ่มต้น Modeltype: ระบุสไตล์ของวัตถุที่สร้างขึ้น 1, เงื่อนไข: คล้ายกับลำดับชั้น; 2, Flat: เนื้อหาทั้งหมด (คีย์หลัก, หยด) ฯลฯ ถูกสร้างขึ้นในวัตถุเดียว 3, ลำดับชั้น: คีย์หลักสร้างวัตถุ XXKEY (คลาสคีย์), หยด ฯลฯ สร้างวัตถุแยกกันและแอตทริบิวต์ง่าย ๆ อื่น ๆ อยู่ในวัตถุเดียว (คลาสบันทึก) TargetRuntime: 1, MyBatis3: ค่าเริ่มต้นสร้างเนื้อหาตาม mybatis3 2, MyBatis3Simple: คล้ายกับ MyBatis3 แต่ไม่ได้สร้าง xxxbysample; แนะนำ columnimpl: ชื่อที่ผ่านการรับรองอย่างสมบูรณ์ของคลาสใช้เพื่อขยาย MBG-> <context id = "mysql" defaultModelType = "ลำดับชั้น" targetRuntime = "myBatis3Simple"> <!-ระบุคำสำคัญของฐานข้อมูลโดยอัตโนมัติ โดยทั่วไปจะเก็บค่าเริ่มต้นคำหลักฐานข้อมูล (คำหลัก Java) ใช้คอลัมน์โอเวอร์รีด์เพื่อแทนที่-> <ชื่อคุณสมบัติ = "AutodelimitKeyWords" value = "false"/> <!-การเข้ารหัสไฟล์ Java ที่สร้างขึ้น-> value = "org.mybatis.generator.api.dom.defaultjavaformatter"/> <!-รูปแบบรหัส xml-> <property name = "xmlformatter" value = "org.mybatis.generator.api.dom.defaultxmlformatter"/> ตัวอย่างเช่น Oracle เป็นคำพูดสองเท่าและค่าเริ่มต้น MySQL เป็น `backticks; -> <property name = "artialdelimiter" value = "` "/> <property name =" enddelimiter "value =" `"/> <!-คุณต้องมีให้ใช้การกำหนดค่านี้เพื่อเชื่อมโยงฐานข้อมูล @todo: สามารถขยายได้-> userId = "root" password = "admin"> <!-ที่นี่คุณสามารถตั้งค่าคุณสมบัติคุณสมบัติและคุณสมบัติแต่ละคุณสมบัติถูกตั้งค่าเป็นไดรเวอร์ที่กำหนดค่า-> </jdbcconnection> <!-โปรเซสเซอร์ประเภท Java ใช้ในการประมวลผลประเภทใน db เพื่อประเภทใน Java โปรดทราบว่าโดยค่าเริ่มต้นคุณจะพยายามใช้จำนวนเต็มยาวสั้น ฯลฯ เพื่อให้สอดคล้องกับประเภทข้อมูลทศนิยมและตัวเลข -> <javatyperesolver type = "org.mybatis.generator.internal.types.javatyperesolverdefaultimpl"> <!-จริง: ใช้ bigdecimal สำหรับทศนิยมและประเภทข้อมูลที่เป็นเท็จ สเกล = 0; ความยาว [5,9]: ใช้จำนวนเต็ม; สเกล = 0; ความยาว <5: ใช้สั้น; -> <property name = "forceBigDecimals" value = "FALSE"/> </Javatyperesolver> <!-ผู้สร้างโมเดล Java เป็นองค์ประกอบที่จำเป็นที่รับผิดชอบ: 1. คลาสคีย์ (ดูค่าเริ่มต้นของบริบท); 2. คลาส Java; 3. คลาส Query TargetPackage: แพ็คเกจที่จะวางไว้ในคลาสที่สร้างขึ้นแพ็คเกจจริงจะถูกควบคุมโดยแอตทริบิวต์ ENABSEBPACKAGES; โครงการเป้าหมาย: โครงการเป้าหมายระบุไดเรกทอรีที่มีอยู่และเนื้อหาที่สร้างขึ้นจะถูกวางไว้ในไดเรกทอรีที่ระบุ หากไม่ได้มีไดเรกทอรี MBG จะไม่สร้างไดเรกทอรีโดยอัตโนมัติ-> <JavamodelGenerator TargetPackage = "com._520it.mybatis.domain" เป้าหมาย project = "src/main/java"> <!-สำหรับ mybatis3/mybatis3simple แทนที่จะใช้ Setters; -> <property name = "constructorBased" value = "false"/> <!-ขึ้นอยู่กับ TargetPackage ชั้นของแพ็คเกจจะถูกสร้างขึ้นตามสคีมาฐานข้อมูล คลาสที่สร้างขึ้นสุดท้ายจะถูกวางไว้ใต้แพ็คเกจนี้และค่าเริ่มต้นเป็นเท็จ-> <property name = "ENABSEBPACKAGES" value = "true"/> <!-สำหรับ myBatis3/myBatis3Simple สร้างคลาสที่ไม่เปลี่ยนรูปหรือไม่? ถ้าเป็นจริง MBG จะสร้างคลาสโดยไม่ต้องใช้เมธอด Setter และแทนที่ด้วยคลาสที่คล้ายกับ ConstructorBased-> <property name = "immutable" value = "false"/> <!-ตั้งค่าวัตถุรูท หากมีการตั้งค่าวัตถุรูทนี้คีย์คลาสที่สร้างขึ้นหรือ RecordClass จะสืบทอดคลาสนี้ ตัวเลือกนี้สามารถถูกแทนที่ในคุณสมบัติ rootclass ของตารางหมายเหตุ: หากมีแอตทริบิวต์เดียวกันกับคลาสรูทในคลาสคีย์หรือคลาสบันทึก MBG จะไม่สร้างแอตทริบิวต์เหล่านี้ใหม่รวมถึง: 1 ชื่อแอตทริบิวต์เหมือนกันประเภทเดียวกันและวิธีการ getter/setter เดียวกัน; -> <property name = "rootclass" value = "com._520it.mybatis.domain.basedomain"/> <!-ตั้งค่าว่าจะเรียกเมธอด trim () บนฟิลด์ประเภทสตริงในเมธอด getter-> <property name = "trimstrings" value = "true"/> โปรดทราบว่าหลังจาก MyBatis3 เราสามารถใช้ไฟล์ mapper.xml + อินเทอร์เฟซแม็ปเปอร์ (หรือไม่ใช้อินเตอร์เฟสแม็ปเปอร์) หรือใช้อินเทอร์เฟซ Mapper + คำอธิบายประกอบเท่านั้น ดังนั้นหากการกำหนดค่า JavaclientGenerator จำเป็นต้องสร้าง XML องค์ประกอบนี้จะต้องกำหนดค่าด้วย targetpackage/เป้าหมาย project: เหมือนกับ javamodelgenerator-> <sqlmapgenerator targetPackage = "com._520it.mybatis.mapper" targetProject = " ไปยังสคีมาฐานข้อมูล คลาสที่สร้างขึ้นสุดท้ายจะถูกวางไว้ใต้แพ็คเกจนี้และค่าเริ่มต้นเป็นเท็จ-> <property name = "ENABLESUBPACKAGES" value = "true"/> </sqlmapGenerator> <!-สำหรับ myBatis มันคือการสร้างอินเทอร์เฟซ Mapper โปรดทราบว่าหากองค์ประกอบไม่ได้รับการกำหนดค่าอินเทอร์เฟซ Mapper จะไม่ถูกสร้างขึ้นโดยค่าเริ่มต้น TargetPackage/TargetProject: เหมือนกับ JavamodelGeneratortype: เลือกวิธีการสร้างอินเทอร์เฟซ mapper (ภายใต้ mybatis3/mybatis3simple): 1. XML จะไม่ถูกสร้างขึ้น 2. Mixtmapper: การใช้การกำหนดค่าไฮบริดอินเทอร์เฟซ Mapper จะถูกสร้างขึ้นและคำอธิบายประกอบที่เหมาะสมจะถูกเพิ่มอย่างเหมาะสม แต่ XML จะถูกสร้างขึ้นใน XML; 3. XMLMApper: อินเทอร์เฟซ Mapper จะถูกสร้างขึ้นและอินเทอร์เฟซจะขึ้นอยู่กับ XML อย่างสมบูรณ์ โปรดทราบว่าหากบริบทคือ MyBatis3Simple: มีเพียงคำอธิบายประกอบและ XMLMApper-> <javaclientGenerator TargetPackage = "com._520it.mybatis.mapper" type = "annotatedMapper" datcackage คลาสที่สร้างขึ้นสุดท้ายจะอยู่ภายใต้แพ็คเกจนี้ซึ่งค่าเริ่มต้นเป็นเท็จ-> <ชื่อคุณสมบัติ = "ENABLESUBPACKAGES" value = "true"/> <!-คุณสามารถเพิ่มอินเทอร์เฟซพาเรนต์เข้ากับอินเทอร์เฟซที่สร้างขึ้นทั้งหมด แต่ MBG มีความรับผิดชอบในการสร้างและไม่รับผิดชอบ อาจมีหนึ่งตารางขึ้นไป จะต้องมีตารางที่เลือกโดยองค์ประกอบตาราง ไฟล์ต่อไปนี้จะถูกสร้างขึ้น: 1. ไฟล์แผนที่ SQL 2. สร้างคลาสคีย์หลัก 3. คลาสที่มีฟิลด์อื่นยกเว้นหยดและคีย์หลัก 4. คลาสที่มีหยด; 5. คลาสแบบมีเงื่อนไขสำหรับผู้ใช้ในการสร้างแบบสอบถามแบบไดนามิก (SelectByExample, DELETEBYEXAMPLE), เป็นทางเลือก; 6. Mapper Interface (ไม่บังคับ) ชื่อ TableName (จำเป็น): ชื่อตารางของวัตถุที่จะสร้าง; หมายเหตุ: ปัญหาที่ละเอียดอ่อนกรณี ภายใต้สถานการณ์ปกติ MBG จะระบุความไวของเคสของตัวระบุฐานข้อมูลโดยอัตโนมัติ โดยทั่วไป MBG จะสืบค้นตารางข้อมูลตามชุดสคีมาแคตตาล็อกหรือชื่อแท็บเลนและทำตามกระบวนการต่อไปนี้: 1. หากมีช่องว่างในสคีมาแคตตาล็อกหรือชื่อแท็บเลนแล้วชุดรูปแบบจะใช้ในการสืบค้นอย่างถูกต้อง 2. มิฉะนั้นถ้าตัวระบุฐานข้อมูลเป็นตัวพิมพ์ใหญ่แล้ว MBG จะเปลี่ยนชื่อตารางเป็นทุนโดยอัตโนมัติแล้วค้นหา 3. มิฉะนั้นถ้าตัวระบุฐานข้อมูลเป็นตัวพิมพ์ใหญ่แล้ว MBG จะเปลี่ยนชื่อตารางเป็นทุนโดยอัตโนมัติแล้วค้นหา ค้นหา; 4. มิฉะนั้นให้ใช้รูปแบบเคสที่ระบุเพื่อสอบถาม นอกจากนี้หากวัตถุฐานข้อมูลถูกใช้เมื่อสร้างตารางชื่อตารางจะถูกสร้างขึ้นโดยใช้กรณีที่กำหนดแม้ว่าจะใช้ตัวระบุฐานข้อมูลในกรณีนี้โปรดตั้งค่า delimitIdentifiers = "จริง" เพื่อรักษารูปแบบเคส; ทางเลือก: 1. Schema: สคีมาของฐานข้อมูล; 2. แคตตาล็อก: แคตตาล็อกฐานข้อมูล; 3. นามแฝง: นามแฝงที่ตั้งไว้สำหรับตารางข้อมูล หากมีการตั้งค่านามแฝงการเลือกทั้งหมดที่สร้างขึ้นในคำสั่ง SQL ชื่อคอลัมน์จะกลายเป็น: alias_actualColumnName4, DomainObjectName: ชื่อของคลาสโดเมนที่สร้างขึ้น หากไม่ได้ตั้งค่าให้ใช้ชื่อตารางเป็นชื่อของคลาสโดเมน สามารถตั้งค่าเป็น somepck.domainname จากนั้นคลาส DomainName จะถูกวางไว้ในแพ็คเกจ SomePCK โดยอัตโนมัติ 5, enableInsert (เริ่มต้นจริง): ระบุว่าจะสร้างคำสั่งแทรกหรือไม่ 6, ENABLESELECTBYPRIMARYKEY (ค่าเริ่มต้นจริง): ระบุว่าจะสร้างคำสั่งสำหรับการสอบถามวัตถุตามคีย์หลัก (เช่น getByID หรือรับ); 7. ENABLESELECTBYEXAMPLE (ค่าเริ่มต้นจริง): MyBatis3Simple เป็นเท็จโดยระบุว่าจะสร้างคำสั่งแบบสอบถามแบบไดนามิกหรือไม่ 8. enableUpdateByPrimaryKey (ค่าเริ่มต้นจริง): ระบุว่าจะสร้างคำสั่งที่ปรับเปลี่ยนวัตถุตามคีย์หลัก (เช่นอัปเดต); 9. ENABLEELETEBYPRIMARYKEY (ค่าเริ่มต้นจริง): ระบุว่าจะสร้างคำสั่งที่ลบวัตถุตามคีย์หลัก (เช่นลบ); 10. ENEVALLEL ETEBYEXAMPLE (ค่าเริ่มต้นจริง): MyBatis3Simple เป็นเท็จระบุว่าจะสร้างคำสั่งลบแบบไดนามิกหรือไม่ 11, enableCountByExample (ค่าเริ่มต้นจริง): myBatis3Simple เป็นเท็จระบุว่าจะสร้างจำนวนคำสืบค้นแบบไดนามิกทั้งหมด (ใช้สำหรับจำนวนคำทั้งหมดสำหรับการปนเปื้อน); 12, enableUpdateByExample (ค่าเริ่มต้นจริง): myBatis3Simple เป็นเท็จระบุว่าจะสร้างคำสั่งการปรับเปลี่ยนแบบไดนามิก (เฉพาะการแก้ไขแอตทริบิวต์ที่ไม่ว่างในวัตถุ); 13, ModelTyp E: อ้างถึง defaultModelType ขององค์ประกอบบริบทซึ่งเทียบเท่ากับการเขียนทับ; 14, DelimitIdentifiers: อ้างถึงคำอธิบายของ Tablename โปรดทราบว่าตัว delimitidentifiers เริ่มต้นเป็นคำพูดสองเท่า หากฐานข้อมูลเช่น MySQL ใช้ `(backquotes คุณจะต้องตั้งค่าคุณสมบัติเริ่มต้นของบริบทและคุณสมบัติ enddelimiter) 15, DelimitallColumns: ตั้งชื่อชื่อคอลัมน์ที่สร้างขึ้นทั้งหมดใน SQL นั้นเกิดจากตัวระบุ DelimitIdentifiers อ้างถึงคุณสมบัติของบริบท โปรดทราบว่าพารามิเตอร์จำนวนมากในตารางเป็นการเขียนใหม่ของคุณสมบัติเริ่มต้นของ JavamodelGenerator บริบทและองค์ประกอบอื่น ๆ -> <table tablename = "userInfo"> <!-อ้างอิงคุณสมบัติ constructorBased ของ JavamodelGenerator-> <property name = "constructorBased" value = "false"/> <!-ค่าเริ่มต้นเป็นเท็จ หากตั้งค่าเป็นจริงชื่อตารางจะไม่ถูกเพิ่มด้วยแคตตาล็อกหรือสคีมาใน SQL ที่สร้างขึ้น -> <property name = "ละเว้น Qualifiersatruntime" value = "false"/> <!-การอ้างอิง JavamodelGenerator คุณสมบัติที่ไม่เปลี่ยนรูปของคุณสมบัติที่ไม่เปลี่ยนรูป-> <ชื่อคุณสมบัติ = "ไม่เปลี่ยนแปลง" value = "false"/> <!-ระบุว่าจะสร้างคลาสโดเมนเท่านั้น หากตั้งค่าเป็นจริงจะมีการสร้างคลาสโดเมนเท่านั้น หากมีการกำหนดค่า SQLMAPGENERATOR ด้วยเช่นกันในไฟล์ MAPPER XML จะมีการสร้างองค์ประกอบผลลัพธ์ MAP เท่านั้น-> <ชื่อคุณสมบัติ = "modelOnly" value = "false"/> <!-อ้างถึงคุณสมบัติ rootclass ของ JavamodelGenerator name = "rootinterface" value = ""/>-> <!-อ้างถึงคุณสมบัติ rootinterface ของ javaclientGenerator <property name = "rootinterface" value = ""/>-> <! <property name = "runtimeCatalog" value = ""/>-> <!-หากตั้งค่า runtimeschema จากนั้นใน SQL ที่สร้างขึ้นจะใช้สคีมาที่ระบุแทนสคีมาบนองค์ประกอบตาราง <property name = "runtimeschema" value = ""/>-> <!-หากตั้งค่า runtimetablename จากนั้นใน SQL ที่สร้างขึ้นจะใช้ชื่อ tablename ที่ระบุแทนองค์ประกอบตาราง <property name = "runtimetablename" value = ""/>-> <!-โปรดทราบว่าคุณสมบัตินี้มีประโยชน์สำหรับ myBatis3Simple เท่านั้น หากรันไทม์ที่เลือกคือ MyBatis3Simple วิธีการเลือกจะถูกสร้างขึ้น หากระบุ SelectallOrderByClause เงื่อนไขการสั่งซื้อที่ระบุจะถูกเพิ่มลงใน SQL; -> <property name = "SelectallOrderByClause" value = "อายุ desc, ชื่อผู้ใช้ ASC"/> <!-ถ้าตั้งค่าเป็นจริงคลาสโมเดลที่สร้างขึ้นจะใช้ชื่อคอลัมน์โดยตรงและจะไม่ใช้วิธีการตั้งชื่ออูฐอีกต่อไป สร้างวิธีการสร้างคีย์หลัก หากองค์ประกอบนี้ถูกตั้งค่า MBG จะสร้างองค์ประกอบ <SelectKey> ที่ถูกต้องในองค์ประกอบ <simert> ที่สร้างขึ้น องค์ประกอบสามารถเลือกคอลัมน์: ชื่อคอลัมน์ของคีย์หลัก; SQLStatement: คำสั่ง SelectKey ที่จะสร้างมีตัวเลือกต่อไปนี้: CloudScape: SQL เทียบเท่ากับ SelectKey คือ: ค่า identity_val_local () () DB2: SQL เทียบเท่ากับ SelectKey คือ: ค่า identity_val_local () () DB2_MF sysibm.sysdummy1derby: SQL เทียบเท่ากับ selectkey คือ: ค่า identity_val_local () hsqldb: SQL เทียบเท่ากับ selectkey คือ: call identity () informix: SQL เทียบเท่ากับ selectkey คือ: เลือก dbinfo (sqlca.sqlerrd1 SelectKey คือ: เลือก last_insert_id () sqlserver: SQL เทียบเท่ากับ selectkey คือ: เลือก scope_identity () sybase: SQL เทียบเท่ากับ selectkey คือ: select @@ identityjdbc: มันเทียบเท่ากับการเพิ่ม usegeneratedkeys = "true" และ keyproperty attributes SQLStatement = ""/>-> <!-องค์ประกอบนี้จะเปลี่ยนชื่อชื่อคอลัมน์ก่อนคำนวณชื่อแอตทริบิวต์วัตถุตามชื่อคอลัมน์ในตาราง มันเหมาะมากสำหรับเมื่อคอลัมน์ในตารางมีสตริงคำนำหน้าทั่วไปเช่นชื่อคอลัมน์: cust_id, cust_name, cust_email, cust_address ฯลฯ ; จากนั้นคุณสามารถตั้งค่า SearchString เป็น "^custer_" และแทนที่ด้วยพื้นที่ว่าง จากนั้นชื่อแอตทริบิวต์ในวัตถุลูกค้าที่สร้างขึ้นจะไม่ถูกเก็บไว้, cu stname, ฯลฯ แต่ถูกแทนที่ด้วยรหัสชื่ออีเมลและจากนั้นกลายเป็นแอตทริบิวต์: id, ชื่อ, อีเมล; โปรดทราบว่า MBG ใช้ java.util.regex.matcher.replaceall เพื่อแทนที่ SearchString และการแทนที่ หากมีการใช้องค์ประกอบ Columnoverride แอตทริบิวต์นี้ไม่ถูกต้อง <columnRenamingRule searchString = "" replacestring = ""/>-> <!-ใช้เพื่อแก้ไขคุณสมบัติของคอลัมน์ในตาราง MBG จะใช้คอลัมน์ที่แก้ไขเพื่อสร้างคุณสมบัติของโดเมน คอลัมน์: ชื่อคอลัมน์ที่จะรีเซ็ต; โปรดทราบว่าอาจมีองค์ประกอบ columnoverride หลายองค์ประกอบในองค์ประกอบตาราง ~-> <columnoverride column = "ชื่อผู้ใช้"> <!-ใช้แอตทริบิวต์คุณสมบัติเพื่อระบุชื่อแอตทริบิวต์เพื่อสร้างคอลัมน์-> <property name = "property" value = "ชื่อผู้ใช้"/> <! <property name = "Javatype" value = ""/>-> <!-JDBCType ใช้เพื่อระบุประเภท JDBC ของคอลัมน์ <property name = "JDBCType" value = ""/>-> <! หากคุณต้องการระบุโปรดทราบว่าใน mybatis, typehandler ใน mybatis-config.xml จะไม่ถูกสร้างขึ้นใน mybatis-config.xml เฉพาะคำอธิบายพารามิเตอร์ของสิ่งต่อไปนี้: id = #{id, jdbctype = bigint, typehandler = com._520it name = "jdbcType" value = ""/>-> <!-อ้างถึงการกำหนดค่า delimitallColumns ขององค์ประกอบตารางค่าเริ่มต้นเป็นเท็จ <property name = "DelimitedColumnName" value = ""/>-> หากมีการตั้งค่าคอลัมน์ใหม่แล้วในโดเมนที่สร้างขึ้นและสร้าง SQL คอลัมน์: ระบุชื่อของคอลัมน์ที่จะละเว้น DelimitedColumnName: อ้างถึงการกำหนดค่า DelimitAllColumns ขององค์ประกอบตารางค่าเริ่มต้นเป็นเท็จ โปรดทราบว่าอาจมีองค์ประกอบที่ไม่รู้หลายอย่างในองค์ประกอบตาราง <molongeColumn column = "deptid" delimitedColumnName = ""/>-> </table> </context>ด้านบนเป็นคำอธิบายโดยละเอียดเกี่ยวกับไฟล์การกำหนดค่าที่สมบูรณ์แบบที่สุดของเครื่องกำเนิด MyBatis ที่แนะนำโดยตัวแก้ไข (เวอร์ชันเต็ม) ฉันหวังว่ามันจะเป็นประโยชน์กับคุณ หากคุณมีคำถามใด ๆ โปรดฝากข้อความถึงฉันและบรรณาธิการจะตอบกลับคุณทันเวลา ขอบคุณมากสำหรับการสนับสนุนเว็บไซต์ Wulin.com!