UpdateTableSpec on dynamoDB table is not working - java

Can any one let me know whether UpdateTableSpec can only update KeySchema attributes and is there any way to update/modify a table with non-keyschema attributes ? My scenario is : I created a table with composite key comprising of a primary ( #id attribute) and range key ( #Name attribute). Now I want to add a third attribute, Gender, which is not a part of keyschema. Is it possible ?
I am updating my DynamoDB table using the following code but it does not add the Gender attribute, although it successfully updates the provisioned attribute:
static void updateTable() {
System.out.println("Updating the table with new attributes ...");
Table table = dynamoDB.getTable(tableName);
UpdateTableSpec updateTableSpec = new UpdateTableSpec();
List<AttributeDefinition> attributeDefinitionList = updateTableSpec.getAttributeDefinitions();
if (null == attributeDefinitionList) {
attributeDefinitionList = new ArrayList<AttributeDefinition>();
}
attributeDefinitionList.add(new AttributeDefinition()
.withAttributeName("Gender")
.withAttributeType("S"));
updateTableSpec.withAttributeDefinitions(attributeDefinitionList)
.withProvisionedThroughput(new ProvisionedThroughput()
.withReadCapacityUnits(6L)
.withWriteCapacityUnits(7L));;
table.updateTable(updateTableSpec);
try {
table.waitForActive();
System.out.println("Table updated succesfully");
} catch (final Exception ex) {
System.out.println("Exception occurred while updating the table");
}
}

You cannot update key schema for a DynamoDB table. Update Table API can be used only for (from the doc):
Modify the provisioned throughput settings of the table.
Enable or disable Streams on the table.
Remove a global secondary index from the table.
Create a new global secondary index on the table. Once the index begins backfilling, you can use UpdateTable to perform other operations.
Your best option, I think, is to migrate to a new table with the desired new key schema. You can see other options here.

Related

Can't delete row from a database

I'm working at some school project and my job here is to make a delete button for that list view in Java FX, but the problem is that when i want to proceed that it shows me this error. I tried some solutions, but none of them worked.
so here's the code
#FXML
private void removeStudentOnClick(ActionEvent event) throws IOException, SQLException{
ModelEditStudent student=(ModelEditStudent)tables.getSelectionModel().getSelectedItem();
String sql="DELETE FROM student WHERE nr_indeksu=?";
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
alert.setTitle("Usuwanie studenta");
alert.setHeaderText(null);
alert.setContentText("Czy na pewno chcesz usunÄ…c tego studenta z listy?");
Optional <ButtonType> action = alert.showAndWait();
if(action.get() == ButtonType.OK){
tables.getItems().removeAll(tables.getSelectionModel().getSelectedItem());
try{
try (Connection myConn = ConnectionManager.getConnection()) {
try (PreparedStatement st = myConn.prepareStatement(sql)) {
st.setString(1, student.getNr_indeksu());
st.executeUpdate();
}
myConn.close();
}
}catch (SQLException e){
System.out.println(e);
}
}
and there's the error:
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException:
Cannot delete or update a parent row: a foreign key constraint fails
(`wu`.`oceny`, CONSTRAINT `oceny_ibfk_3` FOREIGN KEY (`nr_indeksu`)
REFERENCES `student` (`nr_indeksu`))
All the point of this operation is about selecting the row and removing from the database after pressing a button. By now it works only for the listview, but it doesn't remove records from the database.
Anyone got an idea how make it work?
I believe the problem is in your DB schema. try fixing the foreign keys dependencies.I mean the value of nr_indeksu exists in another table of your DB.
You have a table called oceny which has a column nr_indeksu that contains student ids. You have created a foreign key constraint on that table, which requires those student ids to match up with something in the student table.
If you try to delete something in the student table that's referenced by the oceny table, you will get this error, because otherwise, it would leave the database in a state where the oceny table references a student that doesn't exist.
There are a number of solutions to this. You will need to think about what should actually happen in this case - what do you want to have happen to the oceny rows when you delete a matching student.
One option would be for you to change the foreign key to make it do a "cascade delete" - that is, the oceny automatically gets deleted in the same transaction as the student. There's some information here on how to do that.

How to get auto generated primary key after inserting or updating record using jdbc template batch update?

I am using spring JDBC template for data insertion in Oracle and I have one requirement that I have to bulk insert using spring JDBC template batch update and I want auto generated primary key and that key I need to pass in another method but I am not able to get that auto generated primary using batch update.
Can you please provide solution?
Assuming you have auto generated PK in oracle,
See sample code:
final String insertNewFieldSql = Config.getSqlProperty("insert_new_field_record");
GeneratedKeyHolder holder = new GeneratedKeyHolder();
MapSqlParameterSource parameters = null;
for (ParsedData field : fields) {
parameters = new MapSqlParameterSource();
parameters.addValue("FIELD_1",parsedEmail.getDbRecordId())
.addValue("FIELD_2",field.getName());
namedParameterJdbcTemplate.update( insertNewFieldSql, parameters, holder, new String[] {"PK_FIELD_ID" } );
Long newFieldKey = holder.getKey().longValue();
logger.log(Level.FINEST, "row was added: " + newFieldKey);
}

DynamoDB get single column list of range keys or global secondary

I have a DynamoDB table that contains videos info.
Currently "videoID"is the primary (hash) key and "Category" is the range (sort) key.
I want to get a list of all of the "Categories" (Range keys) so I can allow the user to select from one of the available video categories.
https://www.quora.com/What-are-some-good-ways-to-extract-one-single-column-from-a-DynamoDB-table
I was reading that if you modified change the attribute "Category" to a global secondary index you can return the items for that GSI. But I have not been able to find how to do that.
http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GSIJavaDocumentAPI.html
So I guess that gives me three questions:
Is there a way to do to find the items in Category by querying just the range key?
If change Category to a GSI can I fiind the items that way?
or
Is the only way of doing it scanning the whole table?
Thanks in advance for your help
Is the only way of doing it scanning the whole table?
-NO, you can implement GSI to avoid it
Is there a way to do to find the items in Category by querying just the range key?
- Yes, If you don't want to scan entire table then you need to create GSI which will have Category as Hash. This GSI will act as a table in itself and you can query on it by passing category values.
If change Category to a GSI can I find the items that way?
-Yes, you can query on GSI with category values
I was reading that if you modified change the attribute "Category" to a global secondary index you can return the items for that GSI. But I have not been able to find how to do that.
-You need to create GSI when you create table, example is given in the link that you have specified once that is done you can query that GSI
References:http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GSI.html
Here is the sample code to create Videos table with GSI.
Create "Videos" table with GSI:-
#Autowired
private AmazonDynamoDBClient dynamoDBClient;
public Boolean createTableWithGlobalSecondaryIndex(String tableName) {
CreateTableRequest createTableRequest = null;
DynamoDB dynamoDB = new DynamoDB(dynamoDBClient);
try {
ArrayList<AttributeDefinition> attributeDefinitions = new ArrayList<AttributeDefinition>();
attributeDefinitions.add(new AttributeDefinition().withAttributeName("videoid").withAttributeType("S"));
attributeDefinitions.add(new AttributeDefinition().withAttributeName("category").withAttributeType("S"));
ArrayList<KeySchemaElement> keySchema = new ArrayList<KeySchemaElement>();
keySchema.add(new KeySchemaElement().withAttributeName("videoid").withKeyType(KeyType.HASH));
keySchema.add(new KeySchemaElement().withAttributeName("category").withKeyType(KeyType.RANGE));
// Initial provisioned throughput settings for the indexes
ProvisionedThroughput ptIndex = new ProvisionedThroughput().withReadCapacityUnits(150L)
.withWriteCapacityUnits(150L);
GlobalSecondaryIndex videoCategoryGsi = new GlobalSecondaryIndex().withIndexName("VideoCategoryGsi")
.withProvisionedThroughput(ptIndex)
.withKeySchema(new KeySchemaElement().withAttributeName("category").withKeyType(KeyType.HASH),
new KeySchemaElement().withAttributeName("videoid").withKeyType(KeyType.RANGE))
.withProjection(new Projection().withProjectionType(ProjectionType.ALL));
createTableRequest = new CreateTableRequest().withTableName(tableName).withKeySchema(keySchema)
.withAttributeDefinitions(attributeDefinitions)
.withProvisionedThroughput(
new ProvisionedThroughput().withReadCapacityUnits(100L).withWriteCapacityUnits(100L))
.withGlobalSecondaryIndexes(videoCategoryGsi);
Table table = dynamoDB.createTable(createTableRequest);
table.waitForActive();
} catch (ResourceInUseException re) {
if (re.getErrorMessage().equalsIgnoreCase("Cannot create preexisting table")) {
LOGGER.info("Table already exists =============>" + tableName);
} else if (re.getErrorMessage().contains("Table already exists")) {
LOGGER.info("Table already exists =============>" + tableName);
LOGGER.info("Message =============>" + re.getErrorCode() + ";" + re.getErrorMessage());
} else {
throw new RuntimeException("DynamoDB table cannot be created ...", re);
}
} catch (Exception db) {
throw new RuntimeException("DynamoDB table cannot be created ...", db);
}
return true;
}
Query GSI by category:-
Here is the input is just category and it is querying using GSI. In other words, it is not scanning the entire table as well.
public List<String> findVideosByCategoryUsingGlobalSecondaryIndex(String category) {
List<String> videoAsJson = new ArrayList<>();
DynamoDB dynamoDB = new DynamoDB(dynamoDBClient);
Table table = dynamoDB.getTable("Videos");
Index index = table.getIndex("VideoCategoryGsi");
ItemCollection<QueryOutcome> items = null;
QuerySpec querySpec = new QuerySpec();
querySpec.withKeyConditionExpression("category = :val1")
.withValueMap(new ValueMap()
.withString(":val1", category));
items = index.query(querySpec);
Iterator<Item> pageIterator = items.iterator();
while (pageIterator.hasNext()) {
String videoJson = pageIterator.next().toJSON();
System.out.println("Video json ==================>" + videoJson);
videoAsJson.add(videoJson);
}
return videoAsJson;
}

Google Cloud Bigtable emulator seems to drop column families

I am trying to create a table with a single column family (targeting the Google Cloud Bigtable emulator using Java client library 0.9.1).
private void setupTable() throws IOException {
TableName name = TableName.valueOf("EndOfDayPriceUnadjusted");
try(Connection connection = BigtableConfiguration.connect(hbaseConf)){
HTableDescriptor descriptor = new HTableDescriptor(name);
descriptor.addFamily(new HColumnDescriptor("EOD"));
connection.getAdmin().createTable(descriptor);
// calling HTableDescriptor desc = connection.getAdmin().getTableDescriptor(name); yields the same result
Table t = connection.getTable(name);
if(t.getTableDescriptor().getColumnFamilies().length == 0)
log.error("no column families.");
else
log.info("table with column family created.");
}
}
My problem is that after creating the table, the retrieved descriptor never contains the EOD family; therefore, any calls to store data in that column family fails.
Am I missing something or is it a limitation of the emulator?
An emulator-specific workaround you can use until the bug is fixed is to add the column family after creating the table:
connector.getAdmin().addColumn(
descriptor.getTableName(), new HColumnDescriptor("EOD"));

solution with JAVA or Postgres for insertion in database

(source: hostingpics.net)
how can I add a new customer or supplier?, last time I was using this class for one table "customer":
Code:
public int addnewcustomer(){
int idcust;
DBConnection eConnexion = new DBConnection();
try {
//Statement state = eConnexion.getConnexion().createStatement();
String sql = "INSERT INTO customer(name_cust, num_cust, adress_cust, city_cust , tel_cust, ref_cust)";
sql+= "VALUES (?,?,?,?,?,?)";
PreparedStatement insertQuery = eConnexion.getConnexion().prepareStatement(sql);
insertQuery.setString(1,Name_cust);
insertQuery.setString(2,Num_cust);
insertQuery.setString(3,Adress_cust);
insertQuery.setString(4,City_cust );
insertQuery.setString(5,Tel_cust);
insertQuery.setString(6,Ref_cust);
insertQuery.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
//JOptionPane.showMessageDialog(null,"Erreur:the addition is not performed with Succee!");
idcust = 0;
}
eConnexion.closeConnection();
idcust= Services.getLastInsertedId("customer","id_customer");
return idcust;
}
Currently, I attach all tables with new table "person". All tables now extend "person", I tried to add new customer with super variables "person" but I'm stuck in filling foreign key "id_pers FK".
First you need to persist a person into your database. After a successful(!) persist, you can query for the id the database used to insert the data. Most databases also provide a method to directly retrieve the used id after an insert.
After you have successfully persisted the person you can use the id for the foreign key column.
You may consider using a transaction for these actions, as there should never be a person persisted without a customer/employee whatever extending the persons data.
With a transaction, you can rollback the previous actions, for example if something goes wrong during the insertion of the customer.

Categories