Spring/JPA/Hibernate database historical changes at column level - java

In my Spring/JPA/Hibernate application I need to store all historical changes in my database at column level.
For example I have a table - users with a following columns: id, name, email, address
For historical changes I'll introduce a new dedicated table, let's say historical_changes with a following fields: id, table_name, column_name, previous_value, new_value.. create/update_date and user_id
When someone insert/update a record in users table I have to add a set of new records to historical_changes with an affected columns, for example users.name and users.email changes have to be logged in a following way:
1, 'users', 'name', 'old name', 'new name' ...
2, 'users', 'email', 'old#email.com', 'new#email.com' ...
Right now I'm looking for a best way to automate this process. I know that Spring Data supports Auditing feature but can't find functionality that allow me to implement the described case.
Please advise me how the described historical changes feature can be implemented with Spring/JPA/Hibernate or may be with some other 3rd party lib.

Related

How to query current state of all Objects in a event driven database table?

I am currently implementing a blacklist feature for my application. Therefore I want to use a event based datatable, so I can also track, when a item has been blocked and by whom.
To give you a bit of a context: This is how the table looks like
id|object_id |object_type|change_time |change_type|
--|----------|-----------|-------------------|-----------|
0|1234567890|ITEM |2019-04-29 15:12:42|BLACKLISTED|
1|654321 |MATERIAL |2019-04-29 15:14:19|BLACKLISTED|
2|654321 |MATERIAL |2019-04-29 15:14:58|CLEARED |
As I am using spring and spring-data-jpa it is quite easy to get the current state of a single Item when querying for the first result ordered by time.
#Repository
public interface ItemFilterRepository extends JpaRepository<ItemFilterDpo, Integer> {
ItemFilterDpo findFirstByObjectIdAndObjectTypeOrderByChangeTimeDesc(String objectId, ItemFilterObjectTypeDpo type);
}
However, I can't find a nice solution for showing all Items that are currently blocked.
So I had a look here in stack overflow and found an answer using subqueries in the sql (SQL Query for current state of all entities in event table).
select
object_id, object_type, change_time, change_type as last_modified
from
item_filter ife
where
ife.change_time = (
select max(ife2.change_time)
from item_filter ife2
where ife.object_id=ife2.object_id
)
That gives me the following result, which I can filter for BLACKLISTED afterwards:
object_id |object_type|change_time |last_modified|
----------|-----------|-------------------|-------------|
1234567890|ITEM |2019-04-29 15:12:42|BLACKLISTED |
654321 |MATERIAL |2019-04-29 15:14:58|CLEARED |
To use that with spring-data, my first approach would be to create a view and query from that.
I'd really like to know, whether there is a better approach using spring-data to query the current state of all objects in a event datatable.
If an other framework suites better for my problem, I am happy to know.
Edit:
Using distinct on feels a bit better, however this doesn't solves my problem with spring-data.
select distinct on (object_id, object_type)
object_id, object_type, change_time, change_type as last_modified
from
item_filter bl
order by
object_id, object_type, change_time DESC;

How to know which data is from which table when you select data from multiple tables?

I have a table of client contain the client id, name and last name, job ..etc...
also I have 16 tables of the grants of client each table contain a different data(different grant) relate with the client by a foreign key of "id".......
for example this is costumer table"clients":
enter image description here
and this is an example for an grant of client called order:
enter image description here
So when I search for client, I search also for all the grants that he benefited them, and maybe a client can benefit from the same grant more than once........that's means we can find more than one row in the same table relate with the same client:
As you see in the table Of order we have two row relate with the client who have id=2.: So I want to make one query to select all data from the first table and the second of the client "Where id =2"
the problem is how I can get all the information relate with that client and to which row from which table ??
If you want to access data from particular Table you can see the following code It may help you
public Cursor getInformation(databaseOperations dbo){
SQLiteDatabase Db = dbo.getReadableDatabase();
String [] columns = {TableData.TableInfo.USER_NAME, TableData.TableInfo.CONTACT_NO, TableData.TableInfo.EMAIL_ID,TableData.TableInfo.PROFILE_PATH};
Cursor CR =Db.query(TableData.TableInfo.TABLE_NAME,columns,null,null,null,null,null);
return CR;
}
If you need data from particular row or column then you can pass different argument instead of null in DB.query.
To know about different parameters you can see just this answer click here
I hope it will help you. To know more about parameter details of db.query() function you can go through google search.

Get All tables allowed to user with jdbc

I'm connecting to a database using jdbc, getting list of all schemas and tables from database (I assume that some databases may return at this point only tables which current user can query, but some of databases return full list of tables) and when user try to query some tables he get "insufficient privileges" error.
Is there a way to get only tables, user can query using only jdbc capabilities? Without writing special query to database.
Now I'm looking at
DatabaseMetaData dbMeta = connection.getMetaData()
dbMeta.getTablePrivileges(null, null, null);
But from result of this query it's not so clear which exactly tables can user query.
Currently I'm working with SAP HANA database, but in general it may be any database, so I'm looking for some common approach.
Please look at
http://docs.oracle.com/javase/7/docs/api/java/sql/DatabaseMetaData.html#getTablePrivileges%28java.lang.String,%20java.lang.String,%20java.lang.String%29
You have to get the each row from the ResultSet and query of column name TABLE_NAME which contains the table name and PRIVILEGE which contains the access of each table.

