Create database play java evolutions - mysql

I am using play java 2.5.
I have created a database with following java code.
public OnStartup() throws SQLException {
//demo create database with java code
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/?user=root&password=12345678");
Statement s = con.createStatement();
int Result = s.executeUpdate("CREATE DATABASE recruit3");
}
Module:
public class OnStartupModule extends AbstractModule {
#Override
public void configure() {
bind(OnStartup.class).asEagerSingleton();
}
}
application.conf:
play.modules {
enabled += "be.objectify.deadbolt.java.DeadboltModule"
enabled += modules.CustomDeadboltHook
enabled += modules.OnStartupModule
}
default.driver=com.mysql.jdbc.Driver
default.url="jdbc:mysql://localhost:3306/recruit3"
default.username=root
default.password="12345678"
My question is, why running the web-app creating
error Cannot connect to database [default]
How to fix that, if I don't want to create the database with mysql workbench.
Any suggestion or cannot do this, please tell me.
Thanks for advance.

As well as moving your database keys to the db.default namespace, you should be injecting Database into OnStartup to access the database configured with those properties.
First, add Play's JDBC support to build.sbt.
libraryDependencies += javaJdbc
If you're already running activator, make sure you use the reload command to pick up the changes to the build.
Update your application.conf to place the database configuration into the correct namespace.
db {
default {
driver=com.mysql.jdbc.Driver
url="jdbc:mysql://localhost:3306/recruit3"
username=root
password="12345678"
}
}
Finally, update OnStartup to receive a Database object that will be injected by Play.
import javax.inject.Inject;
import play.db.Database;
public class OnStartup {
#Inject
public OnStartup(final Database db) throws SQLException {
db.withConnection((Connection conn) -> {
final Statement s = con.createStatement();
return s.executeUpdate("CREATE DATABASE recruit3");
});
}
}
This allows you to configure the database one time, in application.conf, instead of hard-coding DB configuration into a class.
You can find more information here.

Your database keys start with default instead of db.default. The correct syntax is something like this:
db {
default {
driver=com.mysql.jdbc.Driver
url="jdbc:mysql://localhost:3306/recruit3"
username=root
password="12345678"
}
}
You already made your class as eager singleton, so it should work

Related

Using Entityframework Core, how can I dynamically change the MySql database, I connect to, without changing the connection string?

I'm using Pomelo Entity framework core with MySqlConnector in my asp.net 5 app to connect to my MySql database - using custom DbContext classes. This normally works fine.
However, I have a need to connect to another database than the one in the connection string (for instance 'INFORMATION_SCHEMA').
I can of course change the connection string, replacing the database name, but:
That creates an extra connection pool - one per connection string!
I'm trying to avoid that - having only one connection pool per website.
I was messing around with 'SetDefaultSchema' and other attempts that all fail miserably.
How can I change the database name, the DbContext uses so I only have one connection pool and still each DbContext has its own database to connect to?
The solution is actually quite simple: Use connection interceptor (available from Entity Framework Core 3.0+).
The code below switches the database after the connection has been opened.
Now each DbContext class can use its own database and with only one connection pool in use.
First you create an interceptor class inherited from DbConnectionInterceptor. The constructor takes the database name, you want to switch to, as parameter:
using Microsoft.EntityFrameworkCore.Diagnostics;
using System.Data.Common;
using System.Threading.Tasks;
public class MySqlConnectionInterceptor : DbConnectionInterceptor
{
public MySqlConnectionInterceptor(string databaseName)
{
database = databaseName;
}
readonly string database;
public override void ConnectionOpened(DbConnection connection, ConnectionEndEventData eventData)
{
if (database != null)
{
connection.ChangeDatabase(database); // The 'magic' code
}
base.ConnectionOpened(connection, eventData);
}
public override async Task ConnectionOpenedAsync(DbConnection connection, ConnectionEndEventData eventData, CancellationToken cancellationToken = default)
{
if (database != null)
{
await connection.ChangeDatabaseAsync(database); // The 'magic' code
}
await base.ConnectionOpenedAsync(connection, eventData, cancellationToken);
}
}
Now all you have to is include one line in your DbContext class's OnConfiguring method:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.AddInterceptors(new MySqlConnectionInterceptor("yourDatabase"));
}
Now the connection will switch to 'yourDatabase' database every time, it's opened.
And it will only use one connection pool (total)! That way the number of 'sleeping' connections are kept at a minimum.
This works because Pomelo Entity Framework Core always resets a connection before reusing it from the pool (unless you specifically sets 'Connectionreset=false' - which is bad anyway). It sets the database back to the one in the connection string, which you of course can override again).
Of course you don't have to hard code the database name. If you for instance use a base DbContext class, that your other DbContexts inherits from, you can create a constructor that takes the database name as parameter, like this:
public class BaseDbContext : DbContext
{
public BaseDbContext (string databaseName)
{
database = databaseName;
}
string database;
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.AddInterceptors(new MySqlConnectionInterceptor(database));
}
}
The code has been tested in Asp.Net 5+6 and .Net Windows Forms.

