hibernate not use #column(name='') annotation - spring-boot

I use springboot 2.6 and postgres 15 and hibernate 5.7
I use database Generate persistence Mapping to make entity from database schema;
When I run application with this config:
spring.jpa.hibernate.ddl-auto=validate
table properties name not work.
for example this is my field:
#Basic
#Column(name = "isEnabled", nullable = false)
private boolean isEnabled;
When I run applicataion get this error:
Caused by: org.hibernate.tool.schema.spi.SchemaManagementException: Schema-validation: missing column [is_enabled] in table [analytics]

Can you try to add the following annotation to your Analytics entity definition?
#Table(name = "analytics", schema = "public")

there are 2 problems. first is field name. seccond is table name;
first problem fix with this config in application.properties:
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
this fix first problem. but seccond problem not fix.
you should change table name with this trick:
#Table(name = ""analytics"")

Related

Spring JPA - how to set data.sql to add data if not exist, ignore if exists

Hi i am creaeting rest api spring boot jpa & mysql. i want this to be automated as possible so i drop the database and schema and want spring to create all for me. i am adding data into mysql using data.sql. When i start spring boot, i 1 2 it to add into the table (which spring jpa help to create).
Tis is from my application.properties
spring.jpa.show-sql=true
spring.h2.console.enabled=true
spring.datasource.url=jdbc:mysql://localhost:3306/mockashop
spring.datasource.username=root
spring.datasource.password=root
spring.data.jpa.repositories.bootstrap-mode=default
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
spring.jpa.properties.hibernate.format.sql=true
spring.jpa.hibernate.ddl-auto=update
spring.sql.init.mode=always
here is my data.sql:
INSERT INTO `mockashop`.`user` (`user_id`, `user_role`, `user_contact`, `user_email`, `user_name`, `user_pswd`, `user_wallet`) VALUES ('20003', 'ROLE_USER', '+6592212152', 'shah3#gmail.com', 'shah3', 'shahshah', '777.55');
model:
#Entity
#Data
#SequenceGenerator(name="seq2", initialValue=2000, allocationSize=1)
public class User {
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq2")
#Id
private int user_id;
#NotNull(message = "Name cannot be blank")
#Size(min=5, message = "Name must contain atleast 5 character")
private String user_name;
#NotNull(message = "Email cannot be blank")
#Email(message = "Enter valid email")
#Size(min=5, message = "Email must contain atleast 5 character")
private String user_email;
#Size(min=5, message = "Password must contain atleast 8 character")
#NotNull(message = "Password cannot be blank")
private String user_pswd;
#Size(min=5, message = "Contact must contain atleast 8 character")
#NotNull(message = "Password cannot be blank")
private String user_contact;
#NotNull(message = "Wallet cannot be blank")
private BigDecimal user_wallet;
private String USER_ROLE;
}
1ST PROB
spring hibernate will create the table for me if i create the schema first else it will give me error:
Caused by: java.sql.SQLSyntaxErrorException: Unknown database 'mockashop'
How do i resolve this?
2ND PROB
so i create the schema, then start spring, which give me this error:
Caused by: java.sql.SQLSyntaxErrorException: Table 'mockashop.user' doesn't exist
it will go away until i remove data.sql. now spring boot is finally running.
3RD PROB
mysql has the table created for me but no data. so i add back the data.sql. restart spring. now data is added.
4TH PROB
i do other changes and restart spring it gives me this error:
Caused by: java.sql.SQLIntegrityConstraintViolationException: Duplicate entry '20001' for key 'user.PRIMARY'
i have to remove data.sql then the error is gone.
is there a way to resolve all this ?
1st
While h2 will create the schema for you automatically, MySQL won't automatically create the database for you. You have to do it manually.
Cant create a mysql database using Spring Boot
2nd and 3rd
If you are just adding just one line in mockashop.user, you can try adding the data using #EventListner
You can then remove the data.sql file
#Component
public class Data {
#Autowired
UserRepository userRepository;
#EventListener
public void appReady(ApplicationReadyEvent event){
rolesRepository.save(new User('20003', 'ROLE_USER', '+6592212152', 'shah3#gmail.com', 'shah3', 'shahshah', '777.55'));
}
}
4th
That is because every time you run this application the spring tries to add the same value over and over again and the user_id would have a UNIQUE constraint. That's why you are getting that error.
I believe the solution in the 2nd and 3rd point would also solve this problem as the save method of JPA would update the values in the database if the primary key value that is being passed is already present in the database.

