هل التعيين الوظيفي للعلائقية أسهل من التعيين العلائقي للكائن؟

StackOverflow https://stackoverflow.com/questions/218190

سؤال

تمت مناقشة رسم الخرائط الارتباطية للكائنات بشكل جيد، بما في ذلك هنا.لدي خبرة في بعض الأساليب والمزالق والتسويات.يبدو أن الحل الحقيقي يتطلب إجراء تغييرات على OO أو النماذج العلائقية نفسها.

في حالة استخدام لغة وظيفية، هل تظهر نفس المشكلة؟يبدو لي أن هذين النموذجين يجب أن يتناسبا معًا بشكل أفضل من OO وRDBMS.يبدو أن فكرة التفكير في مجموعات في نظام RDBMS تتناغم مع التوازي التلقائي الذي يبدو أن الأساليب الوظيفية تعد به.

هل لدى أي شخص أي آراء أو رؤى مثيرة للاهتمام؟ما هو الوضع في هذه الصناعة؟

هل كانت مفيدة؟

المحلول

ووالمعاملات، من نوع البيانات عدم التطابق والترجمة الاستعلام الآلي واشياء من هذا القبيل <لأ href = "http://ayende.com/Blog/archive/2006/05/02/CombatingTheSelectN1ProblemInNHibernate تمديد المشاكل الصعبة توسيع قاعدة البيانات العلائقية .aspx اتصال "يختلط =" noreferrer "> N + 1 اختار أن مشاكل الأساسية من ترك النظام العلائقي و- في رأيي - لا تتغير عن طريق تغيير نموذج البرمجة تلقي

نصائح أخرى

ما هو الغرض من ORM؟

الغرض الرئيسي من استخدام ORM هو الربط بين النموذج المتصل بالشبكة (اتجاه الكائن، والرسوم البيانية، وما إلى ذلك) والنموذج العلائقي.والفرق الرئيسي بين النموذجين بسيط بشكل مدهش.يتعلق الأمر بما إذا كان الآباء يشيرون إلى الأطفال (النموذج الشبكي) أو يشير الأطفال إلى الوالدين (النموذج العلائقي).

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

كيف يمكن لـ SQL معالجة المشكلات التي نواجهها مع ORMs؟

على وجه الخصوص، البيان الثالث يحاول معالجة أوجه القصور في لغة SQL والجبر العلائقي من خلال السماح بالمجموعات المتداخلة، والتي تم تنفيذها في مجموعة متنوعة من قواعد البيانات، بما في ذلك:

  • أوراكل (ربما التطبيق الأكثر تطوراً)
  • PostgreSQL (إلى حدٍ ما)
  • إنفورميكس
  • خادم SQL، MySQL، الخ.(من خلال "المحاكاة" عبر XML أو JSON)

في رأيي، إذا نفذت كافة قواعد البيانات معيار SQL MULTISET() المشغل (على سبيل المثالكما تفعل Oracle)، لن يستخدم الأشخاص ORMs لرسم الخرائط (ربما لا يزال من أجل استمرارية الرسم البياني للكائنات)، لأنه يمكنهم إنشاء مجموعات متداخلة مباشرة من داخل قواعد البيانات، على سبيل المثال.هذا الاستعلام:

SELECT actor_id, first_name, last_name,
  MULTISET (
    SELECT film_id, title
    FROM film AS f
    JOIN film_actor AS fa USING (film_id)
    WHERE fa.actor_id = a.actor_id
  ) AS films
FROM actor AS a

سيؤدي إلى جميع الممثلين وأفلامهم كمجموعة متداخلة، بدلاً من نتيجة ربط غير طبيعية (حيث يتم تكرار الممثلين لكل فيلم).

النموذج الوظيفي في جانب العميل

إن السؤال عما إذا كانت لغة البرمجة الوظيفية من جانب العميل أكثر ملاءمة لتفاعلات قاعدة البيانات هو سؤال متعامد حقًا.تساعد ORMs في استمرارية الرسم البياني للكائنات، لذلك إذا كان نموذج جانب العميل الخاص بك عبارة عن رسم بياني، وتريده أن يكون رسمًا بيانيًا، فستحتاج إلى ORM، بغض النظر عما إذا كنت تتعامل مع هذا الرسم البياني باستخدام لغة برمجة وظيفية.

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

مثال في جافا باستخدام جووك من هذا بلوق وظيفة ممكن ان يكون:

// Higher order, SQL query producing function:
public static ResultQuery<Record2<String, String>> actors(Function<Actor, Condition> p) {
    return ctx.select(ACTOR.FIRST_NAME, ACTOR.LAST_NAME)
              .from(ACTOR)
              .where(p.apply(ACTOR)));
}

يؤدي هذا الأسلوب إلى تركيب أفضل بكثير لعبارات SQL مما لو تم تجريد لغة SQL بواسطة بعض ORM، أو إذا تم استخدام طبيعة SQL الطبيعية "المعتمدة على السلسلة".يمكن الآن استخدام الوظيفة المذكورة أعلاه على سبيل المثال.مثله:

// Get only actors whose first name starts with "A"
for (Record rec : actors(a -> a.FIRST_NAME.like("A%")))
    System.out.println(rec);

تجريد FRM عبر SQL

تحاول بعض FRMs التجريد عبر لغة SQL، عادةً للأسباب التالية:

  • يزعمون أن لغة SQL ليست قابلة للتركيب بدرجة كافية (ينفي jOOQ ذلك، فمن الصعب جدًا الحصول عليها بشكل صحيح).
  • يزعمون أن مستخدمي واجهة برمجة التطبيقات (API) معتادون أكثر على واجهات برمجة تطبيقات المجموعة "الأصلية"، لذلك على سبيل المثال. JOIN يتم ترجمته إلى flatMap() و WHERE يتم ترجمته إلى filter(), ، إلخ.

للإجابة على سؤالك

FRM ليست "أسهل" من ORM، فهي تحل مشكلة مختلفة.في الواقع، لا تحل FRM أي مشكلة على الإطلاق، لأن SQL، كونها لغة برمجة تعريفية في حد ذاتها (والتي لا تختلف كثيرًا عن البرمجة الوظيفية)، تعد مطابقة جيدة جدًا للغات برمجة العميل الوظيفية الأخرى.لذلك، إذا كان هناك أي شيء على الإطلاق، فإن FRM يقوم ببساطة بسد الفجوة بين SQL وDSL الخارجي ولغة العميل الخاصة بك.

(أعمل في الشركة خلف جووك, ، لذا فإن هذه الإجابة متحيزة)

هذا يعتمد على احتياجاتك

  1. إذا كنت تريد التركيز على هياكل البيانات، فاستخدم ORM مثل JPA/Hibernate
  2. إذا كنت تريد تسليط الضوء على العلاجات، قم بإلقاء نظرة على مكتبات FRM:QueryDSL أو Jooq
  3. إذا كنت بحاجة إلى ضبط طلبات SQL الخاصة بك على قواعد بيانات محددة، فاستخدم JDBC وطلبات SQL الأصلية

تكمن قوة تقنيات "رسم الخرائط العلائقية" المختلفة في قابلية النقل:عليك التأكد من تشغيل التطبيق الخاص بك على معظم قواعد بيانات ACID.وإلا، فسوف تتمكن من التعامل مع الاختلافات بين لهجات SQL المختلفة عند كتابة طلبات SQL يدويًا.

بالطبع يمكنك تقييد نفسك بمعيار SQL92 (ثم القيام ببعض البرمجة الوظيفية) أو يمكنك إعادة استخدام بعض مفاهيم البرمجة الوظيفية مع أطر عمل ORM

تم بناء نقاط قوة ORM على كائن جلسة والذي يمكن أن يكون بمثابة عنق الزجاجة:

  1. فهو يدير دورة حياة الكائنات طالما أن معاملة قاعدة البيانات الأساسية قيد التشغيل.
  2. فهو يحافظ على تعيين واحد لواحد بين كائنات Java الخاصة بك وصفوف قاعدة البيانات الخاصة بك (ويستخدم ذاكرة تخزين مؤقت داخلية لتجنب الكائنات المكررة).
  3. يقوم تلقائيًا بالكشف عن تحديثات الارتباط والكائنات المعزولة المراد حذفها
  4. فهو يتعامل مع المشكلات المتزامنة بقفل متفائل أو متشائم.

