I have a spring-boot application running using docker on a Ubuntu server, with MYSQL DB running on the server itself not in a docker image. The schema I am using for the spring-boot app keeps getting deleted randomly and I always have to restore it using backed up dump. I cannot determine the reason behind this weird issue. I tried googling this issue and I could not find anything about this issue.
What could possibly cause a DB to be dropped?!?
It is random like once a week! may be more than that. I cannot even track that.
My application.yml has this:
spring:
datasource:
url: jdbc:mysql://localhost/schemaname?useSSL=false
username: username
password: password
tomcat:
validation-query: SELECT 1
test-on-borrow: true
jpa:
show-sql: true
hibernate:
ddl-auto: update
properties:
hibernate:
dialect: org.hibernate.dialect.MySQL5Dialect
You shouldn't use ddl-auto for a production app.
Quote from Java Persistence with Hibernate.
WARNING: We've seen Hibernate users trying to use SchemaUpdate to
update the schema of a production database automatically. This can
quickly end in disaster and won't be allowed by your DBA.
This option is intended to be used only for development.
If you don't want to manually run your SQL migrations, you should consider tools like flyway or liquibase.
Related
What I am looking for is some suggestions on this behavior: Spring boot app(Considered as a microservice) should come up, irrespective of Db status.
Why I am doing this?
Based on my understanding of the microservice all services should be independent of each other.
I am using Spring boot with JPA (org.springframework.boot' version '2.5.7'). I am able to achieve this using the below configuration
spring:
datasource:
driverClassName: org.postgresql.Driver
url: jdbc:postgresql://localhost:5433/xxx?createDatabaseIfNotExist=true&characterEncoding=utf8&enabledTLSProtocols=TLSv1.2&useSSL=false
username: xx
password: xx
continueOnError: true
initialize: false
initialSize: 0
timeBetweenEvictionRunsMillis: 5000
minEvictableIdleTimeMillis: 5000
minIdle: 0
jpa:
show-sql: true
hibernate:
naming_strategy: org.hibernate.cfg.DefaultNamingStrategy
properties:
hibernate:
dialect: org.hibernate.dialect.PostgreSQLDialect
hbm2ddl:
auto: none
temp:
use_jdbc_metadata_defaults: false
But now the issue is I have to make hbm2ddl.auto none. Due to this, I am losing update schema functionalists which is one of the very essential functionality.
Requirement:
case 1. Service should be up and running irrespective of DB status
case 2. Jpa/Hibernate should update the database schema by comparing the existing schema with the entity mappings and generate the appropriate schema migration scripts (hbm2ddl.auto: update)
Can we achieve both? If yes how? or Do I have to compromise with one?
If I am going with only "case 1" do I have to rely on running schema updates manually or is there any other way?
thanks in advance
As mentioned in the comment you can exclude org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfigurationif you wish for spring boot to ignore the status of the data source (link on how to do that). In order to still have the schema auto-generated/controlled outside of your actual db you could use something like liquibase, which is used a lot in production environments.
Is there a way to quickly get initial SQL script for the database that is being generated by hibernating through ddl-auto property?
I would like to get an initial SQL script for the flyway as a quick start.
use property spring.jpa.show-sql = true and it will print all script on console in format.
use ddl-auto as you did and take backup of schema for your respective DB and use that as initial script
example - mysql , postgres
You can see the DDL script generated by Hibernate in a Spring boot application by setting the logging level of Hibernate to debug mode in the application.properties file of your project.
logging.level.org.hibernate.SQL=DEBUG
I am trying to set up in-memory H2 tables for a test class in my Spring boot application.
My config looks something like:
spring:
jpa:
show-sql: true
generate-ddl: true
properties:
hibernate:
dialect: org.hibernate.dialect.H2Dialect
hibernate:
ddl-auto: create-drop
datasource:
# not sure which one to use so added both just in case
initialization-mode: always
initialize: true
platform: h2
# casting a wide net here, but no cookie - completely ignored
data: data-h2.sql,classpath*:data-h2.sql, classpath:data-h2.sql
url: jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
driver-class-name: org.h2.Driver
username: sa
password:
As you can see, I'm trying to load a data-h2.sql script upon db initialization.
Unfortunately, the property is ignored no matter the value.
I am certain the configuration file is being picked up properly (e.g. among others, I desperately added a #Value("${spring.datasource.data}" -annotated property in my test class and the value was indeed populated correctly).
As an alternative, I could annotate the test class with #Sql("classpath:data-h2.sql") which did run the script - however it did so for every test, while I wanted the script to be run once before any test execution.
I also tried removing that and using a blank schema.sql and moving the population to data.sql (as suggested here), but Spring would complain about the empty schema file - which is useless to me, because my schema is auto-generated and I certainly don't want to re-create it (NB: probably a conflict with a hibernate property if memory serves).
I've browsed some of the answers here, but the only one I could use, is not working.
The only solution I can see is to keep the #Sql annotation, but try and clear the tables after every test with another #Sql annotation launching another script on #After.
This seems insane to me - there must be a better solution.
Am I missing something more esoteric than it already is in my configuration?
Simply put your file in the /main/resources directory (what you already did)
Spring Boot 2:
The correct property is:
spring.datasource.initialization-mode=always
Read more about this topic in the Spring Boot Documentation: https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-initialize-a-database-using-spring-jdbc
Spring Boot 1
You only have to place data-h2.sql in the classpath
Read more about this topic in the Spring Boot Documentation:
https://docs.spring.io/spring-boot/docs/1.5.8.RELEASE/reference/htmlsingle/#howto-initialize-a-database-using-spring-jdbc
I'm creating a spring boot application using Flyway to migration and want to use a memory database for development profile, but the problem is that data is lost every time I restart application. So I need to insert some data when my application start in development profile. I tried to put a file called data.sql on src/main/resource to spring load it when application starts but it doesnt work (It didnt run the script). I tried to put INIT=runscript from 'classpath:data.sql' in the h2 url but it tries to run it before Flyway migration execution so the tables doesnt exist yet. Can anyone give me an other way to do it?
My application.yml:
spring:
datasource:
url: jdbc:h2:mem:testdb;IFEXISTS=FALSE
username: sa
password:
driver-class-name: org.h2.Driver
jpa:
show-sql: true
hibernate:
ddl-auto: none
properties:
hibernate:
dialect: org.hibernate.dialect.H2Dialect
flyway:
enabled: true
Per documentation , a profile-specific customised flyway spring.flyway.locations can be configured. The profile-specific scripts runs when that profile is active . So a dev profile configured will work on this requirement.
The initialisation script can be placed as part of migration folder which will run and populate the db.
An example can be found here
My database.properties file is:
datasource.driver=org.h2.Driver
datasource.url=jdbc:h2:file:./test_database/comixed_db;create=true
datasource.username=sa
datasource.password=
hibernate.dialect=org.hibernate.dialect.H2Dialect
hibernate.hbm2ddl.auto=update
hibernate.show_sql=false
hibernate.format_sql=true
hibernate.batch.size=20
hibernate.current.session.context.class=org.springframework.orm.hibernate5.SpringSessionContext
hibernate.generate_statistics=false
hibernate.enable_lazy_load_no_trans=false
When my application starts up I see I am able to see the tables by using the h2.bat tool and peeking at the database from a web browser. However, when I shut down the application and then go back to the database with the h2.bat tool the tables are all gone!
AM I doing something incorrectly with my hibernate configuration? I am not using create-drop but update since this code is currently in flux and I'd like the tables to be adjusted as changes occur. But that doesn't seem to be the issue since it's at app shutdown that the tables keep going away.
Any help would be appreciated.
If you want spring boot to catch your hibernate properties you should prefix them with spring.jpa, so:
spring.jpa.hibernate.ddl-auto=update
Otherwise, and that is the case in my opinion, spring will use the default create-drop options as it is dealing with an H2 in-memory database.
By adding the following line to applications.properties:
spring.jpa.hibernate.ddl-auto=update
Spring-boot stopped dropping tables when the application exits.