Jdbi: عدم التوافق بين v2 و v3 عند استخدام خريطة المعلمات الزائدة

تم إنشاؤها على ١٨ يناير ٢٠١٩  ·  15تعليقات  ·  مصدر: jdbi/jdbi

مرحبا فريق jdbi :)

في JDBI v2 كنا نستخدم بناء مثل هذا:

@SqlQuery("SELECT COUNT(*) FROM account a WHERE <where>")
int count(@Define("where") String where, <strong i="8">@BindMap</strong> Map<String, Object> params);

يتم إنشاء where في وقت التشغيل. في بعض الحالات يكون فارغًا (ببساطة 1 = 1 ) وفي بعض الحالات يحتوي على بعض القيم التي يوفرها المستخدم في مرشح واجهة المستخدم الرسومية. على سبيل المثال:

SELECT COUNT(*) FROM account a WHERE 1 = 1;

مع:

where = '1 = 1'
params = { }

أو:

SELECT COUNT(*) FROM account a WHERE 1 = 1 AND a.status = :status;

عندما قدم المستخدم الحالة في مرشح واجهة المستخدم الرسومية:

where = '1 = 1 AND a.status = :status'
params = { status = 2 }

في الوقت الحالي ، عند توفير وسيطة فارغة params ، فإن هذا يؤدي إلى استثناء. على سبيل المثال:

com.vividgames.swim.akka.exception.MessageProcessingException: org.jdbi.v3.core.statement.UnableToCreateStatementException: Superfluous named parameters provided while the query declares none: '{positional:{}, named:{}, finder:[{}]}'. [statement:"SELECT count(*) FROM test t WHERE <where>", rewritten:"/* templated */ SELECT count(*) FROM test t WHERE value > 0", parsed:"ParsedSql{sql='/* CountDao.count */ SELECT count(*) FROM `dev-abc.1`.test t WHERE value > 0', parameters=ParsedParameters{positional=false, parameterNames=[]}}", arguments:{positional:{}, named:{}, finder:[{}]}]
    at org.jdbi.v3.core.statement.ArgumentBinder.bindNamed(ArgumentBinder.java:58)
    at org.jdbi.v3.core.statement.ArgumentBinder.bind(ArgumentBinder.java:29)
    at org.jdbi.v3.core.statement.SqlStatement.internalExecute(SqlStatement.java:1429)
    at org.jdbi.v3.core.result.ResultProducers.lambda$getResultSet$2(ResultProducers.java:68)
    at org.jdbi.v3.core.result.ResultIterable.lambda$of$0(ResultIterable.java:53)
    at org.jdbi.v3.core.result.ResultIterable.findFirst(ResultIterable.java:116)
    at org.jdbi.v3.sqlobject.statement.internal.ResultReturner$CollectedResultReturner.mappedResult(ResultReturner.java:266)
    at org.jdbi.v3.sqlobject.statement.internal.SqlQueryHandler.lambda$configureReturner$0(SqlQueryHandler.java:54)
    at org.jdbi.v3.sqlobject.statement.internal.CustomizingStatementHandler.invoke(CustomizingStatementHandler.java:155)
    at org.jdbi.v3.sqlobject.statement.internal.SqlQueryHandler.invoke(SqlQueryHandler.java:26)
    at org.jdbi.v3.sqlobject.SqlObjectFactory.lambda$null$13(SqlObjectFactory.java:163)
    at org.jdbi.v3.core.ConstantHandleSupplier.invokeInContext(ConstantHandleSupplier.java:52)
    at org.jdbi.v3.sqlobject.SqlObjectFactory.lambda$createInvocationHandler$14(SqlObjectFactory.java:162)

لقد وجدت علامة في SqlStatements يمكن استخدامها للسماح بعمليات الربط غير المستخدمة :

/**
 * Sets whether or not an exception should be thrown when any arguments are given to a query but not actually used in it. Unused bindings tend to be bugs or oversights, but can also just be convenient. Defaults to false: unused bindings are not allowed.
 *
 * <strong i="32">@see</strong> org.jdbi.v3.core.argument.Argument
 */
public SqlStatements setUnusedBindingAllowed(boolean allowUnusedBindings) {
    this.allowUnusedBindings = allowUnusedBindings;
    return this;
}

