Flazzo memiliki fokus utama untuk menambah nilai bisnis Anda.

Blog

Daftar Keinginan JPA 2.0 saya

16807366-thumb.jpg
Blog

Daftar Keinginan JPA 2.0 saya

[ad_1]

(Artikel awalnya diterbitkan pada Juni 2008)

Sejauh ini kami telah menikmati persistensi yang mudah digunakan APLIKASI 1.0. Memang benar JPA 1.0 memiliki beberapa keterbatasan, namun sekarang teman-teman kita di JSR-317 bekerja keras untuk memberi kami standar kegigihan yang lebih baik untuk Java.

Saya adalah bagian dari OpenXava proyek, OpenXava menghasilkan aplikasi lengkap hanya menggunakan kelas Java yang dianotasi dengan JPA sebagai sumber, sehingga spesifikasi JPA 2.0 sangat penting untuk OpenXava. Tetapi spesifikasi JPA 2.0 juga sangat penting untuk semua pengembang Java, karena ekspresi model kami akan berbanding lurus dengan ekspresi JPA 2.0 yang baru.

JPA 2.0 memiliki banyak fitur baru yang keren, dan beberapa di antaranya sangat saya sukai. Anda dapat melihatnya secara unduh draf dari spesifikasi JCP, atau dengan membaca dua ( dan ) artikel dari di sini di JavaLobby.

Tetapi artikel ini membahas tentang fitur yang hilang dari JPA 2.0. Saya akan memberi tahu Anda daftar keinginan saya untuk JPA 2.0. Silakan jika Anda menyukai beberapa fitur, kirimkan umpan balik Anda. Mungkin kita bisa mempengaruhi JPA 2.0 yang baru.

Ini daftar keinginan saya untuk JPA 2.0:

  1. Pembatasan dalam metode callback.
  2. @ManyToOne, @SatuToMany Dan @ElementCollection implisit.
  3. Pengonversi.
  4. Metode di EntityManagerFactory untuk mendapatkan daftar semua entitas.
  5. Kunci komposit tanpa kelas kunci.
  6. UUID sebagai GeneratedType untuk @GeneratedValue.
  7. Nilai pemulihan default untuk @ManyToOne.
  8. @ElementCollection.
  9. Properti memenuhi syarat di @Dipesan oleh.

1. Batasan dalam metode callback

Saya menunggu JPA 2.0 hanya untuk melihat paragraf berikutnya 3.5 Pendengar entitas dan metode callback dihapus dari spesifikasi:

Secara umum, metode siklus hidup aplikasi portabel tidak boleh memanggil EntityManager
atau operasi kueri, mengakses instance entitas lain, atau memodifikasi hubungan dalam konteks persistensi yang sama.

Tapi, dia masih ada. Kengerian!

Setiap kali pengembang saya perlu menggunakan metode panggilan balik, itu untuk meminta atau menyimpan data. Dan mereka harus menggunakan JPA untuk melakukan itu. Dan itu hanya dilarang. Kesimpulan setelah beberapa waktu bekerja dengan JPA adalah bahwa metode callback tidak berguna.

Dengan kata lain, skenario ini tipikal:

  • Untuk menghapus beberapa entitas, saya perlu memeriksa apakah ada data, dan kami ingin melakukannya menggunakan kueri JPA.
  • Saat entitas disimpan, beberapa entitas lain harus dibuat dan disimpan secara otomatis, dan kami ingin menggunakan kueri JPA untuk melakukan ini.

Mengapa tidak menghapus batasan ini dari @PrePersist Atau @PreRemove setidaknya? Atau, kita dapat membuat anotasi lain (selalu dijalankan sebelum flush) yang dapat kita gunakan Mempertanyakan Dan Manajer Entitas.

2. @ManyToOne, @OneToMany, dan @ElementCollection tersirat

Saran lain ini adalah itu @ManyToOne, @SatuToMany, Dan @ElementCollection bisa tersirat, sama seperti @Dasar anotasi sudah ada di JPA 1.0. Artinya, alih-alih menulis:

@Entity

public class Invoice {

    ...

    

    @ManyToOne

    private Customer customer;

    @OneToMany (mappedBy="invoice")

    private Collection<Delivery> deliveries;

} 

Kita dapat menulis kode berikut:

@Entity

public class Invoice {

    ...

    

    private Customer customer;

    private Collection<Delivery> deliveries;

}

Dan JPA akan menganggap @ManyToOne untuk pelanggan dan @OneToMany untuk pengiriman.
Pendekatan ini setidaknya memiliki dua keuntungan:

  1. Migrasi mudah dari kode non-JPA ke JPA.
  2. Lebih sedikit kode untuk ditulis di tangan programmer.

3. Pengonversi

Di dunia saya, adalah umum untuk mengembangkan aplikasi Java terhadap basis data lama, yang dalam banyak kasus dirancang oleh programmer RPG atau COBOL, ketika tipe data tidak sesuai dengan kelas model Java yang tepat. Misalnya, beberapa database menggunakan 3 nilai numerik untuk datanya, atau VARCHAR dengan nilai arbitrer yang dapat dipetakan ke boolean. Mekanisme konversi tipe standar diperlukan untuk skenario umum ini.

Hibernasi jenis nilai khusus atau konverter OpenXava 2 (untuk nilai tunggal, untuk banyak nilai) keduanya adalah opsi yang valid.

Fitur berguna lainnya adalah kemampuan untuk mendeklarasikan kebijakan konversi default. Lihatlah konverter default OpenXava.

4. Metode dalam EntityManagerFactory untuk mendapatkan daftar semua entitas

Dalam proyek OpenXava, kita memerlukan kode berikut:

private static Collection obtainManagedClassNamesUsingHibernate() {
    // The next code is Hibernate dependent.
    // This code has to be modified in order to work with Glassfish, OpenJPA, etc.       
    EntityManager manager = XPersistence.createManager();
    org.hibernate.impl.SessionImpl impl = (org.hibernate.impl.SessionImpl) manager.getDelegate();
    Collection result = impl.getSessionFactory().getAllClassMetadata().keySet();
    manager.close();
    return result;
}

Seperti yang Anda lihat, kode ini jelek dan bergantung pada implementasi Hibernasi. OpenXava adalah kerangka kerja untuk membuat aplikasi bisnis dari POJO yang dianotasi dengan JPA. Agar berfungsi, setidaknya perlu diketahui daftar entitas yang dikelola oleh JPA.

Memiliki cara standar untuk melakukan ini akan menyenangkan. Mungkin metode di EntityManagerFactory.

Juga, mendapatkan metadata tanpa terhubung ke database akan sangat luar biasa.

5. Kunci komposit tanpa kelas kunci

Idenya adalah kita dapat mendefinisikan entitas dengan kunci komposit dengan cara sederhana ini:

@Entity

public class Invoice {

    @Id 

    private int year;

    

    @Id 

    private int number;

    ...

}

Tidak lagi. TIDAK @IdClass. TIDAK @EmbeddedId.

Satu-satunya tempat yang kita perlukan untuk kelas kunci adalah untuk menemukan() metode dari Manajer Entitas. Dalam hal ini, kita dapat menggunakan beberapa pendekatan berikut:

1. Peta

Map key = new Map();
key.put("year", 2008);
key.put("number", 3);
Invoice invoice = manager.find(Invoice.class, key);

2. Meja

Invoice invoice = manager.find(Invoice.class, new Object[] { 2008, 3} );

3. Vararg

Invoice invoice = manager.find(Invoice.class, 2008, 3);

4. Segarkan

Invoice invoice = new Invoice();
invoice.setYear(2008);
invoice.setNumber(3);
manager.refresh(invoice);

Favorit saya adalah 4.

6. UUID sebagai GeneratedType untuk @GeneratedValue

Mengapa UUID tidak disertakan sebagai GeneratedType untuk @GeneratedValue?

Hibernasi JPA menyertakannya. Di organisasi saya, kami mengembangkan aplikasi yang perlu dijalankan di AS/400, Informix, Postgres, MS SQL, dan MySQL. Menggunakan UUID untuk menghasilkan pengenal sangat berguna bagi kami karena sangat mudah untuk bermigrasi dari satu produk database ke produk lainnya. Saya bertanya-tanya mengapa itu tidak termasuk dalam JPA.

7. Nilai pemulihan default untuk @ManyToOne

Proposal untuk JPA 2.0 ini adalah tentang mengubah nilai default ManyToOne(fetch ), atau bahkan kemampuan yang lebih baik untuk mendeklarasikannya dalam file orm.xml, atau persistence.xml:

ITU pendekatan yang disarankan adalah menggunakan LAZY pada semua definisi pemulihan statis dan ganti pilihan ini secara dinamis melalui JPA-QL. JPA-QL memiliki kata kunci pengambilan yang memungkinkan Anda mengesampingkan kemalasan selama kueri tertentu. Ini sangat berguna untuk meningkatkan kinerja dan diputuskan berdasarkan kasus per kasus.

(ekstrak dari Hibernasi dokumentasi JPA)

Sungguh, dalam banyak kasus, jauh lebih baik menggunakan pemulihan LAZY daripada pemulihan EAGER. Ini mengharuskan developer untuk selalu menulis fetch=FetchType.LAZY ke @ManyToOne. Lebih baik cara yang paling umum dan nyaman adalah cara default.

Artinya, proposisi saya adalah itu ambil di @ManyToOne akan default ke LAZY. Akan lebih baik lagi mendeklarasikan nilai default untuk pemulihan di ManyToOne di persistence.xml atau orm.xml. Dengan cara ini, kami dapat memutuskan strategi pencarian referensi kami secara global.

8. @ElementCollection

Menambahkan koleksi bawaan ke JPA 2.0 adalah ide yang sangat, sangat bagus. Sejauh ini kami harus menggunakan kumpulan entitas sebagai alternatif. Tapi anotasi untuk menandainya benar-benar jelek:

@ElementCollection 
protected Set<String> nickNames = new HashSet(); 

Itu jelek. Mengapa tidak:

@ManyToOne @Embedded
protected Set<String> nickNames = new HashSet(); 

Atau bahkan lebih baik:

@Embedded
protected Set<String> nickNames = new HashSet(); 

Menariknya, OpenXava memiliki anotasi @AsEmbedded yang dapat diterapkan pada referensi dan koleksi.

9. Properti yang memenuhi syarat di @OrderBy

Properti yang memenuhi syarat di OrderBy terkadang diperlukan. Saya ingin menulis sesuatu seperti ini:

@OneToMany (mappedBy="invoice", cascade=CascadeType.REMOVE)
@OrderBy("product.description desc")
private Collection<InvoiceDetail> details;

Atau Detail faktur memiliki referensi produk:

@Entity
public class InvoiceDetail {

    @ManyToOne(fetch=FetchType.LAZY, optional=false)
    private Product product;

    ...

}

Nyatanya, OpenXava menambahkan dukungan ini dengan anotasi XOrderBy miliknya hanya untuk mendukung properti yang memenuhi syarat.

Kesimpulan

Apa pendapat Anda tentang proposal ini?

Jika Anda menyukai beberapa di antaranya, kirimkan komentar Anda ke JSR.

Referensi

[ad_2]