Spring Batch Framework - Auto create Batch Table - database

I just created a batch job using Spring Batch framework, but I don't have Database privileges to run CREATE SQL. When I try to run the batch job I hit the error while the framework tried to create TABLE_BATCH_INSTANCE. I try to disable the
<jdbc:initialize-database data-source="dataSource" enabled="false">
...
</jdbc:initialize-database>
But after I tried I still hit the error
org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [SELECT JOB_INSTANCE_ID, JOB_NAME from BATCH_JOB_INSTANCE where JOB_NAME = ? and JOB_KEY = ?]; nested exception is java.sql.SQLSyntaxErrorException: ORA-00942: table or view does not exist
Anyway can disable the SQL, I just want to test my reader writer and processor work properly.

UPDATE:
As of spring 2.5.0, you should use spring.batch.jdbc.initialize-schema instead. See source.
With Spring Boot 2.0 you probably need this:
https://docs.spring.io/spring-boot/docs/2.0.0.M7/reference/htmlsingle/#howto-initialize-a-spring-batch-database
spring.batch.initialize-schema=always
By default it will only create the tables if you are using an embedded database.
Or
spring.batch.initialize-schema=never
To permanently disable it.

Spring Batch uses the database to save metadata for its recover/retry functionality.
If you can't create tables in the database then you have to disable this behaviour
If you can create the batch metadata tables but not in runtime then you might create them manually

Spring Batch required following tables to run job
BATCH_JOB_EXECUTION
BATCH_JOB_EXECUTION_CONTEXT
BATCH_JOB_EXECUTION_PARAMS
BATCH_JOB_EXECUTION_SEQ
BATCH_JOB_INSTANCE
BATCH_JOB_SEQ
BATCH_STEP_EXECUTION
BATCH_STEP_EXECUTION_CONTEXT
BATCH_STEP_EXECUTION_SEQ
If you are using h2 db then it will create all required table by default
spring.h2.console.enabled=true
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
When you start using Mysql or any other database you need to add follwing properties into application.properties
spring.batch.initialize-schema=always

Since Spring Boot 2.5.0 use
# to always initialize the datasource:
spring.batch.jdbc.initialize-schema=always
# to only initialize an embedded datasource:
spring.batch.jdbc.initialize-schema=embedded
# to never initialize the datasource:
spring.batch.jdbc.initialize-schema=never
(spring.batch.initialize-schema is deprecated since 2.5.0 for removal in 2.7.0)

To enable auto create spring batch data-schema simply add this line to your spring application.properties file :
spring.batch.initialize-schema=always
To understand more about Spring batch meta-data schema :
https://docs.spring.io/spring-batch/trunk/reference/html/metaDataSchema.html

Seems silly, but someone can have the same problem.
I was receiving this error after drop all tables from a database. When I tried to start the Spring Batch, I received the error:
bad SQL grammar [SELECT JOB_INSTANCE_ID, JOB_NAME from BATCH_JOB_INSTANCE where JOB_NAME = ? and JOB_KEY = ?]
and:
Invalid object name 'BATCH_JOB_INSTANCE'
This happened to me because I drop the tables without restart the service. The service was started and receive the database metadata with the Batch tables on the database. After drop them and not restart the server, the Spring Batch thought that the tables still exists.
After restart the Spring Batch server and execute the batch again, the tables were created without error.

When running with Spring Boot:
Running with Spring Boot v1.5.14.RELEASE, Spring v4.3.18.RELEASE
This should be enough:
spring:
batch:
initializer:
enabled: false
The initialize-schema did not work for this Spring boot version.
After that I was able to copy the SQL scripts from the spring-core jar and change the table capitalization since this was my issue with the automatic table creation under Windows/Mac/Linux.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd">
<!-- database -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/springbatch" />
<property name="username" value="root" />
<property name="password" value="" />
</bean>
<!-- transaction manager -->
<bean id="transactionManager" class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" />
<!-- create job-meta tables automatically -->
<jdbc:initialize-database data-source="dataSource">
<jdbc:script location="org/springframework/batch/core/schema-drop-mysql.sql" />
<jdbc:script location="org/springframework/batch/core/schema-mysql.sql" />
</jdbc:initialize-database>
</beans>
And make sure you are using compatible spring-jdbc -version with spring-batch.
Most probably spring-jdbc-3.2.2.RELEASE.JAR compatible.

<jdbc:initialize-database/> tag is parsed by Spring using InitializeDatabaseBeanDefinitionParser. You can try debugging this class in your IDE to make sure what values are being picked up for enabled attribute. Also this value can be disabled by using JVM parameter -Dspring.batch.initializer.enabled=false

this works for me: Spring boot 2.0
batch:
initialize-schema: never
initializer:
enabled: false

Use the following setting as the suggested one above has been deprecated:
spring.batch.jdbc.initialize-schema=always

