Spring boot, Hibernate - create-drop uses old schema - sql-server

I have spring boot, spring data, hibernate and ms sql,
but with create-drop strategy, hibernate creates table based on older implementation of my #Entity class.
Entity class as so:
#Entity
public class User {
#Id
#GeneratedValue
private int id;
#Column(unique = true, nullable = false)
private String name;
#Column(nullable = false)
private String password;
#Column(nullable = false)
private String email;
#Column(nullable = false)
private boolean active = false;
#Column
private String activationUUID = UUID.randomUUID().toString();
//getters and setters
}
In application.properties, related config:
spring.jpa.hibernate.dialect=org.hibernate.dialect.SQLServer2012Dialect
spring.jpa.hibernate.ddl-auto=create-drop
But what I see in stdout, once I run my application:
2018-03-17 12:08:10.973 INFO 876 --- [ main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.SQLServer2008Dialect
2018-03-17 12:08:11.473 INFO 876 --- [ main] org.hibernate.tool.hbm2ddl.SchemaExport : HHH000227: Running hbm2ddl schema export
Hibernate: drop table [user]
Hibernate: create table [user] ([id] int identity not null, [account_activationuuid] varchar(255), [account_active] bit not null, [email] varchar(255) not null, [name] varchar(255) not null, [password] varchar(255) not null, [registration_date] datetime2 not null, primary key ([id]))
Hibernate: alter table [user] add constraint UK_gj2fy3dcix7ph7k8684gka40c unique ([name])
2018-03-17 12:08:11.488 INFO 876 --- [ main] org.hibernate.tool.hbm2ddl.SchemaExport : HHH000230: Schema export complete
Note that I have deleted #Column registration date, renamed accountActivationUUID to activationUUID, and renamed accountActive to active.
Still, I see old schema in stdout, and it is even like this stored in database.
So, my questions:
1) Where does this old schema come from ?
2) Does hibernate have some schema cache ?
3) How to make it generate new schema every time - being exactly representation of #Entity classes in my code ?
4) Why does it say to use 2008 dialect in stdout, even though I have specified 2012 dialect in application.properties ?
I tried invalidating cache in intelj, restarting computer and database, to search for file with old schema definition on hard drive, but none of it worked.
Thanks for any response :)

I found the problem and managed to make it work.
Problem was in pom.xml, there were some duplicates and some non-existent dependencies, so the run was just falling to latest successful run.
That's how it was using old schema.

Related

Django migrate column is not the same data type as referencing column

I have the below model which is an existing DB model and through Django's inspectdb management command the below model is created.
class ExistingLegacyModel(models.Model):
period = models.TextField(db_column="Period", blank=True, null=True)
key = models.AutoField(db_column="OutlookKey", primary_key=True)
class Meta:
managed = False
db_table = "table_name"
and currently, I'm trying to create a model with a field foreign key reference to the existing legacy DB model
class TestModel(models.Model):
period = models.ForeignKey(
ExistingLegacyModel,
on_delete=models.CASCADE,
db_column="OutlookKey",
)
so when I run the makemigrations command the migration file is successfully getting created with no issue. below is the migration file content.
class Migration(migrations.Migration):
initial = True
dependencies = [
('historical', '0011_phoenixcontractprice'),
]
operations = [
migrations.CreateModel(
name='TestModel',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('period', models.ForeignKey(db_column='OutlookKey', on_delete=django.db.models.deletion.CASCADE, to='app.ExistingLegacyModel')),
],
),
]
so now when i run the migrate command now, it is failing and giving the below error.
django.db.utils.ProgrammingError: ('42000', "[42000] [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]Column 'table_name.OutlookKey' is not the same data type as referencing column 'version_testmodel.OutlookKey' in foreign key 'version_testmodel_OutlookKey_eb16c31c_fk_table_name_OutlookKey'. (1778) (SQLExecDirectW); [42000] [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]Could not create constraint or index. See previous errors. (1750)")
I'm stuck with this issue for the past couple of days and I searched all over the internet but didn't get any resolution. I found a couple of StackOverflow questions that are very similar to my issue, but those questions are also unanswered.
Django - Migration foreign key field type not matching current type
Django 3.2 update AutoField to BigAutoField backward compatibility with foreign key relations
I'm currently using Django 3.2.13 and mssql-django to connect to the MSSQL database.
Any help on this will be highly appreciated! Thank you in advance.
UPDATE 1
I ran the sqlmigrate command for the initial migration. So for the period column, it is creating the table with a foreign key field with big int [OutlookKey] bigint NOT NULL whereas the existing legacy model has a normal integer field.
ALTER TABLE [<app>_<model>] ADD CONSTRAINT [<app>_<model>_OutlookKey_3505d410_fk_<existing_legacy_table>_OutlookKey] FOREIGN KEY ([OutlookKey]) REFERENCES [<existing_legacy_table>] ([OutlookKey]);

