มีไลบรารีตัวสร้างไดนามิก SQL ที่ดีใน Java หรือไม่? [ปิด]


108

ใคร ๆ ก็รู้จักไลบรารีตัวสร้าง SQL ที่ดีสำหรับ Java เช่นSquiggle (ดูเหมือนจะไม่ได้รับการดูแลอีกต่อไป) โดยเฉพาะอย่างยิ่งโครงการในการพัฒนาที่ใช้งานอยู่

โดยเฉพาะอย่างยิ่งกับไวยากรณ์เช่นZend_Db_Selectสิ่งที่จะช่วยให้สร้างแบบสอบถามได้

String query = db.select().from('products').order('product_id');

ฉันขอถามอะไรคือข้อดีของไวยากรณ์ด้านบนกับ "SELECT f1..fn FROM products ORDER BY product_id"
Itay Moav -Malimovka

4
@ ItayMoav-Malimovka อย่างน้อยไวยากรณ์ของแบบสอบถาม SQL ในกรณีของฉัน (ถ้าเราใช้ JOOQ เป็นตัวอย่าง) จะถูกตรวจสอบในเวลาที่คุณเขียนโค้ด คุณมีการเติมเต็มไวยากรณ์อัตโนมัติเต็มรูปแบบซึ่งจะทำให้การเขียนแบบสอบถามของคุณเร็วขึ้นและทำให้เกิดข้อผิดพลาดได้ง่ายขึ้น
Vladislav Rastrusny

ฉันยอมรับว่านี่เป็นสิ่งที่ IDE ควรปรับปรุง
Itay Moav -Malimovka

1
@ ItayMoav-Malimovka อืม ... ในกรณีของ JOOQ ถ้าฉันเปลี่ยนแปลงบางอย่างในโครงสร้าง DB โค้ดของฉันจะหยุดรวบรวมจนกว่าฉันจะแก้ไขตามโครงสร้าง DB ใหม่ หากคุณมีข้อความค้นหาเป็นข้อความพวกเขาจะปล่อยให้เสีย
Vladislav Rastrusny

ตัวอย่าง: ฉันกำลังทำงานกับแอปพลิเคชันที่ต้องการสร้างคำสั่งเพื่อทำงานบนฐานข้อมูลเดิมขนาดใหญ่ คำสั่งจำนวนมากแบ่งปันข้อ จำกัด ที่กำหนดเองซึ่งเราสร้างโดย SQL DSL ต้องขอบคุณที่เราสามารถสร้างข้อความที่ไม่เป็นที่รู้จักในเวลาคอมไพล์ได้อย่างง่ายดาย
Rafael Winterhalter

คำตอบ:


54

QuerydslและjOOQเป็นสองตัวเลือกยอดนิยม


6
JOOQ อาจเป็นทางเลือกที่ดีกว่าสำหรับการพัฒนา SQL แบบฮาร์ดคอร์ แต่ Querydsl มี API ที่ง่ายกว่าและรองรับแบ็กเอนด์อื่น ๆ (JPA, JDO, Lucene, Mongodb เป็นต้น) ฉันอยู่ใน บริษัท ที่อยู่เบื้องหลัง Querydsl
Timo Westkämper

เราใช้ Querydsl SQL ในโครงการในบ้านบางโครงการ ฉันไม่มีประสบการณ์ส่วนตัวเกี่ยวกับ jooq แต่ฉันได้ยินมาว่ามันค่อนข้างโอเค
ponzao

11
ปัญหาเกี่ยวกับ QueryDsl คือคุณไม่สามารถใช้เป็นตัวสร้างแบบสอบถามที่แท้จริงได้เนื่องจากไม่ได้ให้แบบสอบถามที่สร้างขึ้นเอง มันจะสร้างแบบสอบถามและดำเนินการให้คุณด้วย คุณไม่สามารถรับกันได้โดยปราศจากกันและกัน
Abhinav Sarkar

