Is it possible to delete all rows from a table and then update the table in a single transaction? I found this documentation: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/transaction-example.html
I tried implementing it for a single item:
productItemKey.put("test_id", new AttributeValue(String.valueOf(150)));
machine_ids.add(0, String.valueOf(newAssignments.get(150).get(0).getID()));
machine_ids.add(1, String.valueOf(newAssignments.get(150).get(1).getID()));
machine_ids.add(2, String.valueOf(newAssignments.get(150).get(2).getID()));
Map<String, AttributeValue> expressionAttributeValues = new HashMap<String, AttributeValue>();
expressionAttributeValues.clear();
expressionAttributeValues.put("test_id", new AttributeValue(String.valueOf(150)));
expressionAttributeValues.put("assignments", new AttributeValue().withSS(machine_ids));
expressionAttributeValues.put("needsMoreMachines", new AttributeValue().withBOOL(output.doesCTneedMoreMachines(150)));
Delete deleteItems = new Delete()
.withTableName("test_table")
.withKey(productItemKey);
Put markItemSold = new Put()
.withTableName("test_table")
.withItem(expressionAttributeValues);
Collection<TransactWriteItem> actions = Arrays.asList(
new TransactWriteItem().withDelete(deleteItems),
new TransactWriteItem().withPut(markItemSold));
TransactWriteItemsRequest placeOrderTransaction = new TransactWriteItemsRequest()
.withTransactItems(actions);
try {
client.transactWriteItems(placeOrderTransaction);
System.out.println("Transaction Successful");
...
But i keep getting this error:
Transaction request cannot include multiple operations on one item
You can manipulate up to 100 (separate) items in a transaction. You could only delete all rows if you have fewer than 100 rows.
The best way to bulk delete all rows is to delete the table. You cannot do that transactionally with the creation of the table again. Better to make a new table with a new name and then delete the old.
If you explained what your fundamental goals are we could give some advice.
Related
I am new in dynamo db. I am trying to update the dynamo item amt attribute using the following expression.
TransactionWriteRequest transactionWriteRequest = new TransactionWriteRequest();
HashMap<String, AttributeValue> attributeValues = new HashMap<>();
attributeValues.put(":amount", new AttributeValue().withN(amount));
// key
Map<String, AttributeValue> key = new HashMap<>();
key.put("pk", new AttributeValue().withS(pk));
key.put("sk", new AttributeValue().withS(sk));
UpdateItemRequest updateItemRequest = new UpdateItemRequest()
.withKey(key)
.withTableName("dynamo-test")
.withUpdateExpression("SET amt = amt + :amount")
.withExpressionAttributeValues(attributeValues);
transactionWriteRequest.addUpdate(updateItemRequest);
dynamoDBMapper.transactionWrite(transactionWriteRequest);
There are multiple updates which are getting executed in transactions. On executing this, it is throwing the following exception.
AmazonDynamoDBException: The number of conditions on the keys is invalid
I am stuck here, not finding any error in the above code. Please help here.
Thanks in advance
I believe you are messing up two clients, you should not use Mapper Client if you are not mapping the data to a class object. Use the DynamoDB low level client which your instantiated to make the transaction request.
Furthermore, ensure that your table dynamo-test had a partition key of pk and sort key of sk both of type String.
Facing an issue while rollback saving data.
Problem:
In my java method there are three saving actions. Data save to different table. I want when a saving fails then all saved transaction will be rollback.
Example, there are three tables consist of master table and sub table. All table save in a method. APVoucherEntryDetails is the child table, when it saves fail then upper transactions should be rollback.
How can I do it ?
Thanks in advance
#Override
public ApiResponse saveVoucher(APVoucherBatch batch) {
APVoucherBatch savedBatch = voucherBatchRepo.save(batch); //table 1
//==========save entry=============
List<APVoucherEntry> entryList = batch.getEntryList();
for(APVoucherEntry info: entryList){
info.setVoucherBatch(savedBatch);
info.setBatchNo(savedBatch.getBatchNo());
APVoucherEntry savedEntry = entryRepo.save(info); //table 2
//==========save detail=============
List<APVoucherEntryDetails> detailsList = info.getDetailsList();
for(APVoucherEntryDetails dtl: detailsList){
dtl.setBatchList(savedBatch);
dtl.setEntryInfo(savedEntry);
detailsRepo.save(dtl); //table 3
}
}
return new ApiResponse();
}
I am new to querydsl and I'm trying to use querydsl in pure java (no hibernate, JPA or anything).
We have a database where the tables are linked through minimum 3 columns
I followed the doc here and ended up with my schema duly created.
Here are my pseudo tables :
Item
Corporation (pk) mmcono
Item number (pk) mmitno
Environnement (pk) mmenv
Item description mmitds
Item_warehouse
Corporation (fk for Item) mbcono
Item number (fk for Item) mbitno
Environnement (fk for Item) mbenv
Warehouse number mbwhlo
Other properties (not important)
Inside the Item_wharehouse class, I manually added the foreignKey (because it's not defined in the actual db schema)
public final com.querydsl.sql.ForeignKey<QItemWharehouse > _ItemWharehouseFk = createInvForeignKey(Arrays.asList(mbitno, mbcono, mbenv), Arrays.asList("mmitno", "mmcono", "mbenv"));
I'm working on the following code in my main class:
SQLTemplates templates = SQLServer2012Templates.builder().printSchema().build();
Configuration configuration = new Configuration(templates);
QItem mm = new QItem ("mm");
QItemWarehouse mb = new QItemWarehouse("mb");
JtdsDataSource ds = getDataSource();
SQLQueryFactory queryFactory = new SQLQueryFactory(configuration, ds);
String toto = queryFactory.select(mm.mmitno, mm.mmitds)
.from(mm)
.join( ???????????? )
.where(mb.mbwhlo.eq("122"))
.fetch()
As per doc here I should be able to do something like this : AbstractSQLQuery.innerJoin(ForeignKey<E> key, RelationalPath<E> entity)
What I want in the end is to allow joining table without having to specify manually all the columns required for the join condition.
As stated before, my model starts with minimum 3 columns in the pk, and it's not uncommon to have 6 or 7 cols in the on clause! It's a lot of typing and very error prone, because you can easily miss one and get duplicate results.
I would like something like .join(mb._ItemWharehouseFk, ???) and let querydsl handle little details like generating the on clause for me.
My trouble is that I can't find the second parameter of type RelationalPath<E> entity for the join method.
I am doing something wrong ? What do I miss ? Is it even possible to accomplish what I want ?
Oups I found the problem : I had it all in the wrong order.
The foreign key was located in the itemWarehouse class.
it should have been named this way :
public final com.querydsl.sql.ForeignKey<QItem> _ItemFk = createInvForeignKey(Arrays.asList(mbitno, mbcono, mbenv), Arrays.asList("mmitno", "mmcono", "mbenv"));
that means that you just have to reverse the order in the statement this way :
SQLTemplates templates = SQLServer2012Templates.builder().printSchema().build();
Configuration configuration = new Configuration(templates);
QItem mm = new QItem ("mm");
QItemWarehouse mb = new QItemWarehouse("mb");
JtdsDataSource ds = getDataSource();
SQLQueryFactory queryFactory = new SQLQueryFactory(configuration, ds);
List<Tuple> toto = queryFactory.select(mm.mmitno, mm.mmitds)
.from(mb)
.join(mb._ItemFk, mm )
.where(mb.mbwhlo.eq("122"))
.fetch()
And you get your nice on clause generated. It's just a question of how you construct your relation.
#Enigma, I sincerely hope it will help you for your Friday afternoon. I wouldn't want your boss to be disappointed with you :-)
Does anybody know is it possible to write in JOOQ select with a set of predefined values? I need it for insert if not exists.
For example,
INSERT INTO test
(text)
SELECT '1234567890123456789'
WHERE
NOT EXISTS (
SELECT id FROM test WHERE text = '1234567890123456789'
);
I've found the answer by myself:
List<Param<?>> params = new LinkedList<>();
params.add(DSL.val("1234567890123456789"));
List<Field<?>> fields = new LinkedList<>();
fields.add(TEST.TEXT);
SelectConditionStep<Record1<TEXT>> notExistsSelect = context.select(TEST.TEXT).from(TEST).where(TEST.TEXT.eq("1234567890123456789"));
SelectConditionStep<Record> insertIntoSelect = context.select(params).whereNotExists(notExistsSelect);
context.insertInto(TEST, fields).select(insertIntoSelect).execute();
But it would be great, if we had an ability to do it via InsertQuery. I've not found the way to do it.
I'm trying to figure out the best way to delete an attribute from an item in Dynamo DB. Below is what I tried, but I get an exception saying that DELETE is not a supported for either type N or S.
Exception in thread "main" Status Code: 400, AWS Service: AmazonDynamoDB, AWS Request ID: 09MRO4PVTJ8IK6OHLKSM551REJVV4KQNSO5AEMVJF66Q9ASUAAJG, AWS Error Code: ValidationException, AWS Error Message: One or more parameter values were invalid: Action DELETE is not supported for the type N
at com.amazonaws.http.AmazonHttpClient.handleErrorResponse(AmazonHttpClient.java:544)
at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:284)
at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:169)
at >com.amazonaws.services.dynamodb.AmazonDynamoDBClient.invoke(AmazonDynamoDBClient.java:675)
at >com.amazonaws.services.dynamodb.AmazonDynamoDBClient.updateItem(AmazonDynamoDBClient.java:371)
Key pk = new Key(new AttributeValue().withN(Long.toString(123)));
AttributeValueUpdate avu = new AttributeValueUpdate(new AttributeValue().withN("555"), "DELETE");
Map<String, AttributeValueUpdate> m = new HashMap<String, AttributeValueUpdate>();
m.put(String.valueOf(555), avu);
UpdateItemRequest uir = new UpdateItemRequest("users", pk, m);
dynamoDB.updateItem(uir);
One point of confusion is why the attribute value matters for a deletion. I really want to delete an attribute name and any associated values, but couldn't find the appropriate way to do that in the SDK.
Help would be appreciated.
I could have sworn I already tried this but by replacing the AttributeValue with a null value it works:
Key pk = new Key(new AttributeValue().withN(Long.toString(123)));
AttributeValueUpdate avu = new AttributeValueUpdate(null, "DELETE");
Map<String, AttributeValueUpdate> m = new HashMap<String, AttributeValueUpdate>();
m.put(String.valueOf(555), avu);
UpdateItemRequest uir = new UpdateItemRequest("users", pk, m);
dynamoDB.updateItem(uir);
This also works.
Table table = dynamoDB.getTable("users");
table.updateItem(new PrimaryKey("<MY HASH KEY NAME>", <MY HASH VALUE>), new AttributeUpdate("columnToRemove").delete());
or you can even use Expressions in an Item Update.
REMOVE - Removes one or more attributes from an item.
To delete an Attribute from Dynamo DB while Updating an item of the table
UpdateItemRequest updateItemRequest =new UpdateItemRequest().withTableName(tableName).withKey(key);
updateItemRequest.addAttributeUpdatesEntry("privileges",new AttributeValueUpdate()
.withAction(AttributeAction.DELETE));
updateItemRequest.addAttributeUpdatesEntry("description", new AttributeValueUpdate()
.withValue(new AttributeValue().withS("description")));
In above Example, First I removed privileges from Item and then updated description in Item.