Cassandra + SpringBoot: Configure Table to automatically add INSERT timestamp - spring-boot

Small question regarding Cassandra, with the context of a SpringBoot application please.
I am interested in adding onto the table the timestamp of when a row gets inserted onto the table.
Therefore, when creating the table, I do this:
create table mytable (someprimarykey text PRIMARY KEY, timestamp long, someotherfield text);
I can see a column timestamp, happy.
Then, the web application:
#Table
public class MyTable {
#PrimaryKey
private final String somePrimaryKey;
private final long timestamp;
private final String someOtherField;
//constructor + getters + setters
And when I insert, I will do the usual:
MyTable myTable = new MyTable(somePK, System.currentTimeMillis(), "foo");
myTableRepository.save(myTable);
This works fine, I can see in the table my record, with the time of the insert, happy.
Problem:
Now, for the hundreds of POJOs I am interested to insert into Cassandra, all of them are carrying this timestamp long field. Somehow, on the web application layer, I am dealing with a database concept, the timestamp of the write.
Question:
May I ask if it is possible to delegate this back to the database? Some kind of:
create table mytable (someprimarykey text PRIMARY KEY, hey-cassandra-please-automatically-add-the-time-when-this-row-is-written long, someotherfield text);
or
create table mytable (someprimarykey text PRIMARY KEY, someotherfield text WITH default timestamp-insert-time-column);
And the web app can have the abstraction creating and inserting POJOs without carrying this timestamp field?
Thank you

It isn't necessary to store the insert time of each row separately since Cassandra already stores this for all writes in the metadata.
There is a built-in CQL function WRITETIME() which returns the date/time (encoded in microseconds) when a column was written to the database.
In your case, you can query your table with:
SELECT WRITETIME(someotherfield) FROM mytable WHERE someprimarykey = ?
For details, see the CQL doc on retrieving the write time. Cheers!

Related

Hibernate insert with id generation on insert trigger with sequence

Here my problem, I have a sequence in my oracle database and a trigger on insert to fetch the next value from the sequence and put it as id. With a tool like sql developer, it works perfectly.
My id is defined at this
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "MY_SEQUENCE")
#SequenceGenerator(sequenceName = "MY_SEQUENCE", allocationSize = 1, name = "MY_SEQUENCE")
private BigInteger jobId;
The problem is hibernate firstly read the next value of the sequence, set it as the id and then persist it. Then my database update my id with the next value of the sequence but that new id isn't "updated" in my code after my .save(entity).
I read that I should use the GenerationType.IDENTITY but I would like to do batch inserts and I also read that with IDENTITY the batch inserts is not possible.
If possible, I would like to keep my trigger so like that hibernate doesn't have to call the database each time I insert and be able to do batch inserts.
Edit: I'll probably need to insert near a million of rows

Cassandra querying a text value with space in shell

I'm having an issue trying to querying my database, my script with cassandra-driver was this:
const query = 'CREATE TABLE IF NOT EXISTS test.RestaurantMenuItems ' +
'(id UUID, restaurantId varchar, menuName text, menuCategoryNames text, menuItemName text, menuItemDescription text, menuItemPrice decimal, PRIMARY KEY (id))';
return client.execute(query);
I have no idea how I could query with the spaces involved.
https://i.stack.imgur.com/0HU9b.png
With that schema you can only do selects on id, not restaurantId id. To satisfy that query C* would have to read the entire dataset from every node. If that is a query you will want to make your table would likely be something like:
CREATE TABLE IF NOT EXISTS test.items_by_restaurant (
restaurant_id varchar,
menu_name text,
menu_category_name text,
menu_item_name text,
menu_item_description text,
menu_item_price decimal,
PRIMARY KEY ((restaurantId), menu_name, menu_category_name, menu_item_name)
);
As per your screen shot, this is not an issue of text with space. If you add a space in a text it will be count as a character like others. As #Chris mentioned earlier, you are querying with a column which is not a partition key or not indexed. You need to use ALLOW FILTERING in your query to get data which is not recommended. Try creating index on the column you want to query with.
create index on restaurantmenuitems (restaurantid) ;
I am attaching a screen shot.