ومع ذلك، فإن نقاط قوتها هي أيضًا نقاط ضعفها:

  1. يجب أن تكون الجلسة قادرة على مقارنة الكائنات لذا تحتاج إلى تنفيذ أساليب يساوي/hashCode.ولكن يجب أن تكون مساواة الكائنات متجذرة في "مفاتيح الأعمال" وليس معرف قاعدة البيانات (الكائنات العابرة الجديدة ليس لها معرف قاعدة بيانات!).ومع ذلك، فإن بعض المفاهيم المتجسدة ليس لها مساواة في الأعمال (عملية على سبيل المثال).يعتمد الحل الشائع على المعرفات الفريدة العمومية (GUIDs) التي تميل إلى إزعاج مسؤولي قاعدة البيانات.

  2. يجب أن تتغير علاقة التجسس على الجلسة ولكن قواعد التعيين الخاصة بها تدفع إلى استخدام مجموعات غير مناسبة لخوارزميات العمل.في وقت ما قد ترغب في استخدام HashMap ولكن ORM سيتطلب أن يكون المفتاح "كائن مجال منسق" آخر بدلاً من كائن خفيف آخر...ثم يتعين عليك تنفيذ المساواة بين الكائنات على كائن المجال الغني الذي يعمل كمفتاح ...لكن لا يمكنك ذلك لأن هذا الكائن ليس له نظير في عالم الأعمال.لذلك عليك الرجوع إلى القائمة البسيطة التي يتعين عليك تكرارها (وتنتج عنها مشكلات في الأداء).

  3. أحيانًا تكون واجهة برمجة تطبيقات ORM غير مناسبة للاستخدام في العالم الحقيقي.على سبيل المثال، تحاول تطبيقات الويب الواقعية فرض عزل الجلسة عن طريق إضافة بعض عبارات "WHERE" عند جلب البيانات...ثم "Session.get(id)" لا يكفي وتحتاج إلى اللجوء إلى DSL أكثر تعقيدًا (HSQL، Criteria API) أو العودة إلى SQL الأصلي

  4. تتعارض كائنات قاعدة البيانات مع كائنات أخرى مخصصة لأطر عمل أخرى (مثل أطر عمل OXM = تعيين كائن/XML).على سبيل المثال، إذا كانت خدمات REST الخاصة بك تستخدم مكتبة جاكسون لإجراء تسلسل لكائن أعمال.لكن جاكسون هذا يعين بالضبط شخصًا إسباتيًا.ثم إما أن تندمج على حد سواء والاقتران القوي بين واجهة برمجة التطبيقات الخاصة بك وظهر قاعدة البيانات الخاصة بك أو يجب عليك تنفيذ ترجمة وجميع التعليمات البرمجية التي تم حفظها من ORM تضيع هناك ...

على الجانب الآخر، FRM عبارة عن مقايضة بين "تعيين الكائنات العلائقية" (ORM) واستعلامات SQL الأصلية (مع JDBC)

أفضل طريقة لشرح الاختلافات بين FRM وORM هي اعتماد نهج DDD.

  • يُمكّن التعيين العلائقي للكائنات من استخدام "كائن المجال الغني" وهي فئات Java التي تكون حالاتها قابلة للتغيير أثناء معاملة قاعدة البيانات
  • يعتمد رسم الخرائط العلائقية الوظيفية على "كائنات المجال الضعيفة" غير القابلة للتغيير (لدرجة أنه يتعين عليك استنساخ كائن جديد في كل مرة تريد فيها تغيير محتواه).

إنها تطلق القيود التي وضعت على جلسة ORM وتعتمد معظم الوقت على DSL على SQL (حتى لا يهم قابلية النقل) ولكن من ناحية أخرى ، عليك أن تنظر في تفاصيل المعاملة ، وقضايا التزامن

List<Person> persons = queryFactory.selectFrom(person)
  .where(
    person.firstName.eq("John"),
    person.lastName.eq("Doe"))
  .fetch();

وكنت اعتقد ظيفية لرسم الخرائط العلائقية ينبغي أن يكون من الأسهل لإنشاء واستخدام من OO إلى RDBMS. طالما كنت الاستعلام فقط قاعدة البيانات، وهذا هو. أنا لا أرى حقا (حتى الآن) كيف يمكن أن تفعل تحديث قاعدة البيانات من دون آثار جانبية بطريقة لطيفة.

والمشكلة الرئيسية هي أرى الأداء. ليست مصممة RDMS اليوم ليتم استخدامها مع الاستفسارات الوظيفية، وربما تتصرف بشكل سيئ في عدد غير قليل من الحالات.

وأنا لم تفعل الخرائط وظيفية العلائقية، <م> في حد ذاته ، ولكن لقد استخدمت تقنيات البرمجة الوظيفية لتسريع الوصول إلى RDBMS.

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

