Convert Entity object to changeSet automatically - java

I created many Entities Like this in my Java project:
#Data
#Entity
#Builder
#NoArgsConstructor
#AllArgsConstructor
#Table(name="backup_item")
public class BackupItem {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
public Long id;
public Path path;
}
Now I need to create the change logs for it:
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.0.xsd">
<changeSet id="1" author="rrrr">
<sql>
CREATE TABLE backup_item(
id SERIAL PRIMARY KEY NOT NULL,
);
</sql>
<rollback>
DROP TABLE backupset;
</rollback>
</changeSet>
Is there any tool that will create it for me automatically? I have at lease 10 tables and it will take me a lot of time to create them manually one by one.

You can use liquibase-maven-plugin as shown in chapter 6. (titled: Generate the changeLog With a Maven Plugin) of this tutorial:
https://www.baeldung.com/liquibase-refactor-schema-of-java-app
Although the auto generated changelogs are not that reliable and I even saw posts where liquibase developers don't recommended. They don't support a lot of stuff like detecting renamed columns etc.
It is recommended to write the changelogs manually as you have more control of the script itself...

Related

Is it possible to configure hibernate.ddl-auto separately for different entities / tables?

In my Spring Boot project I am opening access to an external database, where some tables are already defined.
I want to add some new #Entity classes and auto-update schema.
#Entity
#Table(name = "email")
public class Email {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column(name="email")
private String email;
}
So I define a property for that in my application.properties file:
spring.jpa.hibernate.ddl-auto=update
But how can I prevent updating the schema, when I add a field to already existing #Entity class (e.g. accidentally), that maps "old" tables, which I must not change.
It is not possible to configure schema generation behavior at entity level.
To have better control over database schema evolution, it is recommended to use flyway or liquibase instead of relying on hibernate schema generation.

Set schema for #Embedded tables in JPA annotation?

I'm using JPA to persist my data and have one column that is #embedded and refers to a class that is #embeddable.
When my job runs the tables are created in the schema I specify via the #table annotation. But the data for the #embeddable objects are written in the default schema. I do not see any property to set the schema for the #embeddable tables.
Hope you can point me in the right direction!
The answer seems to be to add the annotation #CollectionTable.

How to alter table by changing the entity in JPA with auto-ddl=update

I changed the entity UserInfoEntity, variable name from 'moblie' to 'mobile', and then I restarted my server. when I looked at the table i found that the table hasn't removed the column 'moblie'. Here is my change in entity;
From this;
#Entity
#Table(name = "pe_userinfo")
public class UserInfoEntity {
private String moblie;
}
to this;
#Entity
#Table(name = "pe_userinfo")
public class UserInfoEntity {
private String mobile;
}
Use auto-ddl=create-drop to drop the faulty schema in its entirety & recreate it with fixed column value, you cannot have update schema in such manner.
Also check Hibernate: hbm2ddl.auto=update in production?, as it says, it is better to handle such cases manually by yourself rather than using Hibernate to handle such modifications on an existing schema.
Extra Idea
If you wish to save your data;
You can create a separate table to hold your data pe_userinfo_temp
deploy your product, auto-ddl will create pe_userinfo_temp
use jpa logic to copy data from pe_userinfo -> pe_userinfo-temp
drop the table pe_userinfo manually from datasource
fix your column in pe_userinfo, auto-ddl will create it but will be empty
use similar jpa logic to copy data from pe_userinfo_temp -> new pe_userinfo
then finally drop the pe_userinfo_temp from your source code & drop from datasource
I assume that you're using hibernate (may be even inside spring-data-jpa) and indeed it doesn't rename the tables but creates new ones. Moreover you shouldn't use (hibernate) auto update in any more or less serious environments.
Use flyway or liquibase instead.

SQL sequence: Hibernate and Liquibase

I am quite new to development with databases, so maybe this question is not entirely spot on, but I'd appreciate if someone can make it a bit clearer to me... I've read all about sequences, and how they are preferred over identities. I have a hypothetical question. If I were to use a sequence to generate my PK along with Hibernate (data insertion) and Liquibase (schema creation), what would be the right spot to define sequence?
For example: Sequence generation on class level.
User.java
#Entity
#Table(name = "USER")
public class User {
#Id
#SequenceGenerator(name = "USER_SEQ", sequenceName = "USER_SEQ")
#GeneratedValue(strategy = SEQUENCE, generator = "USER_SEQ")
#Column(name = "ID")
private Long id;
// other fields
}
Or other example: Sequence generation on Schema level.
changelog.xml
<changeSet author="wesleyy">
<createSequence catalogName="cat"
cycle="true"
incrementBy="1"
maxValue="1000"
minValue="10"
ordered="true"
schemaName="public"
sequenceName="user_seq"
startValue="1"/>
</changeSet>
Is it required to define a sequence in both Liquibase and Hibernate? What exactly is the difference between the two?
By lines in class User
#SequenceGenerator(name = "USER_SEQ", sequenceName = "USER_SEQ")
#GeneratedValue(strategy = SEQUENCE, generator = "USER_SEQ")
you say to hibernate: for each object User inserted into database give new value for primary key from sequence named USER_SEQ.
By adding described changeSet to liquibase xml script you say to liquibase: next time create in database sequence named user_seq if this changeSet was not already applied to database.
In other words in liquibase script you create sequence and in code of class User you use it.
If what you wish for is the id primary key to be auto generated then this can be simply done as follows using a JPA implementation such as Hibernate or others:
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private long id;
The Id primary key will be auto generated and managed for you.
Using liquibase, in your base changelog xml file, you can do the following as long as your database supports auto generated id's (many do this but check if unsure):
<changeSet author="name" id="auto increment example">
<createTable tableName="users">
<column autoIncrement="true" name="id" type="SERIAL">
<constraints primaryKey="true" primaryKeyName="users_pkey"/>
</column>
<column name="some_other_column" type="VARCHAR(255)"/>
<column name="another_column" type="VARCHAR(255)"/>
</createTable>
</changeSet>
Your question is a bit misleading because it is related to two different things:
generation of entity identifiers (behavior of your application) and
definition of the underlying database schema.
"If I were to use a sequence to generate my PK along with Hibernate (data insertion) and Liquibase (schema creation), what would be the right spot to define sequence?"
You could define a sequence in many different ways. It always ends with SQL statement, but sometimes you may prefer to use Liquibase, Flyway or Hibernate to DDL auto export (Hibernate hbm2ddl.auto possible values and what they do?).
My personal preference is to rely on Hibernate automatic schema export during initial development and later on use some of the mentioned version-based DB migration tools.

Update UniqueConstrains on a JPA table

I have a table defined as follow:
#Entity
#Table(
uniqueConstraints = {#UniqueConstraint(columnNames = {"reward_id", "transaction_id"})}
)
public class ShipmentItem extends Model {
...
}
I want to change the unique constraint to make it more relaxed:
#Entity
#Table(
uniqueConstraints = {#UniqueConstraint(columnNames = {"reward_id", "transaction_id", "sku"})}
)
public class ShipmentItem extends Model {
...
}
The updated code compiles, but JPA doesn't change the table schema. Is there a configuration setting I need to use?
If JPA cannot do this, what's the systematic approach to this problem? I can write migration, however, JPA generates the name for the constraint automatically, so it's not obvious how to drop the old constraint.
Not sure if it matters, but I am using hibernate and mysql.
Since you are using Hibernate, there is a property for automatically updating your schema: hibernate.hbm2ddl.auto with the value update
https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/session-configuration.html
(But be aware that it is not recommended to use it on Production)

Categories

Resources