لكن لا يمكنني العثور على أي طريقة لاستخدام هذه الطريقة: (في كود مصدر JDBI ، وجدت الاستخدامات فقط ، ولكن لا يوجد مكان يتم تعيينه فيه.

يمكنني إعادة كتابة DAOs وإدخال طرق جديدة لا تتطلب params ، على سبيل المثال:

@SqlQuery("SELECT COUNT(*) FROM account a")
int countAll();

@SqlQuery("SELECT COUNT(*) FROM account a WHERE <where>")
int countFiltered(@Define("where") String where, <strong i="38">@BindMap</strong> Map<String, Object> params);

ولكن هذا يجب أن يتم في عدد من DAOs الموجودة ولكي أكون صادقًا ، أود تغيير سطر واحد وجعله يعمل بشكل سحري مرة أخرى.

doc feature

التعليق الأكثر فائدة

كنت أقرأ من خلال JdbiConfig وكان لدي نفس الانطباع. تم مسح الأمور بعد أن أعطانيTheRealMarnes مثالاً قدمه في التعليق.

شكرًا لك على @AllowUnusedBindings :)

ال 15 كومينتر

سيتعين عليك تعيين العلم على Jdbi / المؤشر الذي ينشئ SqlObject.

jdbi.useHandle(h -> {
    Dao dao = h.configure(SqlStatements.class, stmts -> stmts.setUnusedBindingAllowed(true))
        .attach(Dao.class);
});

بقدر ما أتذكر ، لا يوجد عبارة مخصصة لتعليق توضيحي مثل @AllowUnusedBindings للقيام بذلك. يمكن أن تساهم بسهولة إذا كنت تريد ذلك حقًا.

مرحبا TheRealMarnes ،

الكود الخاص بك يعمل بشكل مثالي :) شكرا لك!

أعتقد أن هذا يمكن وصفه في وثائق JDBI المتاحة من www ، أو في setUnusedBindingAllowed javadoc (لأن هذه كانت الأماكن الأولى التي بدأت فيها البحث عن كيفية استخدامها).

لا أعرف كيف أقوم بتحرير الوثائق ، لكن يمكنني تحديث javadoc إذا أردت.

أنت على حق ، الدليل يفتقر إلى أي ذكر له. ربما يجب أن يذكرها الاستثناء أيضًا.

لست متأكدًا من سبب طرحك لـ javadoc على الرغم من نقصه ؛ لقد لصقت حرفيا الجافادوك ، لذا فهي موجودة.

إذا كنت ترغب في بدء قسم يدوي حول هذا الموضوع ، فإن الملف اليدوي هو index.adoc . إنه مكتوب بلغة asciidoc ، والتي تشرح نفسها حقًا عندما تقرأها ، إنها نوع من الشطب. لم أتعلم ذلك مطلقًا ، ومع ذلك كنت أكتب أقسامًا يدوية على ما يرام :) يجب أن يمنحك أي IDE معاينة مباشرة للعمل معها.

تضمين التغريدة

شكرا لك. سوف نلقي نظرة على الفهرس.

في ما يخص:

لست متأكدًا من سبب طرحك لـ javadoc على الرغم من نقصه ؛ لقد لصقت حرفيا الجافادوك ، لذا فهي موجودة.

نعم ، إنه موجود ، لكنه لا يصف أي شيء أكثر مما يمكن قراءته مباشرة من الكود. خاصة أنه لا يصف كيفية تكوينه ، وهذه هي النقطة الأساسية لهذه المشكلة. لقد وجدت الطريقة في الكود ، قرأت javadoc ، لكن هذا كل شيء وبعد أن كافحت لبعض الوقت مع الكود ، والعثور على الاستخدامات وما إلى ذلك ، كان علي أن أطلب منك يا رفاق المساعدة. إذا تمت الإشارة / الإشارة إلى طريقة handle.configure في هذا javadoc (الأفضل مع المثال) ، فسيؤدي ذلك إلى زيادة قيمتها بشكل كبير فيما يتعلق بفهم كيفية تمكين هذه الميزة المحددة.

أعتقد أنك تفتقد الصورة الأكبر. يعد الشيء handle.configure قياسيًا لجميع التكوينات على عناصر Configurable مثل Jdbi و Handle (جنبًا إلى جنب مع getConfig ) ، إنه ليس شيئًا خاصًا لهذا الغرض فقط. يأخذ allowUnusedBindings قيمة منطقية ، وبهذا يجب أن يكون واضحًا جدًا. تتبع الطريقة وكيفية انتشارها نموذج التكوين القياسي الخاص بنا.

حسنًا ، في الواقع ، يبدو أنني أفتقده ، لكن ربما يكون المستخدمون الآخرون قد فقدوه أيضًا. يبدو لي أنه متقدم جدًا ونوع من المعرفة القبلية واضحة للمطورين الأساسيين ولكنها ليست واضحة بالنسبة لنا هنا في البرية. بعد أن وصفته بأنه _نموذج تكوين قياسي _ ذهبت لأقوم بتوثيق JDBI ، وبعد قراءته فيما يتعلق بأشياء التكوين ، لا يزال لدي فكرة موجزة عن كيفية عمله. يتم استخدام طريقة configure مرة واحدة فقط فيما يتعلق بتعيين TupleMappers من Vavr.