Jpa Conversion failed string to uniqueidentifier

Spring Boot: 2.0.2
Hibernate Core: 5.2.17
dialect: SQLServer2012Dialect
When trying to save entity whose id is a generated GUID into SQL Server
using JpaRepository save() method the operation fails with the following messages:
SQL Error: 8169, SQLState: S0002
Conversion failed when converting from a character string to
uniqueidentifier
HHH000327: Error performing load command :
org.hibernate.exception.SQLGrammarException: could not load an entity
com.microsoft.sqlserver.jdbc.SQLServerException: Conversion failed
when converting from a character string to uniqueidentifier
#Id
#GenericGenerator(name = "generator", strategy = "guid", parameters = {})
#GeneratedValue(generator = "generator" , strategy = GenerationType.AUTO)
#Column(name = "ActivityID" , columnDefinition="uniqueidentifier")
private String ActivityID;
Another description of the problem: Conversion failed from a character string to uniqueidentifier
Well, after some digging, here is what solved it for me:
Basically change the mapping to:
private UUID id;
#Id
#GeneratedValue
#Column( columnDefinition = "uuid", updatable = false )
public UUID getId() {
return id;
}
And don't forget to send a (not) friendly email to the DBA that decided to use that id type -.-
Regards

I want to use h2 database and scripts on my application but cannot connect it

I have my dependencies set and app.properties
pring.h2.console.enabled=true
spring.h2.console.path=/h2
#Spring data JPA properties
spring.datasource.url=jdbc:h2:mem:testdb:MODE=MySQL;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.hibernate.format_sql=true
hibernate.dialect=org.hibernate.dialect.H2Dialect
spring.thymeleaf.cache = false
in my resource directory I have two files table-script.sql for creating tables
and data-scripts.sql dumping insert statement but what can I do to get this database running on my console, help guys thanks and this is spring boot no other config file I needed or data source bean
#Profile("test")
#Configuration
#PropertySource(value = {"classpath:test.properties"})
static class ConfigTest {
#Autowired
private Environment env;
#Bean(name = "dataSource")
public DataSource dataSourceTest() {
return new EmbeddedDatabaseBuilder()
.generateUniqueName(true)
.setType(EmbeddedDatabaseType.H2)
.setScriptEncoding("UTF-8")
.addScripts("schema.sql", "data.sql")
.build();
}
#Bean
public JpaVendorAdapter jpaVendorAdapterTest() {
HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
adapter.setShowSql(false);
adapter.setDatabase(Database.H2);
adapter.setDatabasePlatform("org.hibernate.dialect.H2Dialect");
adapter.setGenerateDdl(true);
return adapter;
}
}
This is how I configured mine, as the Inmemory database names are auto generated I couldn't make the property file provide either. I had to let Java and Spring do that itself
table-script.sql
CREATE TABLE IF NOT EXISTS table1 (
id INT PRIMARY KEY AUTO_INCREMENT NOT NULL,
name VARCHAR(255) NOT NULL,
field_1 TEXT,
field_2 TEXT,
field_3 INT NOT NULL
);
CREATE TABLE IF NOT EXISTS table2 (
id INT PRIMARY KEY AUTO_INCREMENT NOT NULL,
name VARCHAR(255) NOT NULL,
field_1 TEXT,
field_2 TEXT,
field_3 INT NOT NULL
);
Here is sample folder structure
src
|--- main
|--- java
|--- com.project.root # classpath: <- genarally pointing here
|--- confing
|--- AppConfig.java #Above file
|--- resources
|--- table-script.sql
That's kind of all to it. Rest is handled by Spring. It run that file when it creating the random database.

