/** * Returns a list with a value for each given key (ordered by input). {@code null} values are * returned for nonexistent keys. */ static List<Entity> fetch(Transaction reader, Key... keys) { return compileEntities(keys, reader.get(keys)); }
/** Example of getting an entity for a given key. */ // [TARGET get(Key)] // [VARIABLE "my_key_name"] public Entity get(String keyName) { Datastore datastore = transaction.getDatastore(); // [START get] Key key = datastore.newKeyFactory().setKind("MyKind").newKey(keyName); Entity entity = transaction.get(key); transaction.commit(); // Do something with the entity // [END get] return entity; }
static Entity get(Transaction reader, Key key) { return Iterators.getNext(reader.get(new Key[] {key}), null); }
/** Example of getting entities for several keys. */ // [TARGET get(Key...)] // [VARIABLE "my_first_key_name"] // [VARIABLE "my_second_key_name"] public List<Entity> getMultiple(String firstKeyName, String secondKeyName) { Datastore datastore = transaction.getDatastore(); // TODO change so that it's not necessary to hold the entities in a list for integration testing // [START getMultiple] KeyFactory keyFactory = datastore.newKeyFactory().setKind("MyKind"); Key firstKey = keyFactory.newKey(firstKeyName); Key secondKey = keyFactory.newKey(secondKeyName); Iterator<Entity> entitiesIterator = transaction.get(firstKey, secondKey); List<Entity> entities = Lists.newArrayList(); while (entitiesIterator.hasNext()) { Entity entity = entitiesIterator.next(); // do something with the entity entities.add(entity); } transaction.commit(); // [END getMultiple] return entities; }
@Override public <T extends DataModel> void create(UUID jobId, String key, T model) throws IOException { Preconditions.checkNotNull(jobId); Transaction transaction = datastore.newTransaction(); Key fullKey = getDataKey(jobId, key); Entity shouldNotExist = transaction.get(fullKey); if (shouldNotExist != null) { transaction.rollback(); throw new IOException( "Record already exists for key: " + fullKey.getName() + ". Record: " + shouldNotExist); } String serialized = objectMapper.writeValueAsString(model); Entity entity = Entity.newBuilder(fullKey) .set(CREATED_FIELD, Timestamp.now()) .set(model.getClass().getName(), serialized) .build(); try { transaction.put(entity); } catch (DatastoreException e) { throw new IOException( "Could not create initial record for jobID: " + jobId + ". Record: " + entity, e); } transaction.commit(); }
@Override public <T extends DataModel> void update(UUID jobId, String key, T model) { Transaction transaction = datastore.newTransaction(); Key entityKey = getDataKey(jobId, key); try { Entity previousEntity = transaction.get(entityKey); if (previousEntity == null) { throw new IOException("Could not find record for data key: " + entityKey.getName()); } String serialized = objectMapper.writeValueAsString(model); Entity entity = Entity.newBuilder(entityKey) .set(CREATED_FIELD, Timestamp.now()) .set(model.getClass().getName(), serialized) .build(); transaction.put(entity); transaction.commit(); } catch (IOException t) { transaction.rollback(); throw new RuntimeException("Failed atomic update of key: " + key, t); } }
/** * Inserts a new {@link PortabilityJob} keyed by {@code jobId} in Datastore. * * <p>To update an existing {@link PortabilityJob} instead, use {@link JobStore#update}. * * @throws IOException if a job already exists for {@code jobId}, or if there was a different * problem inserting the job. */ @Override public void createJob(UUID jobId, PortabilityJob job) throws IOException { Preconditions.checkNotNull(jobId); Transaction transaction = datastore.newTransaction(); Entity shouldNotExist = transaction.get(getKey(jobId)); if (shouldNotExist != null) { transaction.rollback(); throw new IOException( "Record already exists for jobID: " + jobId + ". Record: " + shouldNotExist); } Entity entity = createEntity(jobId, job.toMap()); try { transaction.put(entity); } catch (DatastoreException e) { transaction.rollback(); throw new IOException( "Could not create initial record for jobID: " + jobId + ". Record: " + entity, e); } transaction.commit(); }
Entity previousEntity = transaction.get(key); if (previousEntity == null) { throw new IOException("Could not find record for jobId: " + jobId);
@Test public void testGetWithTransaction() throws Exception { Transaction transaction = createStrictMock(Transaction.class); IncompleteKey pKey1 = IncompleteKey.newBuilder("ds", "k").build(); Key key1 = Key.newBuilder(pKey1, 1).build(); Entity entity1 = Entity.newBuilder(key1).build(); Key key2 = Key.newBuilder(pKey1, 2).build(); expect(transaction.get(new Key[] {key1})) .andReturn(Collections.singletonList(entity1).iterator()); expect(transaction.get(new Key[] {key2})).andReturn(Collections.<Entity>emptyIterator()); replay(transaction); assertEquals(entity1, DatastoreHelper.get(transaction, key1)); assertNull(DatastoreHelper.get(transaction, key2)); verify(transaction); }
@Override public void run(Transaction tx, Key userKey, Void arg) { Entity user = tx.get(userKey); if (user == null) { System.out.println("Nothing to delete, user does not exist."); return; } Query<Key> query = Query.newKeyQueryBuilder() .setNamespace(NAMESPACE) .setKind(COMMENT_KIND) .setFilter(PropertyFilter.hasAncestor(userKey)) .build(); QueryResults<Key> comments = tx.run(query); int count = 0; while (comments.hasNext()) { tx.delete(comments.next()); count++; } tx.delete(userKey); System.out.printf("Deleting user '%s' and %d comment[s].%n", userKey.getName(), count); }
@Override public void run(Transaction tx, Key userKey, Void arg) { Entity user = tx.get(userKey); if (user == null) { System.out.printf("User '%s' does not exist.%n", userKey.getName());
@Override public void run(Transaction tx, Key userKey, Contact contact) { Entity user = tx.get(userKey); if (user == null) { System.out.println("Adding a new user."); user = Entity.newBuilder(userKey).set("count", 0L).build(); tx.add(user); } FullEntity<IncompleteKey> contactEntity = FullEntity.newBuilder() .set("email", contact.email()) .set("phone", contact.phone()) .build(); tx.update(Entity.newBuilder(user).set("contact", contactEntity).build()); System.out.printf("Setting contact for user '%s'.%n", userKey.getName()); }
@Override public Entity get(final Key key) { return raw.get(key); }
@Override public Iterator<Entity> get(final Key... key) { return raw.get(key); }
@Override public void run(Transaction tx, Key userKey, String content) { Entity user = tx.get(userKey); if (user == null) { System.out.println("Adding a new user."); user = Entity.newBuilder(userKey).set("count", 1).build(); tx.add(user); } else { user = Entity.newBuilder(user).set("count", user.getLong("count") + 1L).build(); tx.update(user); } IncompleteKey commentKey = IncompleteKey.newBuilder(userKey, COMMENT_KIND).build(); FullEntity<IncompleteKey> comment = FullEntity.newBuilder(commentKey) .set("content", content) .set("timestamp", Timestamp.now()) .build(); tx.addWithDeferredIdAllocation(comment); System.out.printf("Adding a comment to user '%s'.%n", userKey.getName()); }
@Test public void testFetchWithTransaction() throws Exception { Transaction transaction = createStrictMock(Transaction.class); IncompleteKey pKey1 = IncompleteKey.newBuilder("ds", "k").build(); Key key1 = Key.newBuilder(pKey1, 1).build(); Key key2 = Key.newBuilder(pKey1, "a").build(); Entity entity1 = Entity.newBuilder(key1).build(); Entity entity2 = Entity.newBuilder(key2).build(); expect(transaction.get(new Key[] {key1, key2})) .andReturn(Iterators.forArray(entity1, entity2)) .once(); replay(transaction); List<Entity> values = DatastoreHelper.fetch(transaction, new Key[] {key1, key2}); assertEquals(2, values.size()); assertEquals(entity1, values.get(0)); assertEquals(entity2, values.get(1)); verify(transaction); } }
@Test public void testTransactionWithRead() { Transaction transaction = datastore.newTransaction(); assertNull(transaction.get(KEY3)); transaction.add(ENTITY3); transaction.commit(); assertEquals(ENTITY3, datastore.get(KEY3)); transaction = datastore.newTransaction(); assertEquals(ENTITY3, transaction.get(KEY3)); // update entity3 during the transaction datastore.put(Entity.newBuilder(ENTITY3).clear().build()); transaction.update(ENTITY2); try { transaction.commit(); fail("Expecting a failure"); } catch (DatastoreException expected) { assertEquals("ABORTED", expected.getReason()); } }
@Test public void testTransactionWithRead() { Transaction transaction = DATASTORE.newTransaction(); assertNull(transaction.get(KEY3)); transaction.add(ENTITY3); transaction.commit(); assertEquals(ENTITY3, DATASTORE.get(KEY3)); transaction = DATASTORE.newTransaction(); assertEquals(ENTITY3, transaction.get(KEY3)); // update entity3 during the transaction DATASTORE.put(Entity.newBuilder(ENTITY2).clear().set("from", "datastore").build()); transaction.update(Entity.newBuilder(ENTITY2).clear().set("from", "transaction").build()); try { transaction.commit(); fail("Expecting a failure"); } catch (DatastoreException expected) { assertEquals("ABORTED", expected.getReason()); } }
@Override public Iterator<Entity> get(Key... key) { return this.transaction.get(key); }
/** * Marks a task entity as done. * * @param id The ID of the task entity as given by {@link Key#id()} * @return true if the task was found, false if not * @throws DatastoreException if the transaction fails */ boolean markDone(long id) { Transaction transaction = datastore.newTransaction(); try { Entity task = transaction.get(keyFactory.newKey(id)); if (task != null) { transaction.put(Entity.newBuilder(task).set("done", true).build()); } transaction.commit(); return task != null; } finally { if (transaction.isActive()) { transaction.rollback(); } } } // [END datastore_update_entity]