إنها جزء من مشكلة أكبر مع عدم وجود جميع الميزات الموضحة في المستند بتفاصيل كافية ، لكننا ، كمستخدمي JDBI ، هنا للمساعدة في تحديد ما هو مفقود والمساعدة في سد الثغرات.

لذلك ، أقترح تغيير javadoc لاحتواء المزيد من التفاصيل ، على سبيل المثال:

/**
 * Sets whether or not an exception should be thrown when any arguments are
 * given to a query but not actually used in it. Unused bindings tend to be bugs or
 * oversights, but can also just be convenient. Defaults to false: unused bindings 
 * are not allowed.<br>
 * <br>
 * It can be changed by configuring {<strong i="10">@link</strong> Configurable} object (e.g. {<strong i="11">@link</strong> Jdbi}
 * or {<strong i="12">@link</strong> Handle}), for example:
 * <pre>
 * handle.configure(SqlStatements.class, s -> s.setUnusedBindingAllowed(true))
 * </pre>
 *
 * <strong i="13">@see</strong> org.jdbi.v3.core.argument.Argument
 * <strong i="14">@see</strong> Handle.configure
 * <strong i="15">@see</strong> Jdbi.configure
 */

سأضيفها بكل سرور ، ولكن يرجى إعلامي إذا كان ما كتبته على ما يرام.

واجهت هذا النقص نفسه بالضبط هذا الصباح. سأقوم بإعداد PR الذي يضيف @AllowUnusedBindings على sqlobject.

المعرفة القبلية واضحة للمطورين الأساسيين ولكنها ليست واضحة لنا هنا في البرية

أود فقط أن أشير إلى أنني عضو أساسي منذ شهرين فقط وكنت مجرد مستخدم عادي مثلك لأكثر من عام قبل ذلك الحين ، لذلك ليس الأمر كما لو كنت خبيرًا في المعرفة الغامضة. 😛 أنا أعرف معظم الأشياء التي أعرفها عن jdbi من خلال تواجدي في نفس الموقف والاستكشاف والنقر فوق واجهة برمجة التطبيقات والواجهات ، مما يتيح لي أساليب تلميح intellij وما شابه ذلك.

لكن نعم ، يجب توثيقه بوضوح لأننا لا نتوقع أن يقوم الجميع بفحص الأجزاء الداخلية لـ jdbi لمعرفة الاستخدام الأساسي. :)

لا أعتقد أننا سنضيف javadoc بالطريقة التي تقترحها. يجب أن يكون شعار التكوين dcoumented في حد ذاته ، ولا يتكرر في كل إعداد تكوين فردي أو يتم تضمينه في أي إعداد تكوين تم اختياره بشكل خاص. يجب أن يشرح كل إعداد تكوين تأثيراته الخاصة فقط.

لدينا قسم على JdbiConfig : http://jdbi.org/#_jdbiconfig ولكنه يركز أكثر على إنشاء تطبيقاتك الخاصة ويتم حشوها في قسم Advanced بالقرب من النهاية. ربما يتعين علينا إضافة قسم "التكوين من منظور المستخدم" في المستندات في قسم سابق؟ هل هذا يعالج هذه الحاجة بشكل أفضل؟

كنت أقرأ من خلال JdbiConfig وكان لدي نفس الانطباع. تم مسح الأمور بعد أن أعطانيTheRealMarnes مثالاً قدمه في التعليق.

شكرًا لك على @AllowUnusedBindings :)

يا رفاق ، أعلم أن هذا يتعارض مع توثيق نموذج التكوين في مكان واحد ، ولكن يُرجى التفكير في إضافة المعلومات في رسالة الاستثناء بنفس الطريقة التي يتم بها هنا:

https://github.com/jdbi/jdbi/blob/1c80a39c6d9d963df9e6bb21e78634f67da47da4/core/src/main/java/org/jdbi/v3/core/Handle.java#L173

سيوفر هذا الشخص الذي أصيب بهذا الاستثناء الكثير من الحفر في رمز :)

أنا أتفق مع هذا القدر ، الاستثناء نفسه يجب أن يلمح إليه.

تمت إضافة تلميح https://github.com/jdbi/jdbi/pull/1428

لقد أضفنا تلميحًا إلى رسالة الخطأ ، بالإضافة إلى وثائق التكوين العامة مع هذا كمثال محدد. نأمل أن يكون هذا إصلاحًا كافيًا ؛ شكرا لاستخدام jdbi :)

شكرا لك ستيفن! يعتني :)

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات

القضايا ذات الصلة

electrum picture electrum  ·  3تعليقات

Shujito picture Shujito  ·  5تعليقات

stevenschlansker picture stevenschlansker  ·  4تعليقات

buremba picture buremba  ·  5تعليقات

Romqa picture Romqa  ·  5تعليقات