I want to create my tables using Spring JPA auto table creation after that I want to insert my own data (SQL).
To be able to do this I used these lines in my application.properties
spring.jpa.hibernate.ddl-auto=create
spring.sql.init.data-locations=\
classpath:database/sectors_data.sql,\
classpath:database/users_data.sql
spring.sql.init.mode=always
The problem is that when I use ddl-auto=create and run my application it creates tables but does not insert data. To make it to insert data I should change ddl-auto=create to ddl-auto=update and run my application again.
I want to know is there a way to make it with only one run, create tables and then insert data without using any db migration tools like Flyway.
Thanks for answers.
Please note that script-based initialization i.e. through schema.sql and data.sql and Hibernate initialization together can cause some issues.
Either we disable Hibernate automatic schema creation:
spring.jpa.hibernate.ddl-auto=none
This will ensure that script-based initialization is performed using schema.sql and data.sql directly.
If we still want to have both Hibernate automatic schema generation in conjugation with script-based schema creation and data population, we'll have to use:
spring.jpa.defer-datasource-initialization=true
This will ensure, that after Hibernate schema creation is performed then additionally schema.sql is read for any additional schema changes and data.sql is executed to populate the database.
Also, script-based initialization is performed by default only for embedded databases, to always initialize a database using scripts, we'll have to use:
spring.sql.init.mode=always
refer spring-boot-data-sql-and-schema-sql
also refer official Spring documentation Initialize a Database Using Basic SQL Scripts
Related
I’m seriously confused about how flyway generally works to maintain the db as a code. Suppose I have the following V0 script:
Create table student(
Name varchar(25)
)
That would be my initial db. Now, suppose I want to add a new column, why am I being forced to do a V1 script like this one?
Alter table student add column surname varchar(25)
What I’d like to do would be to simply update the v0 script like this:
Create table student(
Name varchar(25),
Surname varchar(25)
)
Then the tool, by comparing the actual db, should be able to understand that a new column should be created!
This is as other code (java, javasctipt,..) tools work and the same I would it like to be for db as a code tools.
So my question is: is there a way to achieve this behavior without dropping/recreating the db?
I tagged this question with flyway and liquibase tools but feel free to suggest other tools that would fit my needs.
Whatever way you develop the database,there is no way to achieve this behavior without dropping/recreating the db, because the CREATE TABLE statement assumes that the table that you specify isn't already there. You can't use a CREATE OR ALTER statement because these aren't supported for tables even where the RDBMS that you use supports that syntax.
In the early stages of a database project, you can work very much quicker with a build script that you use to create a database with tables, views and so on. You can then insert some data, try it out, run a few tests, maybe and then tear it down. Flyway community supports this: you just have a single migration script starting from an empty database that you repeatedly 'clean' and 'migrate', until you reach your first version. Flyway takes care of the 'Tear-down' process. and give you a fresh start, by wiping your configured schemas completely clean.
Flyway Teams supports a special type of migration, the 'repeatable' that allows you to use for migrations SQL files that you can alter. However, you would need to add logic that deletes the table if it already exists before it executes your CREATE TABLE statement. It avoids having to 'Flyway clean', but it is a lot of extra work. It also means that you lose the whole advantage of a version representing an exact state of a database.
At some point, you are going to use migrations because you're likely to have copies of the database to keep up-to-date. Whatever tool you use to update a development or producton database, you are going to need to use a migration for this because of the existing data in tables.
Flyway Enterprise supports the automatic generation of a migration, if you are using Oracle or SQL Server. SQL Compare is provided to compare two versions of a database and produce a migration script from one version to the next. This allows you to use a build script as you suggest, compare it with the current version of the database, and generate a migration script to get from the one to the other.
We have changed the table schema and we need to change the schema name in all the procedures that table being used dynamically instead of manual replace.
If you would use SSDT for database development, you could utilise its refactoring capability of doing just that. Of course, any dynamic SQL will be left untouched, so if you have it in your code modules, you will need to search for it as usual.
If you don't plan to switch over to SSDT, you can create a database project, import schema from any existing database, perform any necessary refactoring and then deploy changes back to the database, either via a generated deployment script, or by using Schema Compare.
Is there a way to tell EF what to use for Autogrowth and Maxsize when it creates a database on SQL Server?
Actually I think you can't. You can also have a look here just to be sure
https://entityframework.codeplex.com/SourceControl/latest#src/EntityFramework.SqlServer/SqlProviderServices.cs
and on the called function (but it runs just a "create database" eventually specifing mdf and ldf file names).
Probably the best thing is that you create the database running a direct query before standard migrations.
EDIT
Database creation is not really automated, or better, you can decide when (and writing your migration, how) create it.
Actually I think you are using automatic migration (you did not write any code for migration).
Database is created if it does not exists and tables are created checking __MigrationHistory table (this is quite important because you can just create the DB without updating EF metadatas).
It happens before the first access to EF (at first access EF reads the mapping, check that the DB is ok and then executes the query you requested) or you can force it.
Actually I think that is more simple to decide if you need to run a create database (you can just check if it exists) than run an alter database if the parameters are wrong.
Your code could:
1. read the connection string from App/Web config
2. connect to master and not to the specified database
3. check if the database exists (select count(*) from sysdatabases where name = ...)
4. if it does not exists create it
Then you can continue with your normal code (EF will find the DB so the migrations will avoid to create it).
Enable migrations, but not automatic migrations. See this to learn about migrations.
Create the first migration. That creates an Up() and Down() method. You can see how to customize it in Customizing migrations section of the previous document.
In the up method you can use Sql("Your sql command") to run the ALTER DATABASE commands to set the growth an max size DB configuration.
Due to an error in our build process, we had the following initial situation:
Connection string of the datasource
jdbc:jtds:sqlserver://db01.example.de/AppDB_Example_Prod
Entity files have the catalog "AppDB_Example"
A stored procedure that is called using a named query
{ CALL usp_performSearch(:searchQuery) }
As you can see, we have a missmatch in the connection string and the catalogs. Normally, they must/should be equal.
At runtime, we execute the stored procedure and retrieved the results from the database AppDB_Example_Prod, as this is the database we are connected to. After that, we load related entities using the entityManager from the database AppDB_Example, as this is the catalog mentioned in the annotation of the entity. JPA is doing this itself, we do not have any influence on this.
Searching through the internet, I've read that you should create multiple persistence units / data sources, to work with multiple databases.
Does it work, as it is supposed do do or did we hit a bug?
Could this be used without any problem to work with multiple database via one connection string?
Does this only work with SQLServer (MSSQL) and so it will fail if we may change to an other database in the future?
This feature isn't supported by JPA itself but depends on the database and the permissions of your connection (= usually the DB user which you use to connect).
JPA doesn't care much about the schema. If you don't specify one, then JPA will not send schema information to the database. Usually, there is a default schema attached to the user (or one is specified via the JDBC connection settings). That way, the database knows where to look.
If you specify a schema, then JPA will include this information in the SQL it sends to the database. That means instead of TABLE.COLUMN, it will generate SCHEMA.TABLE.COLUMN. Whether this works depends only on the database (and maybe the JDBC driver) but not on JPA.
All SQL databases should allow you to look at other schemas than the default one if your DB user has the necessary permissions.
Due to an employee quitting, I've been given a project that is outside my area of expertise.
I have a product where each customer will have their own copy of a database. The UI for creating the database (licensing, basic info collection, etc) is being outsourced, so I was hoping to just have a single stored procedure they can call, providing a few parameters, and have the SP create the database. I have a script for creating the database, but I'm not sure the best way to actually execute the script.
From what I've found, this seems to be outside the scope of what a SP easily can do. Is there any sort of "best practice" for handling this sort of program flow?
Generally speaking, SQL scripts - both DML and DDL - are what you use for database creation and population. SQL Server has a command line interface called SQLCMD that these scripts can be run through - here's a link to the MSDN tutorial.
Assuming there's no customization to the tables or columns involved, you could get away with using either attach/reattach or backup/restore. These would require that a baseline database exist - no customer data. Then you use either of the methods mentioned to capture the database as-is. Backup/restore is preferrable because attach/reattach requires the database to be offline. But users need to be sync'd before they can access the database.
If you got the script to create database, it is easy for them to use it within their program. Do you have any specific pre-requisite to create the database & set permissions accordingly, you can wrap up all the scripts within 1 script file to execute.