Membuat, Mendapatkan, dan Menghapus Data di JDO

Menyimpan objek data JDO ke datastore sangat mudah dilakukan. Anda hanya perlu memanggil metode makePersistent() dari instance PersistenceManager. Implementasi JDO App Engine menggunakan kolom kunci utama objek untuk melacak entity datastore yang sesuai dengan objek data, dan dapat membuat kunci secara otomatis untuk objek baru. Anda dapat menggunakan kunci untuk mengambil entity dengan cepat, dan dapat mengonstruksi kunci dari nilai yang diketahui (seperti ID akun).

Membuat Objek Persisten

Untuk menyimpan objek data sederhana di datastore, panggil metode makePersistent() PersistenceManager, dan meneruskannya ke instance.

PersistenceManager pm = PMF.get().getPersistenceManager();

Employee e = new Employee("Alfred", "Smith", new Date());

try {
    pm.makePersistent(e);
} finally {
    pm.close();
}

Panggilan ke makePersistent() bersifat sinkron, dan tidak ditampilkan hingga objek disimpan dan indeks diperbarui.

Untuk menyimpan beberapa objek di JDO, panggil metode makePersistentAll(...) dengan Collection object. Metode ini akan menggunakan satu operasi simpan batch tingkat rendah yang lebih efisien dibandingkan serangkaian pemanggilan makePersistent(...) individual.

Catatan: Jika salah satu kolom persisten objek data merupakan referensi ke objek data persisten lainnya, dan salah satu objek tersebut belum pernah disimpan atau diubah sejak dimuat, objek yang direferensikan juga akan disimpan ke datastore. Lihat Hubungan.

Kunci

Setiap entity memiliki kunci yang unik di App Engine. Kunci lengkap menyertakan beberapa informasi, termasuk ID aplikasi, jenis, dan ID entitas. (Kunci juga berisi informasi tentang entity group; lihat Transaksi untuk informasi selengkapnya.)

Kunci objek disimpan dalam kolom pada instance. Anda mengidentifikasi kolom kunci utama menggunakan anotasi @PrimaryKey.

Aplikasi dapat menyediakan bagian ID dari kunci sebagai string ketika objek dibuat, atau memungkinkan datastore menghasilkan ID numerik secara otomatis. Kunci lengkap harus unik di seluruh entity di datastore. Dengan kata lain, sebuah objek harus memiliki ID yang unik di semua objek dengan jenis yang sama dan dengan induk entity group yang sama (jika ada). Anda dapat memilih perilaku kunci yang diinginkan menggunakan jenis kolom dan anotasi.

Jika class digunakan sebagai class "turunan" dalam hubungan, kolom kunci harus berisi jenis yang mampu mewakili induk entity group: baik instance Key maupun nilai Key yang dienkode sebagai string. Lihat Transaksi untuk informasi selengkapnya tentang entity group, dan Hubungan untuk informasi selengkapnya tentang hubungan.

Tips: Jika aplikasi membuat objek baru lalu memberikan ID string yang sama seperti objek lain dari jenis yang sama (dan induk entity group yang sama), objek baru yang disimpan akan menimpa objek lain dalam datastore. Untuk mendeteksi apakah ID string sudah digunakan sebelum membuat objek baru, Anda dapat menggunakan transaksi untuk mencoba mendapatkan entity dengan ID tertentu, lalu membuatnya jika ID string belum digunakan. Lihat Transaksi.

Ada empat jenis kolom kunci utama:

Long

Bilangan bulat panjang (java.lang.Long), ID entitas yang dibuat secara otomatis oleh datastore. Gunakan ini untuk objek tanpa induk entity group yang ID-nya harus dibuat secara otomatis oleh datastore. Kolom kunci long pada instance diisi saat instance disimpan.

import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;

// ...
    @PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    private Long id;
String yang Tidak Dienkode

String (java.lang.String), ID entitas ("nama kunci") yang diberikan oleh aplikasi saat objek dibuat. Gunakan ini untuk objek tanpa induk entity group yang ID-nya harus diberikan oleh aplikasi. Aplikasi menetapkan kolom ini ke ID yang diinginkan sebelum menyimpan.

import javax.jdo.annotations.PrimaryKey;

