Hibernate automatically performs some updates such as creating tables or columns, but don't changing types of columns. For example we are changed column type from long to int and column type in database still bigint (PostgreSQL 9.5). Also, we added type converter for LocalDateTime fields, and Hibernate creating new field as timestamps but don't changing type of old fields. How can we configure Hibernate to let it automatically manage such things?
While I think this practice is pretty bad, and very dangerous, the reality is you just need the right permissions.
Most SQL databases store the database information in a system schema. The user for your app would have to have permission to utilize and possibly CRUD that schema. Once you have that, it is just a matter of writing the hibernate classes to manage the tables.
For example, if I wanted to change the schema a particular table belonged to I can do that by executing this statement in PostgreSQL:
update pg_tables set schemaname = 'newSchema' where tablename = 'xxx';
Allowing your application to do so opens you up to all kinds of pain and suffering. Including faults that are expecting a certain data model that was dynamically updated; and, if your application is hacked you could have all your tables dropped.
Related
I want to design a system. There are different customers using this system. I need to create the duplicated tables for every customer. For example, I have a table Order, then all of order records for customerA are in table Order_A, as well as customerB data are in table Order_B. I can distinct different customers from session, but how can I let Spring JPA to reflect the RDS table data to Java object?
I know 2 solutions, but both are not satisfied.
Consider to use Mybatis because it supports load SQL from xml file and parameters inside SQL;
Consider to use org.hibernate.EmptyInterceptor. This is my current implement in my project. For every entity, I must define a subclass of it. It can update the SQL before Hibernate's execution.
However, both are not graceful. I prefer the better solution.
I am using Cassandra database integrated into a spring boot application.
My Question is around the schema actions. If I need to make structural changes to the DB, say add a column to a table, the database needs to be recreated, however this means all the existing data gets deleted:
schema-action: CREATE_IF_NOT_EXISTS
The only way I have managed to solve this is by using the RECREATE scheme action, but as mentioned earlier, this results in data-loss.
What would be the best approach to handle this? To add structural changes such as a column name with out having to recreate the database and lose all existing data?
Thanks
Cassandra does allow you to modify the schema of an existing table without recreating it from scratch, using the ALTER TABLE statement via cqlsh. However, as explained in that link, there are some important limitations on the kind of changes you can do. You cannot modify the primary key of the table at all, you can add or delete regular columns, and you can't change the type of a column to a non-compatible one.
The reason for most of these limitations is how Cassandra needs to deal with the old data that already exists in the table. For example, it doesn't make sense to say that a column A that until now contained strings - will now contain integers - how are we supposed to handle all the old values in column A which weren't integers?
As Aaron rightly said in a comment, it is unlikely you'll want to do these schema changes as part of your application. These are usually rare operations which are done manually, or via some management application - not your usual application.
I am working on spring project, we have data already in production, i am using annotation configuration for my entities, i have data already running, i want to add new data types and modify some already existing types, how to do that smoothly without the need to manually export the data and create import script for the new schema.
You can add tables, columns in existing tables and switch data types of some column but you should take care of these points:
add new column: if the column is not nullable you have to either enable not null constraint after data inserts or use a default dummy value. You can remove the default clause after insertions of good values too.
switch of type: If your db provider is capable of doing the cast directly everything is ok but if you got an error you should check at your db provider documentation if you can provide a hint for casting. For instance Postgres provides USING keyword for that.
Last thing if you try change type on column serving as FK , you should drop the fk, switch type of both columns and recreate the fk.
Finally I would advice you to use a database migration tool to handle that changes. Using tool like Flyway for instance.
I'm working on a legacy application which uses Hibernate and MySQL. In one of my DB tables, I've found duplicate foreign key constraints. Names are like the following:
FK3EBE45E8C4027E24
FK3EBE45E8F5ADD75E
Now I want to drop one index and rename another one from database only. Will there be any impact on hibernate functionalities?
No
There will not be any impact on the Hibernate code. Only when you make changes to the structure of the table - add/remove/rename a column, change the datatype, then there will be an impact as you will have to make changes to the DTO. MySQL Indexes are abstractions for Hibernate. Hibernate doesn't care whether there's an index or not. It will create a query and send to the database.
Renaming a constraint will be impact only on automatic schema update (create). Hibernate will try to delete constraint by name and generate an exception. It is not a problem (for Hibernate 5, don't know about other versions), a schema update will not stop.
If you don't use automatic schema update, you will not have any problems.
I'm getting introduced to serialization and ran into some problems when pairing it with LinkedList
Consider i have the following table:
CREATE TABLE JAVA_OBJECTS (
ID BIGINT NOT NULL UNIQUE AUTO_INCREMENT,
OBJ_NAME VARCHAR(50),
OBJ_VALUE BLOB
);
And i'm planning to store 3 object types - so the table may look like so -
ID OBJ_NAME OBJ_VALUE
============================
1 Class1 BLOB
2 Class2 BLOB
3 Class1 BLOB
4 Class3 BLOB
5 Class3 BLOB
And i'll use 3 different LinkedList's to manage these objects..
I've been able to implement LoadFromTable() and StoreIntoTable(Class1 obj1).
My question is - if i change an attribute for a Class2 object in LinkedList<Class2>, how do i effect the change in the DB for this individual item? Also take into account that the order of the elements in LinkedList may change..
Thanks : )
* EDIT
Yes, i understand that i'll have to delete/update a row in my DB table. But how do i keep track of WHICH row to update? I'm only storing the objects in the List, not their respective IDs in the table.
You'll have to store their IDs in the objects you are storing. However, I would suggest not trying to roll your own ORM system, and instead use something like Hibernate.
If you change an attribute in a an object or the order of items. You will have to delete that row and insert the updated list again.
How do i effect the change in the DB for this individual item?
I hope I get you right. The SQL update and delete statements allow you to add a WHERE clause in which you chose the ID of the row to update.
e.g.
UPDATE JAVA_OBJECTS SET OBJ_NAME ="new name" WHERE ID = 2
EDIT:
To prevent problems with your Ids you could wrap you object
class Wrapper {
int dbId;
Object obj;
}
And add them instead of the 'naked' object into your LinkedList
You can use AUTO_INCREMENT attribute for your table and then use the mysql_insert_id() function to retrieve the id assigned to the row added/updated by the last INSERT/UPDATE statement. Along with this maintain a map (eg a HashMap) from the java object to the Id. Using this map you can keep track of which row to delete/update.
Edit: See the answer to this question as well.
I think the real problem here is, that you mix and match different levels of abstraction. By storing serialized Java objects into a relational database as BLOBs you have to consider several drawbacks:
You loose interoperability. Applications written in other languages than Java are not able to read the data back. Even other Java applications have to have the class files of the serialized classes in their classpath.
Changing the class definitions of the stored classes will end up in maintenance nightmares.
You give up the advantages of a relational database. Serialization hides the actual data from the database. So the database is presented only with a black box. You are unable to execute any meaningfull query against the real data. All what you have is the ID and block of bytes.
You have to implement low level data handling by yourself. Actually the database is made to handle your data effectively, but because of serialization you hinder it doing its job. So you are on your own and you are running into that problem right now.
So in most cases you benifit from separation of concerns and using the right tool for a job.
Here are some suggestions:
Separate the internal data handling inside your application from persistent storage. Design your database schema in a way to enable the built-in database features to handle the data efficently. In case of a relational database like MySQL you can choose from different technologies like plain JDBC, object relational mappers like JPA or simple mappers like MyBatis. Separation here means to avoid to contaminate the database with implementation specific concerns.
If you have for example in your Java application a List of Person instances and each Person consists of a name and an age. Then you would represent that list in a relational database as a table consisting of a VARCHAR field for the name and a numeric field for the age and maybe a third field for a unique key. Then the database is able to do what it can do best: managing large amounts of data.
Inside your application you typically separate the persistent layer from the rest of your program containing the code to communicate with the database.
In some use cases a relational database may not be the appropiate tool. Maybe in a single user desktop application with a small set of data it may be the best to simply serialize your Person list into a plain file and read it back at the next start up.
But there exists other alternatives to persist your data. Maybe some kind of object oriented database is the right tool. In particular I have experiences with Fast Objects. As a simplification it is serialization on steroids. There is no need for a layer like JPA or JDBC between your application and your database. You are able to store the class instances directly into the database. But unlike the relational database with its BLOB field, the OODB knows your classes and the actual data and can benefit from that.
Another alternative may be JDBM or Berkeley DB.
So separation of concerns and choosing the right persistence strategy (and using it the right way) is a key concern for the success of your project. But doing it right is hard even for experienced developers.