Grails creates old columns from in mysql database event on clean schema - mysql

During development I added some fields to some domain classes. Then after re-factoring these fields were removed.
But they continue to appear in database schema, even if I drop and recreate it between "grails run-app" invocations.
Can anyone give an idea of what's going on? There are no references to these fields any more in the app.
I'm running Grails 2.4.3 in dev mode with mysql 5.6
As a matter of fact this happens from time to time, i.e. sometimes after recreating the schema old fields are not created.
Here's my datasource config:
environments {
development {
dataSource {
driverClassName = "com.mysql.jdbc.Driver"
dialect = "com.dropbyke.mysql.dialect.MySQLUTF8InnoDBDialect"
dbCreate = "update"
url = "jdbc:mysql://localhost:3306/dropbike?useUnicode=true&characterEncoding=UTF-8"
username = "root"
password = "123"
}
}
UPD:
MySQLUTF8InnoDBDialect is custom dialect:
public class MySQLUTF8InnoDBDialect extends MySQL5InnoDBDialect {
#Override
public String getTableTypeString() {
return " ENGINE=InnoDB DEFAULT CHARSET=utf8";
}
}

Related

Why the second database not created when multiple datasources in Springboot application?

I want to use two (Mysql) databases in my Springboot application. Following the instructions I use the following configuration
app.properties
spring.datasource.url = jdbc:mysql://localhost:3306/db1?createDatabaseIfNotExist=true&autoReconnect=true
spring.datasource.username = root
spring.datasource.password = password
spring.seconddatasource.url = jdbc:mysql://localhost:3306/db2?createDatabaseIfNotExist=true&autoReconnect=true
spring.seconddatasource.username = root
spring.seconddatasource.password = password
DataSourceConfig.java
#Configuration
public class DataSourceConfig {
#Bean("dataSource")
#Primary
#ConfigurationProperties(prefix = "spring.datasource")
public DataSource dataSource() {
return DataSourceBuilder.create()
.type(DriverManagerDataSource.class)
.build();
}
#Bean("secondDataSource")
#ConfigurationProperties(prefix = "spring.seconddatasource")
public DataSource secondDataSource() {
return DataSourceBuilder.create()
.type(DriverManagerDataSource.class)
.build();
}
}
The application starts without errors but only the first database (or whichever datasource bean is marked as primary) gets created. Why not the second?
EDIT:
Once I create the second database manually, the application connects to both of them just fine. It is the automatic creation of the non-primary database only that is causing the problems.
Because you're using #ConfigurationProperties wrong. The annotation most certainly does not point a bean to the relevant configuration. The first DB gets created because, well, spring.datasource.* are actually standard Spring Boot properties.
If you wish to create two data sources, at the very least you'll need to set the appropriate properties (url, password) on the second one yourself. You may inject your custom properties (spring.seconddatasource.*) into the configuration class using #Value, of course.

Create database play java evolutions

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

What's the best way to migrate to ServiceStack authentication framework when stuck with my_aspnet_* tables

I'm not quite ready to change up all my user/auth tables from the MySQL user/roles/profile provider format, but am moving off of MVC to ServiceStack.
Is there a pre-built IUserAuthRespository and/or CredentialsAuthProvider somewhere that can be used, or do I need to build one to provide this mapping?
If I need to build one, I assume implementing at the IUserAuthRepository level is the cleanest? Is there a minimum set of methods required to implement basic login/logout (and administrative "switch user" impersonation) functionality?
I tried implementing a custom CredentialsAuthProvider, which seems to work, but I'm unable to get local posts for impersonation to use the proper provider. Looking for a solution to that, I realized that maybe its better to implement the repository instead.
EDIT:
My current registration of the custom auth provider is:
Plugins.Add(new AuthFeature(() => new AuthUserSession(), new IAuthProvider[]
{
container.Resolve<MySqlCredentialsAuthProvider>() //HTML Form post of UserName/Password credentials
}));
And calling code for the local post to the AuthenticateService is:
[RequiredRole(SystemRoles.Administrator)]
public object Any(ImpersonateUser request)
{
using (var service = base.ResolveService<AuthenticateService>()) //In Process
{
//lets us login without a password if we call it internally
var result = service.Post(new Authenticate
{
provider = AuthenticateService.CredentialsProvider,
UserName = request.Username,
//Password = "should-not-matter-since-we-are-posting-locally"
});
return result;
}
}
Integrating with existing User Auth tables
If you want to use your existing User/Auth tables, the easiest solution is to ignore the UserAuth repositories and implement a Custom CredentialsAuthProvider that looks at your existing database tables to return whether their Authentication attempt was successful.
Implement OnAuthenticated() to populate the rest of your typed IAuthSession from your database, e.g:
public class CustomCredentialsAuthProvider : CredentialsAuthProvider
{
public override bool TryAuthenticate(IServiceBase authService,
string userName, string password)
{
//Add here your custom auth logic (database calls etc)
//Return true if credentials are valid, otherwise false
}
public override IHttpResult OnAuthenticated(IServiceBase authService,
IAuthSession session, IAuthTokens tokens,
Dictionary<string, string> authInfo)
{
//Fill IAuthSession with data you want to retrieve in the app eg:
session.FirstName = "some_firstname_from_db";
//...
//Call base method to Save Session and fire Auth/Session callbacks:
return base.OnAuthenticated(authService, session, tokens, authInfo);
//Alternatively avoid built-in behavior and explicitly save session with
//authService.SaveSession(session, SessionExpiry);
//return null;
}
}
Importing existing User Auth tables
If you want to import them into an OrmLite User Auth tables, you would configure to use the OrmLiteAuthRepository in your AppHost:
//Register to use MySql Dialect Provider
container.Register<IDbConnectionFactory>(
new OrmLiteConnectionFactory(dbConnString, MySqlDialect.Provider));
Plugins.Add(new AuthFeature(
() => new CustomUserSession(), //Use your own typed Custom UserSession type
new IAuthProvider[] {
//HTML Form post of UserName/Password credentials
new CredentialsAuthProvider()
}));
//Tell ServiceStack you want to persist User Info in the registered MySql DB above
container.Register<IUserAuthRepository>(c =>
new OrmLiteAuthRepository(c.Resolve<IDbConnectionFactory>()));
//Resolve instance of configured IUserAuthRepository
var userAuth = container.Resolve<IUserAuthRepository>();
//Create any missing UserAuth RDBMS tables
authRepo.InitSchema();
Then to import your data you can use the above MySQL DB connection to select from your existing tables then use the IUserAuthRepository to create new Users.
// Open DB Connection to RDBMS
using (var db = container.Resolve<IDbConnectionFactory>().Open())
{
//Example of fetching old Users out of a custom table (use your table instead)
var oldUsers = db.Select<OldUserInfo>();
// Clear existing UserAuth tables if you want to replay this import
//db.DeleteAll<UserAuthDetails>();
//db.DeleteAll<UserAuth>();
//Go through and create new User Accounts using Old User Info
foreach (var oldUser in oldUsers)
{
//Create New User Info from Old Info
var newUser = new UserAuth {
UserName = oldUser.UserName,
Email = oldUser.Email,
//...
};
//Create New User Account with oldUser Password
authRepo.CreateUserAuth(newUser, oldUser.Password);
}
}
After this you'll have new User Accounts from your old User Info which you can sign in with.

How to properly set-up Spring Boot & Hibernate using InteliJ?

As the title suggests I am building a web application using Spring Boot and Hibernate for my data access layer and the development is done on InteliJ IDEA 14.1.2.
My Knowledge
This is my first time using Spring Boot, Hibernate and InteliJ. I have built a few small apps to test Spring Boot and Hibernate, but the complexity difference between those and the one I am building now is a bit bigger.
Environment
Regarding my environment, in case it matters, I am running Windows 7 SP1 64bit, MySQL server 5.6.17, InteliJ 14.1.2 and Ubuntu Server 14.04 on a VirtualBox 4.3.26 VM hosting a Redis 3.0.1 server.
Purpose
The purpose of using the above technologies at this point in time is the storage and retrieval of different entities to a MySQL database (Redis is used only for session externalization and sharing among app instances). In other words, I am building my data access layer.
Database
My complete database schema can be found here:
https://dl.dropboxusercontent.com/u/49544122/so/DB.pdf
Source
My Spring Boot application is the following:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import se.domain.cvs.abstraction.dataaccess.AccountRepository;
import se.domain.cvs.domain.AccountEntity;
#SpringBootApplication
#EnableRedisHttpSession
public class Application implements CommandLineRunner {
#Autowired
AccountRepository repository;
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Override
public void run(String... strings) throws Exception {
System.out.println("=======================================================");
AccountEntity account = repository.findByEmail("r.franklin#companya.se");
System.out.println("My name is " + account.getFirstName() + " " + account.getLastName());
System.out.println("=======================================================");
}
}
I am using CommandLineRunner interface just to test the bare data access layer without introducing REST endpoints yet.
My configuration is the following in YAML format:
...
# MySQL Database Configuration
spring.datasource:
url: jdbc:mysql://localhost:3306/cvs
username: cvs
password: cvs
driverClassName: com.mysql.jdbc.Driver
spring.jpa:
database: MYSQL
show-sql: true
hibernate.ddl-auto: validate
hibernate.naming-strategy: org.hibernate.cfg.DefaultNamingStrategy
properties.hibernate.dialect: org.hibernate.dialect.MySQL5Dialect
...
The JPA entities are automatically generated with InteliJ and that is where the problems begin. Let's take for example the OrderEntity below (for the sake of brevity I omit some code):
...
#Entity
#Table(name = "order", schema = "", catalog = "cvs")
public class OrderEntity {
...
private int invoiceId;
...
private InvoiceEntity invoiceByInvoiceId;
...
#Basic
#Column(name = "InvoiceID", nullable = false, insertable = false, updatable = false)
public int getInvoiceId() {
return invoiceId;
}
public void setInvoiceId(int invoiceId) {
this.invoiceId = invoiceId;
}
...
#ManyToOne
#JoinColumn(name = "InvoiceID", referencedColumnName = "InvoiceID", nullable = false)
public InvoiceEntity getInvoiceByInvoiceId() {
return invoiceByInvoiceId;
}
public void setInvoiceByInvoiceId(InvoiceEntity invoiceByInvoiceId) {
this.invoiceByInvoiceId = invoiceByInvoiceId;
}
...
}
When trying to run the Spring Boot application I get the following error:
org.hibernate.MappingException: Repeated column in mapping for entity: OrderEntity column: invoiceId (should be mapped with insert="false" update="false")
After doing a little bit of research, I guess the problem is that the invoiceID now has two ways to be set, one through the setInvoiceID() setter and one through the InvoiceEntity object itself that the OrderEntity relates to, which could lead to an inconsistent state. As another user here puts it,
You would do that when the responsibility of creating/udpating the related entity in question isn't in the current entity.
See related post here: Please explain about: insertable=false, updatable=false
Setting the proposed values of the corresponding field (insertable and updateable) to false fixes the error.
My question here is why is this generated the wrong way? My change fixed the error, but I want to make sure that there is no errors in my SQL that lead InteliJ to generate this the wrong way. The complete SQL script can be found here http://pastebin.com/aDguqR1N.
Additionally, when generating the Entities, InteliJ requires a Hibernate config file which I guess Spring Boot generates on its own somewhere else (or uses Java based configuration). Whether I leave it there or delete it, it doesn't seem to affect the app at all. I guess the order taken by SB to read properties overrides it. Is it OK that I just remove it?
Thank you very much for your time and help in advance and sorry for this long post! :)
my advice is to let Spring/Hibernate let generate your db schema for you ( everything including foreign keys and constraints can be generated by Spring.
For me the folloeing approach worked:
in the parent entity(in my case the TblUser):
#OneToMany(targetEntity=TblTracks.class,fetch=FetchType.EAGER,cascade=CascadeType.ALL,mappedBy="tbluser")
private List<TblTracks> tbltracks= new ArrayList<TblTracks>();
where mappedBy points to the Tbluser Entity (private TblUser tbluser) of the child Entity
and in the child entity (in my case TblTracks) like
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name="idTblUser",nullable=false)
private TblUser tbluser;