How to Configure spring datasource with GenericContainer that's creating a container from a custom MySQL Docker image

I am trying to run an integration test in spring that is using the data access layer but for that i need to connect to a database for me to run the application beans for testing. some of my testing involves using the database persisted data, so that's why i chose testContainers to run my database test using docker. The problem here is that i already have an sql image of my Own that contains populated entries that i need for testing and i don't want to create an empty database from scratch for testing, i want to use my own image for testing. but i don't know how i can configure my datasource for my spring boot from the docker image, cause with generic containers we don't have a getJDBCUrl() function or anything that would help me configure. I know its easy to configure the datasource if i am directly using the Mysql image. but for this one, i want to use my image.
#ClassRule
val databaseContainer: KGenericContainer = KGenericContainer("myOwnSqlImage:latest")
.withEnv("MYSQL_DATABASE", "databaseNamer")
.withEnv("MYSQL_USER", "root")
.withEnv("MYSQL_ROOT_PASSWORD", "root-password")
It's a postgres example, but I think you can reuse it for MySQL as well.
You should take a look at System.setProperty("spring.datasource.url", "jdbc:postgresql://${postgres.containerIpAddress}:${postgres.firstMappedPort}/service")
Groovy:
static {
def postgres = new GenericContainer("postgres:10").with {
addEnv("POSTGRES_DB", "service")
addEnv("POSTGRES_USERNAME", "postgres")
addEnv("POSTGRES_PASSWORD", "postgres")
withExposedPorts(5432)
}
postgres.start()
System.setProperty("spring.datasource.url", "jdbc:postgresql://${postgres.containerIpAddress}:${postgres.firstMappedPort}/service")
}
Kotlin:
class Test {
companion object {
fun database() {
val postgres = KGenericContainer("postgres:10")
postgres.addEnv("POSTGRES_DB", "service")
postgres.addEnv("POSTGRES_USERNAME", "postgres")
postgres.addEnv("POSTGRES_PASSWORD", "postgres")
postgres.withExposedPorts(5432)
postgres.start()
System.setProperty("spring.datasource.url", "jdbc:postgresql://${postgres.containerIpAddress}:${postgres.firstMappedPort}/service")
}
}
init {
database()
}
class KGenericContainer(dockerImageName: String) : GenericContainer<KGenericContainer>(dockerImageName)
}
fun main() {
Test()
}

Changing database type at runtime using EntityFramework