// ...
    @PrimaryKey
    private String name;
Key

Instance Key (com.google.appengine.api.datastore.Key). Nilai kunci mencakup kunci induk entity group (jika ada) dan ID string yang ditetapkan aplikasi atau ID numerik yang dihasilkan sistem. Untuk membuat objek dengan ID string yang ditetapkan aplikasi, Anda harus membuat nilai Key dengan ID dan menetapkan kolom ke nilai. Untuk membuat objek dengan ID numerik yang ditetapkan sistem, Anda harus membiarkan kolom kunci null. (Untuk informasi tentang cara menggunakan induk entity group, lihat Transaksi.)

import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;
import com.google.appengine.api.datastore.Key;

// ...
    @PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    private Key key;

    public void setKey(Key key) {
        this.key = key;
    }

Aplikasi dapat membuat instance Key menggunakan class KeyFactory:

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;

// ...
        Key key = KeyFactory.createKey(Employee.class.getSimpleName(), "Alfred.Smith@example.com");
        Employee e = new Employee();
        e.setKey(key);
        pm.makePersistent(e);
Key sebagai String yang Dienkode

Serupa dengan Key, tetapi nilainya merupakan bentuk string kunci yang dienkode. Kunci string yang dienkode memungkinkan Anda menulis aplikasi secara portabel dan tetap memanfaatkan entity group datastore App Engine.

import javax.jdo.annotations.Extension;
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;

// ...
    @PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    @Extension(vendorName="datanucleus", key="gae.encoded-pk", value="true")
    private String encodedKey;

Aplikasi dapat mengisi nilai ini sebelum menyimpan menggunakan kunci dengan nama, atau dapat membiarkannya null. Jika kolom kunci yang dienkode null, kolom tersebut akan diisi dengan kunci yang dihasilkan sistem saat objek disimpan.

Instance Key dapat dikonversi ke dan dari representasi string yang dienkode menggunakan metode KeyFactory keyToString() dan stringToKey().

Saat menggunakan string kunci yang dienkode, Anda dapat memberikan akses ke string atau ID numerik objek dengan kolom tambahan:

    @PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    @Extension(vendorName="datanucleus", key="gae.encoded-pk", value="true")
    private String encodedKey;

    @Persistent
    @Extension(vendorName="datanucleus", key="gae.pk-name", value="true")
    private String keyName;

    // OR:

    @Persistent
    @Extension(vendorName="datanucleus", key="gae.pk-id", value="true")
    private Long keyId;

Kolom "gae.pk-name" dapat ditetapkan ke nama kunci sebelum menyimpan objek. Saat objek disimpan, kolom kunci yang dienkode akan diisi dengan kunci lengkap yang menyertakan nama kunci. Jenisnya harus String.

Kolom "gae.pk-id" diisi saat objek disimpan, dan tidak dapat diubah. Jenisnya harus Long.

Saat objek baru dengan kunci yang dihasilkan (kolom kunci yang menggunakan valueStrategy = IdGeneratorStrategy.IDENTITY) dibuat, nilai kuncinya dimulai dengan null. Kolom kunci diisi saat objek ditulis ke datastore. Jika Anda menggunakan transaksi, objek akan ditulis saat transaksi di-commit. Jika tidak, objek akan ditulis saat metode makePersistent() dipanggil ketika objek sedang dibuat, atau saat metode close() instance PersistenceManager dipanggil ketika objek sedang diperbarui.

Untuk informasi selengkapnya tentang cara membuat kunci, lihat Entity, Properti, dan Kunci.

Mendapatkan Objek berdasarkan Kunci

Untuk mengambil objek dengan kuncinya, gunakan metode getObjectById() PersistenceManager. Metode ini mengambil class untuk objek, dan kunci:

        Key k = KeyFactory.createKey(Employee.class.getSimpleName(), "Alfred.Smith@example.com");
        Employee e = pm.getObjectById(Employee.class, k);

Jika class menggunakan kolom kunci yang merupakan ID string yang tidak dienkode (String) atau ID numerik (Long), getObjectByID() dapat menggunakan nilai sederhana sebagai parameter kunci:

        Employee e = pm.getObjectById(Employee.class, "Alfred.Smith@example.com");

