قم بتكوين السبات لاستخدام SYS_GUID() الخاص بـ Oracle للمفتاح الأساسي

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

سؤال

أنا أبحث عن طريقة للإسبات لاستخدام Oracle SYS_GUID() وظيفة عند إدراج صفوف جديدة.حاليًا تحتوي جداول قاعدة البيانات الخاصة بي على SYS_GUID() كإعداد افتراضي، لذلك إذا قام السبات ببساطة بإنشاء SQL الذي حذف القيمة التي يجب أن تعمل.

كل شيء يعمل لدي، ولكنه يقوم حاليًا بإنشاء UUID/GUID في التعليمات البرمجية باستخدام منشئ uuid النظام:

@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid")
@Column(name = "PRODUCT_ID", unique = true, nullable = false)
public String getId() {
    return this.productId;
}

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

أنا أستخدم التعليقات التوضيحية للتكوين، ولكن أمثلة تكوين XML رائعة أيضًا.

فيما يلي نموذج لتعريف الجدول (في حال كان الأمر مهمًا):

CREATE TABLE SCHEMA_NAME.PRODUCT
(
    PRODUCT_ID RAW(16) DEFAULT SYS_GUID() NOT NULL,
    PRODUCT_CODE VARCHAR2(10 CHAR) NOT NULL,
    PRODUCT_NAME VARCHAR2(30 CHAR) NOT NULL,
    PRODUCT_DESC VARCHAR2(512 CHAR)
)

تحديث:

نجح حل مات باستخدام "guid"، وهنا تم إنشاء SQL:

Hibernate: 
    select rawtohex(sys_guid()) 
    from dual
Hibernate: 
    insert into PRODUCT
    (PRODUCT_CODE, PRODUCT_DESC, LOB_ID, PRODUCT_NAME, PROVIDER_ID, PRODUCT_ID) 
    values (?, ?, ?, ?, ?, ?)

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

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

المحلول

قد تتمكن من استخدام منشئ "المرشد".يرى هذا المشنور من منتدى السبات .يبدو أنهم أضافوا دعمًا لاستخدام Oracle SYS_GUID() منذ فترة، ولكن توثيق ما زالوا يقولون إنهم يدعمون SQL Server و MySQL فقط.

لم أعمل مع التعليقات التوضيحية لـ JPA حتى الآن، ولكن إليك مثالًا باستخدام تكوين XML:

<id name="PRODUCT_ID">
  <generator class="guid" />
</id>

يحرر: فيما يتعلق بسؤالك الثاني، أعتقد أنك تتساءل لماذا لا يستطيع Hibernate القيام بشيء مثل هذا:

INSERT INTO PRODUCT (PRODUCT_ID, /* etc */)
SELECT SYSGUID(), /* etc */

والسبب هو أن السبات يجب أن يعرف ما هو معرف الكائن.على سبيل المثال، خذ بعين الاعتبار السيناريو التالي:

  1. يمكنك إنشاء كائن منتج جديد وحفظه.تقوم Oracle بتعيين المعرف.
  2. يمكنك فصل المنتج عن جلسة السبات.
  3. يمكنك لاحقًا إعادة إرفاقه وإجراء بعض التغييرات.
  4. أنت الآن تريد الاستمرار في هذه التغييرات.

بدون معرفة المعرف، لا يستطيع Hibernate القيام بذلك.فهو يحتاج إلى المعرف لإصدار بيان UPDATE.لذلك تنفيذ org.hibernate.id.GUIDGenerator يجب عليه إنشاء المعرف مسبقًا، ثم إعادة استخدامه لاحقًا في عبارة INSERT.

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

نصائح أخرى

لدي نفس المهمة التي بداية الموضوع.مع الشكر ل @ مات سولنيت اقتراح أستخدم مثل هذه التعليقات التوضيحية:

@Id
@NotNull
@Column(name = "UUID")
@GenericGenerator(name = "db-uuid", strategy = "guid")
@GeneratedValue(generator = "db-uuid")
private String uuid;
public String getUuid() { return uuid; }
public void setUuid(String uuid) { this.uuid = uuid; }

strategy = "guid" و String النوع هي أجزاء أساسية من الحل.

قبل استمرار الكيانات الجديدة، قم بإسبات إصدار استعلام SQL:

select rawtohex(sys_guid()) from dual

الإعداد الخاص بي:أوراكل 11، السبات 4.3.4.النهائي، الربيع 3.2.x.والميدان هو raw(16) في الجدول للتخزين الفعال وحجم فهرس أقل مما إذا كنت تستخدمه char(32).

عندما أحاول استخدام java.util.UUID كنوع حقل معرف، أحصل على خطأ من Hibernate بشأن استمرار الكيان الجديد (يحاول تعيين String اكتب ل java.util.UUID مجال).

كما أنني أستخدم javax.xml.bind.DatatypeConverter للاستعلامات غير المتعلقة بالإسبات (مساعدي Spring JDBC)، لتمرير التحويل إلى byte[]:

String query = "insert into TBL (UUID, COMPANY) values (:UUID, :COMPANY)";
MapSqlParameterSource parameters = new MapSqlParameterSource()
    .addValue("COMPANY", repo.getCompany())
    .addValue("UUID", DatatypeConverter.parseHexBinary(signal.getUuid()));
namedJdbcTemplate.update(query, parameters);

لاستخراج:

ResultSet rs;
sig.id = DatatypeConverter.printHexBinary(rs.getBytes("UUID"));

تحصل جميع وحدات التحكم على الويب على رموز مثل:

025131763FB19522E050010A106D11E9

بدون {, -, } الأحرف (التمثيل المعتاد لـ UUID هو {a-b-c-d-x-y} اذا تذكرت).هذا التمثيل هو بالفعل ترميز URL نظيف وآمن.لا تحتاج إلى التنفيذ PropertyEditor أو Convertor ل String يكتب:

@RequestMapping(value = {"/signal/edit/{id}.htm"}, method = RequestMethod.POST)
public String handleEditRequest(
        @PathVariable("id") String id,

قارن مع محاولة الاستخدام الفاشلة jaa.util.UUID, حيث أحتاج أن أكتب:

@Component
public static class UUIDPropertyEditor extends PropertyEditorSupport {
    @Override
    public void setAsText(final String str) {
        if (str == null || str.isEmpty()) {
            setValue(null);
            return;
        }
        setValue(UUID.fromString(str));
    }
}
private @Autowired UUIDPropertyEditor juuidPE;

@InitBinder
public void initBinder(WebDataBinder binder) {
    binder.registerCustomEditor(UUIDPropertyEditor.class, juuidPE);
}

لكي تستخدم:

@PathVariable("id") UUID id,

أعتقد أنه يمكنك القيام بذلك عن طريق ضبط المولد على الوضع الأصلي.لست متأكدًا حقًا من كيفية القيام بذلك في Hibernate ولكن في NHibernate ستفعل شيئًا كهذا في XML:

<id column="PRODUCT_ID">
  <generator class="native"/>
</id>
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top