Partial Entity Binding for Android Room

Would like to confirm is it possible to bind an entity bean to partial columns of a table?
Example:
Table "A" has column id, col1, col2, col3, col4, col5, ... , col10
But I only need id, col1, col2, so I create a entity bean with fields id, col1, col2 and do binding for these fields only? I tried doing this but got:
Caused by: java.lang.IllegalStateException: Room cannot verify the data integrity. Looks like you've changed schema but forgot to update the version number. You can simply fix this by increasing the version number.
Appreciate if anyone can verify is it possible to do the above binding using Room Persistence Library.
(Note: Why are there columns in my table which are not used in the mobile app. These tables schema are an exact copy of some tables in server side, hence some fields are used at server side webapp)
Returning subsets of columns
Most of the time, you need to get only a
few fields of an entity. For example, your UI might display just a
user's first name and last name, rather than every detail about the
user. By fetching only the columns that appear in your app's UI, you
save valuable resources, and your query completes more quickly.
https://developer.android.com/topic/libraries/architecture/room.html
You can define a model which does not have an #Entity annotation and use it at your select query.
// No #Entity annotation here !!!
public class NameTuple {
#ColumnInfo(name="first_name")
public String firstName;
#ColumnInfo(name="last_name")
public String lastName;
}
It isnt necessary to write another DAO (as the new class isnt an entity) - you can use the new Class as the return datatype from within any existing DAO.
// inside any existing DAO
#Query("SELECT first_name, last_name FROM user")
public List<NameTuple> loadFullName();

Retrieving autoincrement value when using #JdbcInsert

I'm trying to store a row in a DB2 database table where the primary key is an autoincrement. This works fine but I'm having trouble wrapping my head around how to retrieve the primary key value for further processing after successfully inserting the row. How do you achieve this? #JdbcInsert only returns the amount of rows that were inserted ...
Since there does not seem to be a way to do this with SSJS (at least to me), I moved this particular piece of logic from my SSJS controller to a Java helper bean I created for JDBC related tasks. A Statement is capable of handing back generated keys (using the method executeUpdate()). So I still create my connection via #JdbcGetConnection, but then hand it in into the bean. This is the interesting part of the bean:
/**
* SQL contains the INSERT Statement
*/
public int executeUpdate(Connection conn, String SQL){
int returnVal;
Statement stmt = conn.createStatement();
stmt.executeUpdate(SQL,
Statement.RETURN_GENERATED_KEYS);
if(!conn.getAutoCommit()) conn.commit();
ResultSet keys = stmt.getGeneratedKeys();
if(keys.next()){
returnVal = keys.getInt(1);
} else {
returnVal = -1;
}
return returnVal;
}
If you insert more than one row at a time, you'll need to change the key retrieval handling, of course.
In newer DB2 Versions you can transform every Insert into a Select to get automatic generated key columns. An example is:
select keycol from Final Table (insert into table (col1, col2) values (?,?))
keycol is the name of your identity column
The Select can be executed with the same #Function than your usual queries.

Get the latest inserted PK after submitting a linq insert stored procedure

I have a stored procedure that updates a table using linq, eg: (this is just example code by way)
using (DataContext db = new DataContext())
{
d.sp_Insert_Client( textboxName.Text, textBoxSurname.Text);
}
What I would like to know is how to retrieve (if possible) newly generated primary key of the above inserted row, as I need this primary key as a foreign key to complete another insert.
You have to modify your stored procedure to return that value from database and then regenerate your Linq mapping to update that change in your ORM files. After that your sp_Insert_Client method will return an integer.
The other way to do that is to add another parameter into the query and mark it as output one.
To get last inserted I'd inside your SP use SCOPE_IDENTITY: http://msdn.microsoft.com/pl-pl/library/ms190315.aspx
I think you need to retrieve value by using the output parameter that you can check over here : Handling stored procedure output parameters A Scott Gu post which explain that easily
Procedure
For you
create procdeudre nameofprocedure
#id int output
as
begin
insert in your table statement
--retrieve identity value
select #id = scope_identity();
end
Code

Resources