How does no-sql handle relational data?

I know it is a non-relational database but this does not mean that relational data does not exist.
For example, I have a table that holds urls like this ( simplified ):
url | domain
and I have a table that holds domains like this ( simplified ):
domain | favicon_path
Because many different urls may have the same domain, I did not want to repeat the favicon_path for each domain when pulling the data for sending to the view.
Hence I used a simple ( simplified for example ) join command when I need the data.
"SELECT bookmarks.*, domains.favicon FROM bookmarks JOIN
domains ON bookmarks.domain=domains.domain"
How would I handle this scenario using no-sql?
I plan on implementing no-sql using indexedDB on the client ( javascript ) and MongoDB on the server ( java ).
If you want to use document-oriented DB, you can use this structure of documents:
URL_ID : {
"domain":"id_of_domain",
"another_staff": "..."
}
DOMAIN_ID : {
"favicon_path" : "path or id of another document",
"another_staff": "..."
}
So you can get document with URL_ID by id from database and then get document of type Domain.
ADDITION:
You can use the following approach for generating id. Create special document (like sequence) which will have only one field - current_value_of_sequence. Every insert to DB you have to get this sequence and increment it. Some DB like Couchbase have low-level support of this mechanism, which very efficient and thread-safety.
From years of work expierence in IT area, I would say most of the business models could be normalized as simple as these two types of data structure:
Entity info.
Entity list.
For example, in a book store business, we will have the Book entity, and many list that containing all of the books or a subset of the whole books.
With a NoSQL database, such as Redis or SSDB, the Book entity is stored with Key-Value, where key is the book sn, and value is the stringified book info(title, publish date, description, etc). While book list(list by publish date, list by price, etc) are stored in zset data type.

Mongodb database Schema design tips [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Mongodb database Schema Design with shared data
Hi I am newbie to mongodb.I am using java.
I have 4 tables Tenant,system,authorization in my relational table.
Something like this.
Table Fields
Tenant Tenant_ID(PK), Tenant_INFO
System System_ID(PK), System_Info
Authorization System_ID, Autho_Info.
System_prop System_ID, Prop_Info, Tenant_ID
In System_prop table, Tenant_ID refers the Tenant Table Tenant_ID (PK), System_ID refers the System Table System_ID.
In Authorization table, System_ID refers System tabel System_ID
I am switching my database from relational to mongodb. First thing I need to do is Schema design.
Query I need to do is:
SELECT D.Prop_Info, D.System_ID, A.Tenant_Info From TENANT A ,System_prop D, SYSTEM B, Where D.System_ID = B.System_ID AND D.Tenant_ID = A.Tenant_ID
SELECT C.System_ID, C.auth_Info, B.System_ID FROM Authorization C, SYSTEM B WHERE C.System_ID = B.System_ID
Can anyone help me how to design these tables as collections in mongodb?
Do i need to embed r use dbref? Help me to design the schema for this.
From the schema information you provided, it looks like you have a many-to-many relationship between Tenant and System (through the JOIN table System_prop), and a one-to-many relationship between System and Authorization.
In MongoDB, both of these types of relationships can be implemented using array fields. This is how you could set up your System collection:
{
System_Info: ...,
Tenant: [
{
Tenant_Id: ...,
Tenant_Info: ...,
Prop_Info: ...
},
{
Tenant_Id: ...,
Tenant_Info: ...,
Prop_Info: ...
} ],
Authorization: [
{
Auth_Id: ...,
Auth_Info: ...
},
{
Auth_Id: ...,
Auth_Info: ...
} ]
}
However, for the Tenant info, you will now have de-normalized duplicate information, i.e. the same Tenant document appears in different System documents. It is up to your application to ensure consistency.
As for the queries you mentioned: It looks like there is some information missing. For the first query, you're joining on the Tenant_Id but not requesting any information from the Tenant table. The second one requests Prop_Info from the Authorization table but that table doesn't have Prop_Info. Should that be A.Autho_Info instead? So you might want to double-check these queries.
Here are some additional resources about schema design in MongoDB that are worth a read:
http://www.mongodb.org/display/DOCS/Schema+Design
https://openshift.redhat.com/community/blogs/designing-mongodb-schemas-with-embedded-non-embedded-and-bucket-structures
In the end, it depends on your application and most frequent queries how exactly you choose to store your data, and the example above is just one way to set up your schema.
You are still thinking in relational databases. MongoDB, however, is a document-oriented database.
artificial ID numbers are usually not needed, because every document automatically has a _id field, which is a GUID (as good as guaranteed to be globally unique).
relation tables should not be used in MongoDB. n-type relations are made with arrays fields instead. So when 1 system has N authorizations it uses, your system document should have a field "authorization" which is an array of the object IDs of the authorizations it has. Yes, that would be a horrible violation of the normalization rules of relational databases. But you don't have a relational database here. In MongoDB it is practical to represent N-relations with arrays, because arrays are transparent to the query language.

Categories