spring data insert if not exists entity with field

Can anyone recommend a way to perform inserts in a database table via spring data jpa (in a clustered environment) only when the entry doesn't already exist in the database?
As an example situation, take a database with message and email_address tables. When a new message addressed to 'user#so.com' is added to the message table, a check will be done in the email_address table whether the email 'user#so.com' exists in the email_address and if it doesn't, it gets added to the database. Afterwards the email address entity field is set on the message entity and subsequently the message entity is saved.
#Entity
public class Message {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private long id;
#ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private EmailAddress emailAddress;
private String content;
}
#Entity
public class EmailAddress {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private long id;
// a unique constraint exists on this field on the database
private String email;
}
What should there be done with the spring data jpa EmailAddressRepository to avoid database exceptions that can occur when concurrently trying to insert entities with the same email address?
You could run a check inside a #PrePersist annotated method in your entity. Other than that, I don't think JPA or spring-data provide something out of the box for that.

HibernateException: Missing table error for a Join Table using Grails 2.0.2 on MS SQL legacy database

I am trying to get a many-to-many relationship working using Grails 2.0.1 on Windows 7. I have exhausted both Google, this site, and my Grails books. Nothing worked. I am connecting to a MS SQL Server 2005 database that I have READ only privileges on and yes - it is a legacy database. Everything in the 2 individual tables works fine (views OK & all) but when I try to add the join table code I get an error:
org.hibernate.HibernateException: Missing table: dbo.IN_USR_DRAWING_PRIV
The table does indeed exist and I can see it fine using IntelliJ's IDEA 10.5 Data Sources view & the MS SQL Server Management Studio. The relevant part of the error is this (I can send more ... much more if needed) :
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManagerPostProcessor': Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManager': Cannot resolve reference to bean 'sessionFactory' while setting bean property 'sessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory': Invocation of init method failed; nested exception is org.hibernate.HibernateException: Missing table: dbo.IN_USR_DRAWING_PRIV
Here are the 2 domain classes :
class Drawing {
static hasMany = [appusers:Appuser]
String id
String drawingId //this is in the join table
String drawingName
static transients = ['name']
void setName(String name) {
id = name
}
String getName() {
return id
}
static mapping = {
table name: "IN_DRAWING", schema: "dbo"
version false
id column: 'DRAWING_ID', generator:'identity', insertable:false, updateable:false
drawingId column: "`DRAWING_ID`",insertable:false, updateable:false //this is in the join table
drawingName column: "`DRAWING_NAME`"
appusers column: '`USR_ID`',
joinTable: 'IN_USR_DRAWING_PRIV'
}
}
class Appuser {
static belongsTo = Drawing
static hasMany = [drawings:Drawing]
String id
String usrId //this is in the join table
String usrName
static transients = ['name']
void setName(String name) {
id = name
}
String getName() {
return id
}
static mapping = {
table name: 'IN_USR', schema: "dbo"
version false
id column:'USR_ID', generator:'identity', insertable:false, updateable:false //this is in the join table
drawings column: 'DRAWING_ID',
joinTable: 'IN_USR_DRAWING_PRIV'
usrName column: "`USR_NAME`"
}
}
And here is the schema for the join table:
dbo.IN_USR_DRAWER_PRIV
USR_ID (PK, varchar(23), not null)
DRAWING_ID (PK, FK, varchar(23), not null)
PRIV_ID (PK, int, not null)
GRAG reports it has a composite key of all 3 columns, which it does along with a FK on DRAWING_ID.
Solutions that I have tried :
This code (which fails with the "Missing Table" exception.
Adding a domain controller for the join table - same result.
Any hints/clues/solutions appreciated.
I fixed this by using Groovy SQL directly and passing in the T-SQL.

Resources