ويبدو معقولا. ولكن المشكلة مع ذلك هو أنه يمكن الحصول على بطيئا جدا. إذا تطلب حساب الخاص بيان SQL آخر إلى جانب استعلام التحديث نفسها، أو حتى يحتاج إلى أن يتم ذلك في تطبيق القانون، لديك حرفيا إلى (إعادة) البحث عن السجلات التي كنت تقوم بتغيير بعد احتساب لتخزين النتائج في الصفوف الصحيحة .

ويمكنك الحصول على حول هذا ببساطة عن طريق إنشاء جدول جديد للحصول على نتائج. بهذه الطريقة، يمكنك فقط دائما إدراج بدلا من التحديث. كنت في نهاية المطاف وجود جدول آخر، تكرار المفاتيح، ولكنك لم تعد بحاجة إلى النفايات الفضائية على أعمدة تخزين NULL - قمت بتخزين فقط ما لديك. يمكنك ثم الانضمام نتائجك في النهائي الخاص بك حدد.

وأنا (أ ب) استخدمت RDBMS بهذه الطريقة، وانتهى الأمر كتابة البيانات SQL التي بدت في الغالب مثل هذا ...

create table temp_foo_1 as select ...;
create table temp_foo_2 as select ...;
...
create table foo_results as
  select * from temp_foo_n inner join temp_foo_1 ... inner join temp_foo_2 ...;

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

وأتصور هذا من شأنه أن يسمح أيضا لالتوازي أسهل بكثير.

ورفع معنوياته إضافية هي أن أنواع أعمدة الجداول التي تم إنشاؤها بهذه الطريقة لا يجب أن تكون محددة لأنها الاستدلال على ذلك من الأعمدة انهم اختيار من بينها.

وكنت أعتقد أنه، كما ذكر سام، إذا يجب أن يتم تحديث DB، ومشكلات التوافق نفسها يجب أن تواجه كما هو الحال مع OO العالم. الطبيعة الوظيفية للبرنامج ربما يمكن أن يكون حتى أكثر من ذلك بقليل تعقيدا من طبيعة الكائن بسبب حالة البيانات والمعاملات وغيرها من RDBMS.

ولكن للقراءة، فإن لغة وظيفية يكون أكثر طبيعية مع بعض المجالات المشكلة (كما يبدو أن بغض النظر عن DB)

ووظيفية <-> يجب أن يكون رسم الخرائط RDBMS عدم وجود فروق كبيرة لOO <-> RDMBS تعيينات. ولكن أعتقد أن ذلك يعتمد كثيرا على أي نوع من أنواع البيانات التي تريد استخدامها، إذا كنت ترغب في تطوير برنامج مع علامة تجارية مخطط DB جديد أو أن تفعل شيئا ضد DB مخطط تراث، الخ ..

ووالجلب كسول الخ للجمعيات على سبيل المثال ربما يكون من الممكن تنفيذها بشكل جيد جدا مع بعض التقييم كسول ذات الصلة ب المفاهيم. (على الرغم من أنها يمكن القيام به بشكل جيد جدا مع OO أيضا)

وتحرير: مع بعض غوغلينغ وجدت HaskellDB (مكتبة SQL ل هاسكل) - قد يكون من المفيد محاولة

يمكن دمج قواعد البيانات والبرمجة الوظيفية.

على سبيل المثال:

Clojure هي لغة برمجة وظيفية تعتمد على نظرية قواعد البيانات العلائقية.

               Clojure -> DBMS, Super Foxpro
                   STM -> Transaction,MVCC
Persistent Collections -> db, table, col
              hash-map -> indexed data
                 Watch -> trigger, log
                  Spec -> constraint
              Core API -> SQL, Built-in function
              function -> Stored Procedure
             Meta Data -> System Table

ملحوظة:في أحدث المواصفات 2، المواصفات أشبه بـ RMDB.يرى: المواصفات-alpha2 ويكي:مخطط واختيار

أنا أؤيد:بناء نموذج بيانات علائقية أعلى خريطة التجزئة لتحقيق مزيج من مزايا NoSQL وRMDB.هذا في الواقع تطبيق عكسي لـ posgtresql.

كتابة البط:إذا كانت تبدو مثل البطة وتصدر صوتًا مثل البطة، فلا بد أنها بطة.

إذا كان نموذج بيانات clojure مثل RMDB، ومرافق clojure مثل RMDB ومعالجة بيانات clojure مثل RMDB، فيجب أن يكون clojure هو RMDB.

Clojure هي لغة برمجة وظيفية تعتمد على نظرية قواعد البيانات العلائقية

كل شيء هو RMDB

تنفيذ نموذج البيانات العلائقية والبرمجة بناءً على خريطة التجزئة (NoSQL)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top