Schema-validation: wrong column type encountered in column [name] in table [testTable] - spring

i'm getting this error while starting my springboot application:
Schema-validation: wrong column type encountered in column [name] in table [testTable];
found [character (Types#VARCHAR)], but expecting [clob (Types#CLOB)]
Other people of my team can run it just fine, but it doesn't work for me.
This is my class:
#Entity
#Table(name = "testTable")
data class TestTable(
#Id
val id: Long,
#Lob
#Column
val name: String,
#Column(nullable = false)
val parentId: Long,
I guess its a problem with mapping, but I don't understand why other people don't have the problem.
Thanks in advance.

Other people of your team probably use a different database schema. The error says that your model requires a CLOB column type (due to the use of #Lob), but the database column has the type VARCHAR. If you want to work with this schema, remove the #Lob annotation. Otherwise, migrate the column to CLOB: alter table testTable alter column name set data type clob

Related

JPA stores null value in CLOB when setting an empty String

Let's say I have an entity Entry with a Clob column like:
#Entity
public class Entry {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQUENCE_GENERATOR")
private Long id;
#Lob
#Column(name = "value")
private String data;
...
And in database we have an existing Entry row where VALUE is a clob initialized with Oracle's EMPTY_CLOB() function.
I need to clone the existing to a new entity, but after querying and setting an empty String for simulate the EMPTY_CLOB() from Java side, Oracle's show up a (null) value instead of an empty Clob.
Whe use hibernate as JPA implementation.
Expected after saving entity 2 with JPA:
SELECT * FROM ENTRY
ID VALUE
1 <------------ Returning an empty CLOB here
2 (null)
Actual behaviour
SELECT * FROM ENTRY
ID VALUE
1 <------------ Returning an empty CLOB here
2 <------------ Returning an empty CLOB here
It's because an empty string in Java is not NULL, and then the ORM generates an INSERT with "" for that column and the DEFAULT defined in the DDL is not applied, and eventually the '' is converted to NULL before caste-ed to CLOB.
With Hibernate, you may try to put #org.hibernate.annotations.Entity(dynamicInsert = true) or #DynamicInsert on the entity and don't set the column to empty string: if NULL, dynamic insert should skip it when generating the INSERT statement, so the DEFAULT defined in the DLL should be applied.
(Be aware of https://hibernate.atlassian.net/browse/HHH-7074)
(And you may also need dyanmicUpdate = true)

Cassandra + SpringBoot: Configure Table to automatically add INSERT timestamp

Small question regarding Cassandra, with the context of a SpringBoot application please.
I am interested in adding onto the table the timestamp of when a row gets inserted onto the table.
Therefore, when creating the table, I do this:
create table mytable (someprimarykey text PRIMARY KEY, timestamp long, someotherfield text);
I can see a column timestamp, happy.
Then, the web application:
#Table
public class MyTable {
#PrimaryKey
private final String somePrimaryKey;
private final long timestamp;
private final String someOtherField;
//constructor + getters + setters
And when I insert, I will do the usual:
MyTable myTable = new MyTable(somePK, System.currentTimeMillis(), "foo");
myTableRepository.save(myTable);
This works fine, I can see in the table my record, with the time of the insert, happy.
Problem:
Now, for the hundreds of POJOs I am interested to insert into Cassandra, all of them are carrying this timestamp long field. Somehow, on the web application layer, I am dealing with a database concept, the timestamp of the write.
Question:
May I ask if it is possible to delegate this back to the database? Some kind of:
create table mytable (someprimarykey text PRIMARY KEY, hey-cassandra-please-automatically-add-the-time-when-this-row-is-written long, someotherfield text);
or
create table mytable (someprimarykey text PRIMARY KEY, someotherfield text WITH default timestamp-insert-time-column);
And the web app can have the abstraction creating and inserting POJOs without carrying this timestamp field?
Thank you
It isn't necessary to store the insert time of each row separately since Cassandra already stores this for all writes in the metadata.
There is a built-in CQL function WRITETIME() which returns the date/time (encoded in microseconds) when a column was written to the database.
In your case, you can query your table with:
SELECT WRITETIME(someotherfield) FROM mytable WHERE someprimarykey = ?
For details, see the CQL doc on retrieving the write time. Cheers!

HSQLDB column and table names in lowercases

I have a spring boot app which generates a schema with flyway in an hsqldb.
The problem is that all table and column names are converted to upper case (TBL_ROLE, ID, NAME).
The aim is to have the names in the db exactly like in my script defined.
Flyway script:
create table tbl_role (
id integer not null,
name varchar(255),
default_layout varchar(255),
primary
key (id))
Entity:
#Entity
#Table(name = "tbl_role")
public class Role {
#Id
private Integer id;
private String name;
...
Hibernate Output:
org.hibernate.SQL : create table tbl_role (id integer not null, default_layout varchar(255), name varchar(255), possible_layouts varchar(255), primary key (id))
I tried to write the table and column names in double qoutes and single quotes but this didn't had any effect.
Any ideas how to achieve this?
Problem was that the flyway scripts weren't executed. So the changes with the double quotes weren't applied.
Nevertheless it's not a perfect solution..

#OneToMany Column not showing?

I am new to Hibernate and curious, why my column is not showing.
So I have following code (in kotlin):
#Entity
class Project (
var guid: String = "",
#OneToMany(mappedBy = "project", cascade = [CascadeType.ALL])
var tickets: List<Ticket?>,
var current: Date
){
#Id #GeneratedValue(strategy = GenerationType.AUTO)
var id: Long = 0
}
and the other entity:
#Entity
class Ticket (
var guid: String = "",
#ManyToOne
#JoinColumn(name="project_id")
var project: Project?,
var current: Date
){
#Id #GeneratedValue(strategy = GenerationType.AUTO)
var id: Long = 0
}
In my database, the table "ticket" has a column project_id, with null values.
BUT my other table "Project" has no column for the list of Tickets. What went wrong? Every help will be appreciated, please dont forget to explain.
Thank you!
The reason your Project table has no column for the list of tickets, is that relational databases are designed to have one value per cell. You cannot store a list or array of something in a table. The solution for this is to create another table (let's call it the child table) that references this table (the parent table). Each row in the child table will be one entry of that list, and stores a reference to the parent list. So in a way, the relationship has been inverted: instead of storing the tickets in the Project table, a reference to the Project table is stored in the Ticket table.
In your case, you're indicating that the project_id should be used as a reference, since you're mentioning it in the #JoinColumn. However, there is no such property in the Project table, so you should add it. Hibernate is expecting that this is the column to link the two tables.
Also: don't forget to create a foreign key constraint to the parent table on the column that you're using in the Ticket table either.

Hibernate Jpa - constraint violation exception on Primary Key(Sequence)

I use Hibernate JPA in my application. I have a Table that has a Primary key(Sequence). Service inserts records to that table.
Version: Oracle 12c
Dialect: org.hibernate.dialect.Oracle10gDialect
Issue :
We face problem(Unique constraint violation on SEQUENCE Key) during the load testing.
Questions :
This issue is not occurring all the time. But only during load test. Can someone please check and help to use thread safe generator?
Is it DB side sequence definition issue or at Java side?
DB Sequence :
CREATE SEQUENCE MY_SEQ
START WITH 1
INCREMENT BY 1
NOMINVALUE
NOMAXVALUE
CACHE 30
NOORDER;
CREATE TABLE MY_TABLE (
MY_PRIMARY_KEY INT default MY_SEQ.nextval NOT NULL,
VALUE_COL VARCHAR2(10) NULL
);
Entity :
public class MyTableEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "MY_PRIMARY_KEY")
#GenericGenerator(
        name = "mySequenceGenerator",
        strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator",
        parameters = {
                #Parameter(name = "sequence_name", value = "SEQUENCE MY_SEQ"),
                #Parameter(name = "increment_size", value = "1")
        }
)
#GeneratedValue(generator = "mySequenceGenerator")
private long myPrimaryKey;
#Column(name = "VALUE")
private String value;
}
Oracle 10 Dialect
For Oracle10gDialect use this configuration
#Id
#Column(name = "MY_PRIMARY_KEY")
#GeneratedValue(strategy=GenerationType.AUTO)
Long myPrimaryKey;
Hibernate creates a table and a sequence:
create table MY_TABLE (
MY_PRIMARY_KEY number(19,0) not null,
VALUE varchar2(255 char),
primary key (MY_PRIMARY_KEY))
create sequence hibernate_sequence
While storing it first gets the new sequence ID and than passes it in the INSERT statement
select hibernate_sequence.nextval from dual
insert into MY_TABLE (VALUE, MY_PRIMARY_KEY) values (?, ?)
Oracle 12 Dialect
If you use Oracle 12 that natively supports IDENTITY column it is prefered to upgrade to Oracle12cDialect (note that this requires Hibernate 5.3)
Set the strategy to GenerationType.IDENTITY
#Id
#Column(name = "MY_PRIMARY_KEY", updatable = false, nullable = false)
#GeneratedValue(strategy=GenerationType.IDENTITY)
Long myPrimaryKey;
The following table is created - the important part is generated as identity which provides the unique velues.
Note that no explicite sequence is required to be created, it is managed internally .
create table MY_TABLE (
MY_PRIMARY_KEY number(19,0) generated as identity,
VALUE varchar2(255 char),
primary key (MY_PRIMARY_KEY))
While storing no ID is passed in the INSERT, it is assigned by Oracle and returned to the session
insert into MY_TABLE (VALUE) values (?) RETURNING MY_PRIMARY_KEY INTO ?
Note that in contrary to the Oracle 10 you save one round trip to the database.
Change long to Long
Because if you use long, it (by default) is 0. No generator is allowed to change existing values!
https://docs.oracle.com/javaee/7/api/javax/persistence/GeneratedValue.html

Resources