How do I use Spring Data JPA(Hibernate) ORM mapping to a Oracle Tables from other Schema?

The oracle db is version 12c. I use ojdbc8 connector.
I was only granted access to an account, let's call it schema "USR". Login with USR, I can see tables of another schema, let's call it schema "ADM". There is a table "TGT_TABLE" that I want to map it with JPA inside schema ADM. And under USR console, I am able to query "select * from ADM.TGT_TABLE" to get correct result. Now I write up the Entity class as:
#Data
#Entity
#Table(name = "ADM.TGT_TABLE") // or #Table(name = "TGT_TABLE") , Neither worked
public class ApiHeaderLogs {
#Id
#Column(name = "id")
String id;
....
and my config:
spring.jpa.hibernate.ddl-auto=none
# Oracle settings
spring.datasource.url=jdbc:oracle:thin:#10.119.125.70:1540:dhtlm4
spring.datasource.username=USR
spring.datasource.password=******
spring.datasource.driver-class-name=oracle.jdbc.OracleDriver
and my test:
Optional<ApiHeaderLogsEntity> ahl = apiHeaderLogsService.findById(id);
I got error:
org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet
....
Caused by: java.sql.SQLSyntaxErrorException: ORA-00942: table or view does not exist
and the SQL query in console is:
select ... from adm_tgt_table where ... //#Table(name = "ADM.TGT_TABLE")
Or
select ... from tgt_table where ... //#Table(name = "TGT_TABLE")
Clearly it does not address the table ADM.TGT_TABLE.
How can I map to ADM.TGT_TABLE?
My experience was mainly on MySQL, which has no account related to schema access, and my colleague already proposed a solution using JDBC directly... which I really want to avoid, please let me know if there is a proper way to handle this, thanks
You must define explicitely the table_name and the schema in the #Table annotation
Example
#Table(name="TGT_TABLE", schema="ADM")
See the documentation in javax.persistence.Table
Ommiting the schema assumes the deafult owner of the connecting session, which leads to an error.
Neither can you pass a qualified name (ADM.TGT_TABLE) as a table name.

Hibernate creates new Tables but won't modify/add Columns

Looking for next debugging steps. I'm using Hibernate with Spring Boot, with my ddl setting set to update (I realize the hibernate setting is redundant but I just wanted to be sure):
application.properties
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=update
hibernate.hbm2ddl.auto=update
I've just added a new Entity, which succesfully created. But when adding an additional field, profileImageURI2, nothing is ever run to attempt to add it:
#Entity
#Data
public class User {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
private String profileImageURI;
private String profileImageURI2;
}
Is there any additional config that will control the modification of existing tables? The user also has all permissions for the database.

Sequence "HIBERNATE_SEQUENCE" not found; SQL statement

In my spring mvc app, i have the following object. I am trying to make a visual of data using devtool in my app.
#Entity
#Data
public class ConsultationRequest {
#Id
#GeneratedValue
private Long id;
private String name;
private String email;
private String purpose;
private String programme;
private int year;
private String language;
private String comments;
#Enumerated(EnumType.STRING)
private ConsultationStatus status;
}
Then i used the jpa to make the entity:
#Repository
public interface ConsultationRequestRepository extends JpaRepository<ConsultationRequest, Long> {
}
The problem is when i load my application, i face with 2 errors:
Unsuccessful: drop sequence hibernate_sequence
[36morg.hibernate.tool.hbm2ddl.SchemaExport Sequence "HIBERNATE_SEQUENCE" not found; SQL statement:
Then when i open the
http://localhost:8080/h2-console/
I cannot see the table.
It seems that the in the boot process, table is not made.
Update your code as below:
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
As you have not specified a sequence table name, hibernate will look for a sequence table named as hibernate_sequence and use it as default.
For Oracle/Postgres, increment fields used are sequence tables.
In MySql, there are increment fields that automatically increment.
If someone is getting this error with Spring Boot testing(with H2) , we have to use following in the application.properties(or whatever profile we are using) :
spring.jpa.hibernate.ddl-auto=create-drop
Setting the following property in the properties file helped me solve the hibernate_sequence problem for hibernate 5.4v
spring:
jpa:
hibernate:
use-new-id-generator-mappings: false
Check persistence.xml
property name="hibernate.hbm2ddl.auto" value="create"
not hdm2ddl
This worked in my case.
SQL operation ERROR when start app spring-boot.
I added the setting in spring properties and solved: in the spring:jpa.hibernate.ddl-auto= create-drop to hibernate be able create or drop table automatically.
If you use a 2nd cache with liquidbase, you have to add the sequence in the changelog like this:
<changeSet author="liquibase-docs"
id="createSequence-example">
<createSequence catalogName="cat" cycle="false"
incrementBy="1" ordered="true" schemaName="public"
sequenceName="hibernate_sequence" startValue="0" />
</changeSet>
For spring-boot 2.7.x and h2 2.x you need to add MODE=LEGACY; in the database connection:
example application.yml:
spring:
datasource:
url: jdbc:h2:mem:test;MODE=LEGACY;
exemple application.properties:
spring.datasource.url=jdbc:h2:mem:test;MODE=LEGACY;
For Mysql:
the auto-increment is not added, modify ur table:
ALTER TABLE table_name MODIFY COLUMN id BIGINT AUTO_INCREMENT=1

Entity Class name is transformed into SQL table name with underscores

I have the following entity defined:
#Entity
#Table(name = "EmailTemplate")
public class EmailTemplate {
Despite the table annotation, I receive java.sql.SQLException: Invalid object name 'email_template'. How can I prevent an entity class such as EmailTemplate being transformed into email_template table name?
Edit:
I'm using Spring Boot: start JPA. From my build.gradle file,
compile("org.springframework.boot:spring-boot-starter-data-jpa")
Spring by default uses org.springframework.boot.orm.jpa.SpringNamingStrategy which splits camel case names with underscore. Try setting spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.EJB3NamingStrategy in application.properties. Check out this and this for more info.
For hibernate v5:
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
For Spring Boot 2 (checked with 2.2.6.RELEASE) it should be configuration yml file:
spring:
jpa:
hibernate:
naming:
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
So you could have model like:
#Table(name = "tblDepartments")
public class Department {
#Id
#Column(name = "dpID")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#NotEmpty
#Size(min = 1, max = 25)
#Column(name = "dpName", length = 25)
private String name;
and populate tables at startup with data.sql:
INSERT INTO tblDepartments (dpName) VALUES ('Gryffindor');
INSERT INTO tblDepartments (dpName) VALUES ('Hufflepuff');
Use this in your appplication.properties.
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
Use
spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.DefaultNamingStrategy
In application.properties set
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
There are two most common org.hibernate.boot.model.naming.PhysicalNamingStrategys:
org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy
# also deprecated in 2.6 in favor of CamelCaseToUnderscoresNamingStrategy
# for removal in 2.8
org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties holds:
private void applyNamingStrategies(Map<String, Object> properties) {
applyNamingStrategy(properties, AvailableSettings.IMPLICIT_NAMING_STRATEGY, this.implicitStrategy,
() -> SpringImplicitNamingStrategy.class.getName());
applyNamingStrategy(properties, AvailableSettings.PHYSICAL_NAMING_STRATEGY, this.physicalStrategy,
() -> CamelCaseToUnderscoresNamingStrategy.class.getName());
}
so by default CamelCaseToUnderscoresNamingStrategy is in use and you have underscores...
org.springframework.dao.InvalidDataAccessResourceUsageException: could not execute statement; SQL [n/a];
nested exception is org.hibernate.exception.SQLGrammarException: could not execute statement
Both are required :
implicit-strategy
physical-strategy
Solved.
Invalid Object Name: Springboot with JPA(SQL server)
In application.yaml/properties specify the
spring.jpa.hibernate.naming.implicit-strategy
spring.jpa.hibernate.naming.physical-strategy
jpa:
show-sql: false
hibernate:
ddl-auto: none # Defaults to "none" when NOT in embedded mode
naming:
implicit-strategy: org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

Resources