Grails: Joda LocalDate as unique key in a MySQL database

I have a domain class with a Joda LocalDate property. This property must be unique.
It works using an H2, but using a MySQL db I have this error on app boot:
[SchemaExport.create(l.386)]Unsuccessful: create table [...]
[SchemaExport.create(l.387)]BLOB/TEXT column 'mydate' used in key specification without a key length
If a remove unique constraint, it works also with MySQL.
Is it a bug or my misunderstanding?
I'm using Grails 2.2.5.
Here domain fragment:
class MyClass {
LocalDate mydate
static constraints = {
mydate(nullable:false, unique:true)
}
}
DataSource config fragment:
dataSource {
dbCreate = "create-drop"
driverClassName = "com.mysql.jdbc.Driver"
dialect = org.hibernate.dialect.MySQL5InnoDBDialect
username = "xxx"
password = "xxx"
dbNamer = "myapp"
url = "jdbc:mysql://localhost:3306/${dbNamer}?autoreconnect=true"
logSql = true
}
wild guess, I think that date is reserved word in mySQL. rename the field and try again
UPDATE:
ok, I see.
the problem is, that GORM/Hibernate is not aware of joda LocalDate class, so it's trying to create a BLOB column for it:
[SchemaExport.create(l.387)]BLOB/TEXT column 'mydate'`.
To fix it, you can either use a custom hibernate type (have no idea how), or convert the property into a plane java's Date class by saving, and back to LocalDate after loading