Argumen kunci dapat berupa salah satu jenis kolom kunci yang didukung (ID string, ID numerik, nilai Key, string kunci yang dienkode), dan dapat berupa jenis yang berbeda dari kolom kunci di class tersebut. App Engine harus dapat memperoleh kunci lengkap dari nama class dan nilai yang diberikan. ID string dan ID numerik bersifat eksklusif, jadi panggilan yang menggunakan ID numerik tidak akan pernah menampilkan entity dengan ID string. Jika nilai Key atau string kunci yang dienkode digunakan, kunci tersebut harus merujuk pada entity yang jenisnya diwakili oleh class.

Memperbarui Objek

Salah satu cara untuk memperbarui objek dengan JDO adalah dengan mengambil objek, lalu memodifikasinya saat PersistenceManager yang menampilkan objek masih terbuka. Perubahan dipertahankan saat PersistenceManager ditutup. Contoh:

public void updateEmployeeTitle(User user, String newTitle) {
    PersistenceManager pm = PMF.get().getPersistenceManager();
    try {
        Employee e = pm.getObjectById(Employee.class, user.getEmail());
        if (titleChangeIsAuthorized(e, newTitle) {
            e.setTitle(newTitle);
        } else {
            throw new UnauthorizedTitleChangeException(e, newTitle);
        }
    } finally {
        pm.close();
    }
}

Karena PersistenceManager menampilkan instance Employee, PersistenceManager mengetahui tentang setiap modifikasi yang dibuat pada kolom Persistent di Employee, dan memperbarui datastore secara otomatis dengan perubahan ini saat PersistenceManager ditutup. PersistenceManager mengetahui hal ini karena instance Employee "dilampirkan" ke PersistenceManager.

Anda dapat memodifikasi objek setelah PersistenceManager ditutup dengan mendeklarasikan class sebagai "detachable". Untuk melakukannya, tambahkan atribut detachable ke anotasi @PersistenceCapable:

import javax.jdo.annotations.PersistenceCapable;

@PersistenceCapable(detachable="true")
public class Employee {
    // ...
}

Sekarang Anda dapat membaca dan menulis kolom objek Employee setelah PersistenceManager yang memuatnya ditutup. Contoh berikut mengilustrasikan bagaimana objek terlepas mungkin berguna:

public Employee getEmployee(User user) {
    PersistenceManager pm = PMF.get().getPersistenceManager();
    Employee employee, detached = null;
    try {
        employee = pm.getObjectById(Employee.class,
            "Alfred.Smith@example.com");

        // If you're using transactions, you can call
        // pm.setDetachAllOnCommit(true) before committing to automatically
        // detach all objects without calls to detachCopy or detachCopyAll.
        detached = pm.detachCopy(employee);
    } finally {
        pm.close();
    }
    return detached;
}

public void updateEmployeeTitle(Employee e, String newTitle) {
    if (titleChangeIsAuthorized(e, newTitle) {
        e.setTitle(newTitle);
        PersistenceManager pm = PMF.get().getPersistenceManager();
        try {
            pm.makePersistent(e);
        } finally {
            pm.close();
        }
    } else {
        throw new UnauthorizedTitleChangeException(e, newTitle);
    }
}

Objek yang terlepas adalah alternatif yang baik untuk membuat objek transfer data. Untuk informasi selengkapnya tentang cara menggunakan objek terlepas, harap lihat dokumentasi DataNucleus.

Menghapus Objek

Untuk menghapus objek dari datastore, panggil metode deletePersistent() PersistenceManager dengan objek:

pm.deletePersistent(e);

Untuk menghapus beberapa objek di JDO, panggil metode deletePersistentAll(...) dengan Collection objek. Metode ini akan menggunakan satu operasi penghapusan batch tingkat rendah yang lebih efisien dibandingkan serangkaian pemanggilan deletePersistent(...) individual.

Jika objek memiliki kolom yang berisi objek turunan yang juga bersifat persisten, objek turunan tersebut juga akan dihapus. Lihat Hubungan untuk informasi selengkapnya.

Untuk menghapus semua objek yang cocok dengan kueri, Anda dapat menggunakan fitur "delete by query" JDOQL. Lihat Menghapus Entity Berdasarkan Kueri untuk informasi selengkapnya.