In your DataSourceConfig you should add this code. Once the app comes up it deletes any existing schema , or creates a new one .
private DataSource dataSource() {
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
return builder.setType(EmbeddedDatabaseType.HSQL)
.addScript("classpath:org/springframework/batch/core/schema-drop-h2.sql")
.addScript("classpath:org/springframework/batch/core/schema-h2.sql")
.build();
}
If you are not able to do this , the schema scripts are present in your .m2 folder . Run the scripts manually.
Location is inside spring-batch-core jar.
C:\Users\XXX.m2\repository\org\springframework\batch\spring-batch-core\4.3.7.
Split open this jar and find sql schema script you want.
org\springframework\batch\core\schema-h2.sql.
org\springframework\batch\core\schema-drop-h2.sql.

Related

H2 database "if" query grammar [duplicate]

I have some problems with using a schema.sql file to create my sql schema when executing a junit test while this schema contains mysql specific expression. I have to add the mode=mysql to the H2 url.
For example something like this:
jdbc:h2:mem:testd;MODE=MYSQL
But Spring boot automatically uses the url defined in the enum
org.springframework.boot.autoconfigure.jdbc.EmbeddedDatabaseConnection with its url
jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE.
I have tried similiar approaches to get this to work, but spring does not take the spring.datasource.url=jdbc:h2:mem:testdb;MODE=MYSQL from my test-application.properties. All other settings from my test-application.properties have been read successfully.
If I let spring/hibernate create the schema (without the schema.sql file) with the javax.persistence annotations in my entities everything works fine.
Is there a simple way to add a mode?
Set
spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;MODE=MYSQL
in application-test.properties, plus
#RunWith(SpringRunner.class)
#DataJpaTest
#AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
#ActiveProfiles("test")
on the test class
I was having this same issue. It would not pick up the url when running tests. I'm using flyway to manage my scripts. I was able to get all of these working together by following these few steps.
Created a V1_init.sql script in src/test/resources/db/migration so that it is the first script run by flyway.
SET MODE MYSQL; /* another h2 way to set mode */
CREATE SCHEMA IF NOT EXISTS "public"; /* required due to issue with flyway --> https://stackoverflow.com/a/19115417/1224584*/
Updated application-test.yaml to include the schema name public:
flyway:
schemas: public
Ensure the test specified the profile: #ActiveProfiles("test")
I have tried similiar approaches to get this to work, but spring does not take the spring.datasource.url=jdbc:h2:mem:testdb;MODE=MYSQL from my test-application.properties
Did you try to append this parameters instead of rewriting the existing ones?
spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;MODE=MYSQL
All other settings from my test-application.properties have been read successfully.
I thought that file should be named application-test.properties.
I was able to run it with this config:
# for integration tests use H2 in MySQL mode
spring.datasource.url=jdbc:h2:mem:testdb;DATABASE_TO_LOWER=TRUE;MODE=MySQL;
spring.jpa.database-platform=org.hibernate.dialect.MariaDBDialect
The main trick here is to force Hibernate to generate SQL scripts for MariaDB dialect because otherwise Hibernate tries to use H2 dialect while H2 is already waiting for MySQL like commands.
Also I tried to use more fresh MariaDB103Dialect for MariaDB 10.3 but it doesn't worked properly.
You need to set MYSQL mode on h2 and disable replacing of datasource url for embedded database:
Modify application-test.yaml
spring:
datasource:
url: jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false;MODE=MYSQL
test:
database:
replace: NONE

how to do snowfalkes DB JNDI connection in Websphere Liberty application server

Is there a way to configure snowflakes connection pooling in websphere application serve.
I tried below config inside server.xml file. But not working.
<dataSource id="SnowflakeDataSource" jndiName="jdbc/BM_SF" type="javax.sql.DataSource">
<properties db="abcd" schema="_TARGET" URL="jdbc:snowflake://adpdc_cdl.us-east-1.privatelink.snowflakecomputing.com" user="****" password="****" />
<jdbcDriver libraryRef="DatacloudLibs" javax.sql.DataSource="net.snowflake.client.jdbc.SnowflakeBasicDataSource"/>
</dataSource>
To clarify, the configuration that you have configures WebSphere Application Server Liberty's connection pooling for a Snowflake data source, rather than Snowflake's connection pooling.
The configuration that you have looks mostly pretty good.
When I looked up the SnowflakeBasicDataSource class that you are using, I can see that it has a property called "databaseName", not "db", so you'll need to switch that in your configuration.
You will also need to configure one of the jdbc-4.x features in Liberty if you haven't already, and if you plan to look it up in JNDI (vs inject it), you'll need the jndi-1.0 feature.
Here is an example with some corrections:
<featureManager>
<feature>jdbc-4.2</feature>
<feature>jndi-1.0</feature>
... your other features here
</featureManager>
<dataSource id="SnowflakeDataSource" jndiName="jdbc/BM_SF" type="javax.sql.DataSource">
<properties databaseName="abcd" schema="_TARGET" URL="jdbc:snowflake://adpdc_cdl.us-east-1.privatelink.snowflakecomputing.com" user="****" password="****" />
<jdbcDriver libraryRef="DatacloudLibs" javax.sql.DataSource="net.snowflake.client.jdbc.SnowflakeBasicDataSource"/>
</dataSource>
If this still doesn't work, look into your definition of the DatacloudLibs library to ensure that it is properly pointing at the Snowflake JDBC driver, and if it still doesn't work, post the error message that you see in case it helps to determine the cause.