5
Querydsl และ jOOQ ดูเหมือนจะเป็นตัวเลือกที่ได้รับความนิยมและเป็นผู้ใหญ่มากที่สุด แต่มีสิ่งหนึ่งที่ต้องระวัง: ทั้งสองอาศัยแนวคิดของการสร้างโค้ดโดยที่คลาสเมตาถูกสร้างขึ้นสำหรับตารางฐานข้อมูลและฟิลด์ สิ่งนี้อำนวยความสะดวกให้กับ DSL ที่ดีและสะอาด แต่ประสบปัญหาเมื่อพยายามสร้างแบบสอบถามสำหรับฐานข้อมูลที่ทราบเฉพาะในขณะรันไทม์เท่านั้นเช่นในตัวอย่างของ OP ด้านบน แม้ว่า jOOQ จะรองรับการเข้าหาแบบ String แต่ก็มีนิสัยแปลก ๆ เอกสารของ Querydsl ไม่ได้ระบุว่าเป็นไปได้หรือไม่ที่จะไม่ใช้การสร้างโค้ด กรุณาแก้ไขฉันถ้าฉันผิด
Sven Jacobs

3
@SvenJacobs ความคิดเห็นเก่ามาก แต่ในการอัปเดต QueryDSL อนุญาตให้สร้าง sql โดยไม่ต้องสร้างรหัส: stackoverflow.com/questions/21615956/…
Nagaraj Tantri

7

ddlutilsเป็นทางเลือกที่ดีที่สุดของฉัน: http://db.apache.org/ddlutils/api/org/apache/ddlutils/platform/SqlBuilder.html

นี่คือตัวอย่างการสร้าง (groovy):

Platform platform  = PlatformFactory.createNewPlatformInstance("oracle");//db2,...
//create schema    
def db =        new Database();
def t = new Table(name:"t1",description:"XXX");
def col1 = new Column(primaryKey:true,name:"id",type:"bigint",required:true);
t.addColumn(col1);
t.addColumn(new Column(name:"c2",type:"DECIMAL",size:"8,2"));
t.addColumn( new Column(name:"c3",type:"varchar"));
t.addColumn(new Column(name:"c4",type:"TIMESTAMP",description:"date"));        
db.addTable(t);
println platform.getCreateModelSql(db, false, false)

//you can read Table Object from  platform.readModelFromDatabase(....)
def sqlbuilder = platform.getSqlBuilder();
println "insert:"+sqlbuilder.getInsertSql(t,["id":1,c2:3],false);
println "update:"+sqlbuilder.getUpdateSql(t,["id":1,c2:3],false);
println "delete:"+sqlbuilder.getDeleteSql(t,["id":1,c2:3],false);
//http://db.apache.org/ddlutils/database-support.html

1
ฉันต้องกำหนดคอลัมน์อีกครั้งแม้ว่าฉันจะกำหนดไว้ใน @Entity แล้วก็ตามความเจ็บปวด
huuthang

6

ฉันสามารถขอแนะนำjOOQ มันมีคุณสมบัติที่ยอดเยี่ยมมากมายรวมถึง DSL ที่ใช้งานง่ายสำหรับ SQL และแนวทางวิศวกรรมย้อนกลับที่ปรับแต่งได้อย่างยอดเยี่ยม

jOOQ รวม SQL ที่ซับซ้อน, ความปลอดภัยประเภท, การสร้างซอร์สโค้ด, เร็กคอร์ดที่ใช้งาน, โพรซีเดอร์ที่จัดเก็บ, ชนิดข้อมูลขั้นสูงและ Java ได้อย่างมีประสิทธิภาพใน DSL ที่ใช้งานง่ายและคล่องแคล่ว


ใช้มั้ย? คุณจะพบมันได้อย่างไร?
Vladislav Rastrusny

3
ฉันใช้มันเพื่อสร้างซอร์สโค้ดที่กำหนดเองจาก DDL มันใช้งานได้ดี!
Christopher Klewes