Is it possible to change database type at runtime? If yes, how it can be done? I am using EntityFramework 6.
Background about the question:
I have an application that initially does not have database access. A user first has to go through "installation" process and provide information about the database(including database type eg. MySql or MsSql).
I would like to avoid having 2 contexts if possible. If necessary I can provide more details.
You can specify the connection string at runtime using the following...
DbContext has a constructor that can be overloaded with the name of the connection string, or the connection string itself.
public partial class EntityName: DbContext {
public EntityName(): base("name=EntityName") {}
public EntityName(string connectionString): base(connectionString) {}
}
var connString = "PopulateConnString";
Using (var ctx = new EntityName(EntityConnectionStringBuilder)
{
// Do stuff
}

Flyway migration, Unable to obtain Jdbc connection from DataSource

I am trying to use flyway to create and manage a MySQL database. Here is the code i have got so far.
FlywayMigration.java : Class that applys the migration
public class FlywayMigration
{
public FlywayMigration(DatabaseConfiguration configuration, Flyway flyway)
{
flyway.setDataSource(configuration.getDataSource());
flyway.migrate();
}
public static void main(String[] args)
{
new FlywayMigration(new DatabaseConfiguration("database.properties"), new Flyway());
}
}
DatabaseConfiguration.java : Configuration class, this class will configure the datasource to be applyed to the Flyway.setDataSource method
public class DatabaseConfiguration
{
private final Logger LOGGER = LoggerFactory.getLogger(this.getClass());
private PropertiesUtil prop = null;
public DatabaseConfiguration(String file)
{
prop = new PropertiesUtil(file);
}
public String getDataSourceClass()
{
return prop.getProperty("mysql.data.source.class");
}
public String getURL ()
{
return prop.getProperty("mysql.url");
}
public String getHostName()
{
return prop.getProperty("mysql.host.name");
}
public String getDatabaseName()
{
return prop.getProperty("mysql.database.name");
}
public DataSource getDataSource()
{
MysqlDataSource dataSource = new MysqlDataSource();
dataSource.setURL(getURL());
dataSource.setUser(prop.getProperty("mysql.user.name"));
dataSource.setPassword(null);
return dataSource;
}
}
database.properties is the file where i store the database information, password can be null
mysql.data.source.class=com.mysql.jdbc.Driver
mysql.url=jdbc:mysql://localhost:3306/vmrDB
mysql.host.name=localhost
mysql.database.name=vmrDB
mysql.user.name=root
And i get the folowing error in my trace
Exception in thread "main" org.flywaydb.core.api.FlywayException: Unable to obtain Jdbc connection from DataSource
at org.flywaydb.core.internal.util.jdbc.JdbcUtils.openConnection(JdbcUtils.java:56)
at org.flywaydb.core.Flyway.execute(Flyway.java:1144)
at org.flywaydb.core.Flyway.migrate(Flyway.java:811)
at com.bt.sitb.vmr.migration.FlywayMigration.<init>(FlywayMigration.java:10)
at com.bt.sitb.vmr.migration.FlywayMigration.main(FlywayMigration.java:15)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
Can someone please tell me why the DataSource from MySQL is not connecting?
It looks like Flyway cannot connect to the database.
One reason for this is that the database in the database URL does not exist.
Question: does your database schema exist?
If your answer is no, then:
connect to jdbc:mysql://localhost:3306/mysql
also specify the schema to use for migration with flyway.setSchemas(configuration.getDatabaseName())
you also need flyway.init() before you can initialize migration of your database.
Ran into this same issue. Apparently, the problem was with my .properties file. The jar was using the one packaged with it and not the external one. So I moved my external properties file out of the resources folder and into the root directory of the jar and problem solved!
Hope this helps someone.
I had this same issue when working on a Java application in Debian 10 using Tomcat Application server.
I defined the connection strings for the database in the context.xml file, however, when I start out the application and try to log into the application, I get the error:
Exception in thread "main" org.flywaydb.core.api.FlywayException: Unable to obtain Jdbc connection from DataSource
at org.flywaydb.core.internal.util.jdbc.JdbcUtils.openConnection(JdbcUtils.java:56)
at org.flywaydb.core.Flyway.execute(Flyway.java:1144)
Here's what I figured out:
I finally realized that the application was using internally defined database connection strings that were packaged with it. The internally defined database connection strings were different from my own database connection strings defined in the context.xml file.
The solution for me was to either modify the internally defined database connection strings that were packaged with the application or use the same internally defined database connection strings that were packaged with application in my context.xml file.
That's all.
I hope this helps.

Fail to run Code-First Migration - RenameColumn - with MySql

I have an issue which I could not find answer for across the web.
I am using CodeFirst EF 4.3.1 Migrations with MySQL.
My MySQL provider is Devart.
After running Add-Migration against an existing database, I got the following code:
public partial class ChangeSet_1231 : DbMigration
{
public override void Up()
{
RenameColumn(table: "RW_TTaskInstanceProperties", name: "TaskInstance_TaskInstanceId", newName: "TaskInstanceId");
}
public override void Down()
{
RenameColumn(table: "RW_TTaskInstanceProperties", name: "TaskInstanceId", newName: "TaskInstance_TaskInstanceId");
}
}
Running Update-Database results in the following error:
PM> Update-Database -verbose –startupprojectname "RTDataAccess"
Using NuGet project 'RTDataAccess'.
Target database is: 'rsruntime' (DataSource: localhost, Provider: Devart.Data.MySql, Origin: Explicit).
Applying explicit migrations: [201205311312361_ChangeSet_1231].
Applying explicit migration: 201205311312361_ChangeSet_1231.
ALTER TABLE RW_TTaskInstanceProperties RENAME COLUMN TaskInstance_TaskInstanceId TO TaskInstanceId
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'COLUMN TaskInstance_TaskInstanceId TO TaskInstanceId' at line 2
From looking at the error details I see that the RenameColumn is translated to a MsSql command, rather than MySql command, so no wonder it reports about a syntax error.
Any ideas how to solve it?
I know I can use Update-Database -script, then edit the script to fit MySql and run it, but I prefer to make the Update-Database command work...
Thanks.
In response to Ladislav's question:
Yes, I registered the Devart's SQL generator for MySQL Migrations.
My Configuration class looks like that:
using Devart.Data.MySql.Entity.Configuration;
using Devart.Data.MySql.Entity.Migrations;
internal sealed class Configuration : DbMigrationsConfiguration<RTDataAccess.RTContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
MySqlEntityProviderConfig.Instance.Workarounds.IgnoreSchemaName = true;
var connectionInfo = MySqlConnectionInfo.CreateConnection("Server=xxxx;Port=yyyy;Database=rsruntime;Uid=zzzz;Pwd=wwww;charset=utf8;");
this.TargetDatabase = connectionInfo;
this.SetSqlGenerator(connectionInfo.GetInvariantName(), new MySqlEntityMigrationSqlGenerator());
}
protected override void Seed(RTDataAccess.RTContext context)
{
}
}
The issue was fixed by Devart.
Details at the following links:
http://forums.devart.com/viewtopic.php?f=2&t=24250
http://www.devart.com/dotconnect/mysql/download.html