How to select a database in run time using spring boot

I have created an application with 2 databases. I need to select one of them in run time. Is there any method or class in spring boot.
You can do it using application.properties configurations. You don't need to restart the server for those configurations to act.
Please refer to:
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html
spring.datasource.url=jdbc:mysql://localhost/test
spring.datasource.username=dbuser
spring.datasource.password=dbpass
spring.datasource.driver-class-name=com.mysql.jdbc.Drive
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-sql.html

Spring - how to load configuration from database?

I need to load configuration settings used in applicationContext.xml from relational database (PostgreSQL).
I followed this article http://www.codeproject.com/Articles/28893/Loading-Application-Properties-from-a-Database but it uses a deprecated "Spring Modules" jar file.
Is there some another technique how to achieve it? I use Spring 3.
My idea is to set only access setting to database (hostname, dbname, username, password) for creating a datasource and probably create some own handler class(?) for loading setting from DB. In applicationContext.xml I will use settings in the same way - ${foo.bar}.
Plesase share your experience and code examples with this topic and Spring 3.
Although it's no longer bundled in Spring 3 I don't see any reason why you can't use it. Just include
<dependency>
<groupId>org.springmodules</groupId>
<artifactId>spring-modules-jakarta-commons</artifactId>
<version>0.8</version>
</dependency>
On your maven pom alongside with other Spring 3 dependencies and the setup as described in the tutorial should look alright.
If that produces specific error please post the details (incl. stack trace) so we can help investigate further

Persisting Entities to a Database Java

I'm just starting to work with persistence and databases in my use of webapps. I have created several Entity classes and have a database connection set up in Eclipse, but I'm not sure how to generate the tables from those entities. This is all I've managed to come up with so far:
public class Main {
#Resource
static UserTransaction utx;
#PersistenceUnit
static EntityManagerFactory emf;
public static void main(String[] args) throws Exception {
EntityManager em = emf.createEntityManager();
utx.begin();
em.joinTransaction();
User user = new User();
user.setUsername("cvolkernick");
em.persist(user);
utx.commit();
em.flush();
em.close();
emf.close();
}
}
You can create Tables from Entity declarations, using the Dali JPA Tools. As long as your project is configured with a JPA facet, you will have access to these tools. Creating tables from entities is as simple as right-clicking on your project, and then browsing through the context menu, as shown in the below screenshot:
Note that it is preferable to create tables in this manner, or by hand-coding the DDL statements yourself. It is not recommended to have the JPA provider create the tables for you, as you would lose the ability to place the table definitions under version control. They're also suboptimal and not meant to be used in production. Even for small projects, it is not worth the trouble, as the ability of the JPA provider (EclipseLink or Hibernate) to generate fine-tuned DDL statements is quite limited. In any case, if you wish to have the JPA provider do this work for you, details are as follows:
If your JPA provider is EclipseLink:
Your persistence.xml file ought to look like the following:
<?xml version="1.0" encoding="UTF-8"?>
<persistence ...>
<persistence-unit ...>
...
<properties>
<!-- valid values include 'none, 'drop-and-create-tables' and 'create-tables' -->
<property name="eclipselink.ddl-generation" value="create-tables"/>
<!-- valid values include 'both', 'database' and 'sql-script' -->
<property name="eclipselink.ddl-generation.output-mode" value="database"/>
...
</properties>
</persistence-unit>
</persistence>
You can configure these values from Eclipse, by opening the persistence.xml file with the Persistence XML editor:
Details of the EclipseLink schema generation properties and values can be found in the EclipseLink wiki.
If your JPA provider is Hibernate:
Your persistence.xml file ought to look like the following:
<?xml version="1.0" encoding="UTF-8"?>
<persistence ...>
<persistence-unit ...>
...
<properties>
<!-- valid values include 'validate', 'update', 'create' and 'create-drop' -->
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
...
</properties>
</persistence-unit>
</persistence>
Unlike the EclipseLink values, the ones for Hibernate cannot be configured from the Persistence XML editor of Eclipse. You can find other Hibernate properties in the Hibernate Core documentation.
Also, note that the in the case of both EclipseLink and Hibernate, you might need to specify additional properties like the connection pool configuration and the database dialect, to aid the schema generators.

Resources