"แม้ว่าไลบรารี jOOQ จะมี API ที่ยอดเยี่ยมสำหรับการสร้างคำสั่ง SQL แต่ก็มาพร้อมกับชุดเครื่องมือทั้งหมดในการสร้างคำสั่งเชื่อมต่อกับฐานข้อมูลเขียน / อ่านโมเดลไปยัง / จากฐานข้อมูล ฯลฯ เนื่องจาก VM ของแอปพลิเคชัน Androids ในปัจจุบัน มีขีด จำกัด การอ้างอิงเมธอด 64k jOOQ สามารถมีเมธอดอ้างอิงได้มากกว่า 10,000 เมธอดเมื่อใช้งานซึ่งอาจดูเหมือนไม่มากเมื่อเทียบกับขีด จำกัด แต่ถ้าคุณพิจารณาไลบรารีขนาดใหญ่อื่น ๆ ที่ใช้กันทั่วไป (เช่น Guava และ Google Play Services) การกดขีด จำกัด 64k นั้นจะง่ายกว่ามาก " - android-arsenal.com/details/1/3202 :(
Tomáš Fejfar

3

Hibernate Criteria API (ไม่ใช่ SQL ธรรมดา แต่มีประสิทธิภาพมากและอยู่ในการพัฒนาที่ใช้งานอยู่):

List sales = session.createCriteria(Sale.class)
         .add(Expression.ge("date",startDate);
         .add(Expression.le("date",endDate);
         .addOrder( Order.asc("date") )
         .setFirstResult(0)
         .setMaxResults(10)
         .list();

1
ปัญหาคือมันไม่ได้แมปกับ SQL อย่างที่เข้าใจใช่ไหม?
Vladislav Rastrusny

7
สิ่งนี้ไม่ได้สร้าง SQL และเป็นฝันร้ายในการดีบักเมื่อไม่เป็นไปตามกฎของความประหลาดใจอย่างน้อยที่สุด (ไม่ทำงานตามที่คาดไว้)

สร้าง SQL (ในตอนท้าย) และไม่ทำให้ใครประหลาดใจ ประโยชน์ - เป็นแบบพกพาข้ามฐานข้อมูล
Vladimir Dyuzhev

3
ระดับความซับซ้อนของการสืบค้นที่คุณประสบความสำเร็จในการเข้าถึงด้วย JPA Criteria API โดยที่ไม่ทำให้ข้อความค้นหาไม่สามารถอ่านได้ทั้งหมด คุณมีตัวอย่างของการเลือกที่ซ้อนกันในIN/ EXISTSอนุประโยคหรือการเข้าร่วมด้วยตนเองโดยใช้นามแฝงสำหรับSaleเอนทิตี ฯลฯ หรือไม่ ฉันอยากรู้อยากเห็น
Lukas Eder

1
ความคิดเห็นไม่ได้ให้พื้นที่มากนักในการให้ตัวอย่าง แต่คุณสามารถตรวจสอบได้ที่docs.jboss.org/hibernate/core/3.5/reference/en/html/…
Vladimir Dyuzhev

0

คุณสามารถใช้ไลบรารีต่อไปนี้:

https://github.com/pnowy/NativeCriteria

ไลบรารีถูกสร้างขึ้นที่ด้านบนของ Hibernate "create sql query" ดังนั้นจึงรองรับฐานข้อมูลทั้งหมดที่ Hibernate รองรับ (รองรับเซสชัน Hibernate และ JPA) รูปแบบตัวสร้างพร้อมใช้งานและอื่น ๆ (ตัวทำแผนที่วัตถุตัวทำแผนที่ผลลัพธ์)

คุณสามารถดูตัวอย่างได้ที่หน้า github ไลบรารีมีอยู่ที่ Maven central แน่นอน

NativeCriteria c = new NativeCriteria(new HibernateQueryProvider(hibernateSession), "table_name", "alias");
c.addJoin(NativeExps.innerJoin("table_name_to_join", "alias2", "alias.left_column", "alias2.right_column"));
c.setProjection(NativeExps.projection().addProjection(Lists.newArrayList("alias.table_column","alias2.table_column")));

สิ่งนี้ซับซ้อนกว่าการเขียน SQL ด้วยมือ
EpicPandaForce

@EpicPandaForce ฉันเห็นด้วยสำหรับกรณีที่ง่ายมาก แต่การเชื่อมต่อนั้นซับซ้อนมากเมื่อคุณต้องการต่อสตริงนั้นตามเงื่อนไขที่ซับซ้อนมากซึ่งมีชุดเงื่อนไขที่แตกต่างกัน สตริงที่ต่อกันอย่างถูกต้อง (เช่นเดียวกับการเพิ่มการรวมการมีการตั้งค่าพารามิเตอร์ ฯลฯ ) เป็นความเจ็บปวด ด้วยโซลูชันคุณมีผู้สร้างที่จะจัดการกับความซับซ้อนนี้ให้กับคุณ
Przemek Nowak
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.