I use in application MySQL 5.7 and I have JSON columns. When I try running my integration tests don't work because the H2 database can't create the table. This is the error:
2016-09-21 16:35:29.729 ERROR 10981 --- [ main] org.hibernate.tool.hbm2ddl.SchemaExport : HHH000389: Unsuccessful: create table payment_transaction (id bigint generated by default as identity, creation_date timestamp not null, payload json, period integer, public_id varchar(255) not null, state varchar(255) not null, subscription_id_zuora varchar(255), type varchar(255) not null, user_id bigint not null, primary key (id))
2016-09-21 16:35:29.730 ERROR 10981 --- [ main] org.hibernate.tool.hbm2ddl.SchemaExport : Unknown data type: "JSON"; SQL statement:
This is the entity class.
#Table(name = "payment_transaction")
public class PaymentTransaction extends DomainObject implements Serializable {
#Convert(converter = JpaPayloadConverter.class)
#Column(name = "payload", insertable = true, updatable = true, nullable = true, columnDefinition = "json")
private Payload payload;
public Payload getPayload() {
return payload;
}
public void setPayload(Payload payload) {
this.payload = payload;
}
}
And the subclass:
public class Payload implements Serializable {
private Long userId;
private SubscriptionType type;
private String paymentId;
private List<String> ratePlanId;
private Integer period;
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public SubscriptionType getType() {
return type;
}
public void setType(SubscriptionType type) {
this.type = type;
}
public String getPaymentId() {
return paymentId;
}
public void setPaymentId(String paymentId) {
this.paymentId = paymentId;
}
public List<String> getRatePlanId() {
return ratePlanId;
}
public void setRatePlanId(List<String> ratePlanId) {
this.ratePlanId = ratePlanId;
}
public Integer getPeriod() {
return period;
}
public void setPeriod(Integer period) {
this.period = period;
}
}
And this converter for insert in database:
public class JpaPayloadConverter implements AttributeConverter<Payload, String> {
// ObjectMapper is thread safe
private final static ObjectMapper objectMapper = new ObjectMapper();
private Logger log = LoggerFactory.getLogger(getClass());
#Override
public String convertToDatabaseColumn(Payload attribute) {
String jsonString = "";
try {
log.debug("Start convertToDatabaseColumn");
// convert list of POJO to json
jsonString = objectMapper.writeValueAsString(attribute);
log.debug("convertToDatabaseColumn" + jsonString);
} catch (JsonProcessingException ex) {
log.error(ex.getMessage());
}
return jsonString;
}
#Override
public Payload convertToEntityAttribute(String dbData) {
Payload payload = new Payload();
try {
log.debug("Start convertToEntityAttribute");
// convert json to list of POJO
payload = objectMapper.readValue(dbData, Payload.class);
log.debug("JsonDocumentsConverter.convertToDatabaseColumn" + payload);
} catch (IOException ex) {
log.error(ex.getMessage());
}
return payload;
}
}
I just came across this problem working with the JSONB column type - the binary version of the JSON type, which doesn't map to TEXT.
For future reference, you can define a custom type in H2 using CREATE DOMAIN, as follows:
CREATE domain IF NOT EXISTS jsonb AS other;
This seemed to work for me, and allowed me to successfully test my code against the entity.
Source: https://objectpartners.com/2015/05/26/grails-postgresql-9-4-and-jsonb/
Champagne time! 🍾
Starting with the version 2.11, the Hibernate Types project now provides a generic JsonType that works auto-magically with:
Oracle,
SQL Server,
PostgreSQL,
MySQL, and
H2.
Oracle
#Entity(name = "Book")
#Table(name = "book")
#TypeDef(name = "json", typeClass = JsonType.class)
public class Book {
#Id
#GeneratedValue
private Long id;
#NaturalId
#Column(length = 15)
private String isbn;
#Type(type = "json")
#Column(columnDefinition = "VARCHAR2(1000) CONSTRAINT IS_VALID_JSON CHECK (properties IS JSON)")
private Map<String, String> properties = new HashMap<>();
}
SQL Server
#Entity(name = "Book")
#Table(name = "book")
#TypeDef(name = "json", typeClass = JsonType.class)
public class Book {
#Id
#GeneratedValue
private Long id;
#NaturalId
#Column(length = 15)
private String isbn;
#Type(type = "json")
#Column(columnDefinition = "NVARCHAR(1000) CHECK(ISJSON(properties) = 1)")
private Map<String, String> properties = new HashMap<>();
}
PostgreSQL
#Entity(name = "Book")
#Table(name = "book")
#TypeDef(name = "json", typeClass = JsonType.class)
public class Book {
#Id
#GeneratedValue
private Long id;
#NaturalId
#Column(length = 15)
private String isbn;
#Type(type = "json")
#Column(columnDefinition = "jsonb")
private Map<String, String> properties = new HashMap<>();
}
MySQL
#Entity(name = "Book")
#Table(name = "book")
#TypeDef(name = "json", typeClass = JsonType.class)
public class Book {
#Id
#GeneratedValue
private Long id;
#NaturalId
#Column(length = 15)
private String isbn;
#Type(type = "json")
#Column(columnDefinition = "json")
private Map<String, String> properties = new HashMap<>();
}
H2
#Entity(name = "Book")
#Table(name = "book")
#TypeDef(name = "json", typeClass = JsonType.class)
public class Book {
#Id
#GeneratedValue
private Long id;
#NaturalId
#Column(length = 15)
private String isbn;
#Type(type = "json")
#Column(columnDefinition = "json")
private Map<String, String> properties = new HashMap<>();
}
Works like a charm!
So, no more hacks and workarounds, the JsonType will work no matter what DB you are using.
If you want to see it in action, check out this test folder on GitHub.
A workaround is actually to create a custom column data type in H2 for the jsonb type, and put the query in the datasource url like this:
spring.datasource.url=jdbc:h2:mem:testdb;INIT=create domain if not exists jsonb as text;MODE=PostgreSQL"
Now for tests and integration tests in particular, it would be preferable to use the same DB than your application, via TestContainers
JSON support was added to H2 after the question was asked, with version 1.4.200 (2019-10-14).
However, you rarely need a JSON data type in a database. JSON essentially is just a potentially very long string, so you can use CLOB which is available on most databases.
You do need the JSON data type if you need an SQL function that operates on them, and then only if the database insists that its JSON functions operate on a JSON type instead of on a CLOB. Such functions tend to be database-dependent though.
This is how I solved it in Spring context:
Create /src/test/resources/init.sql
CREATE TYPE "JSONB" AS json;
Configure H2 datasource as follows /src/test/resources/application-test.yml
spring:
datasource:
driver-class-name: org.h2.Driver
url: jdbc:h2:mem:db;DB_CLOSE_DELAY=-1;INIT=RUNSCRIPT FROM 'classpath:init.sql'
username: sa
password: sa
Source article
My problem was with JSONB since H2 does not support it as was already mentioned.
One more problem is that when you insert a json, H2 transforms it into a json object string which makes jackson serialization fail. ex: "{\"key\": 3}" instead of {"key": 3} . One solution is to use FORMAT JSON when inserting the json, but then you need to have duplicate insert files if you are using flyway, for example.
Inspired by the #madz answer I came across with this solution:
Create a custom JsonbType (on production - e.g. main/java/com/app/types/JsonbType.java)
import com.vladmihalcea.hibernate.type.json.JsonBinaryType;
public class JsonbType extends JsonBinaryType {
private static final long serialVersionUID = 1L;
}
Create a custom JsonbType (on tests - e.g. test/java/com/app/types/JsonbType.java)
import com.vladmihalcea.hibernate.type.json.JsonStringType;
public class JsonbType extends JsonStringType {
private static final long serialVersionUID = 1L;
#Override
public String getName() {
return "jsonb";
}
}
Create an alias type from JSONB to JSON only on tests (h2):
-- only on H2 database
CREATE TYPE "JSONB" AS TEXT;
note: I'm using flyway which make it easy to do but you can follow #jchrbrt suggestion
Finally you declare the type on your entity model, as follows:
import com.app.types.JsonbType;
#TypeDef(name = "jsonb", typeClass = JsonbType.class)
#Entity(name = "Translation")
#Table(name = "Translation")
#Data
public class Translation {
#Type(type = "jsonb")
#Column(name="translations")
private MySerializableCustomType translations;
}
}
That's it. I hope it helps someone.
In my case we were dealing with PostgreSQL jsonb type in production and H2 for our tests.
I could not test #n00dle 's solution because apparently spring does not support executing a SQL script before Hibernate's ddl-auto=update for our tests so I used another way to solve this.
Here is a gist for it.
The overall idea is to create two package-info files.
One for production and the other for tests and register different types (JsonBinaryType.class for production and TextType.class for tests) to handle them differently for PostgreSQL and H2
I have solved the problem using TEXT type in H2.
One must create a separate database script to create schema in H2 for tests and replace the JSON type by TEXT.
It is still a problem since if you use Json function in queries, you will not be able to test those while with H2.
Example with Kotlin + Spring + Hibernate + Postgres + jsonb column
Create the entity:
#Entity
#TypeDef(name = "jsonb", typeClass = JsonBinaryType::class)
class MyEntity(
#Type(type = "jsonb")
#Column(columnDefinition = "jsonb")
val myConfig: String,
#Id
#GeneratedValue
val id: Long = 0,
)
JsonBinaryType.class comes from https://github.com/vladmihalcea/hibernate-types
<dependency>
<groupId>com.vladmihalcea</groupId>
<artifactId>hibernate-types-52</artifactId>
<version>2.9.13</version>
</dependency>
Configure your H2 database in spring profile. The key line is this: INIT=create domain if not exists jsonb as other
spring:
profiles: h2
datasource:
driver-class-name: org.h2.Driver
url: jdbc:h2:mem:testdb;INIT=create domain if not exists jsonb as other;MODE=PostgreSQL;DB_CLOSE_DELAY=-1
username: sa
password: sa
spring.jpa.hibernate.ddl-auto: create
Write the test:
// Postgres test
#SpringBootTest
class ExampleJsonbPostgres(#Autowired private val myEntityRepository: MyEntityRepository) {
#Test
fun `verify we can write and read jsonb`() {
val r = myEntityRepository.save(MyEntity("""{"hello": "world"}"""))
assertThat(myEntityRepository.findById(r.id).get().config).isEqualTo("""{"hello": "world"}""")
}
}
// H2 test
#ActiveProfiles("h2")
#SpringBootTest
class ExampleJsonbH2(#Autowired private val myEntityRepository: MyEntityRepository) {
#Test
fun `verify we can write and read jsonb`() {
val r = myEntityRepository.save(MyEntity("""{"hello": "world"}"""))
assertThat(myEntityRepository.findById(r.id).get().config).isEqualTo("""{"hello": "world"}""")
}
}
Alternatively you can try to define custom type per database in hibernate XML as described here: https://stackoverflow.com/a/59753980/10714479
I am in the same situation as #madz, where we use Postgres in production and H2 for unit tests. In my case i found a bit more simple solution, i think.
We use Liquibase for database migrations, so here i made a conditional migration only to be run on H2, where i change the column type to H2's "other" type.
With the other type, H2 just stores it in the database and doesn't think twice about how the data is formatted etc. This does require however that you are not doing anything with the JSON directly in the database, and only in your application.
My migration looks like this:
# Use other type in H2, as jsonb is not supported
- changeSet:
id: 42
author: Elias Jørgensen
dbms: h2
changes:
- modifyDataType:
tableName: myTableName
columnName: config
newDataType: other
Along with this, i added the following to my test datasource:
INIT=create domain if not exists jsonb as text;
The correct way of avoiding such things is using liquibase or flywaydb to evolve your schema and never ever allow Hibernate to create it.
H2 does not have the JSON data type.
In MySQL the JSON type is just an alias for the LONGTEXT data type so the actual data type for the column will be LONGTEXT.
Related
I am using the following class as an entity, and a controller class to write data on it:
#Entity
#Table(name = "TableA")
public class TableA {
#JsonProperty(access = JsonProperty.Access.READ_ONLY)
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(nullable = false, name="Id")
private BigInteger id;
#Column(nullable = false, name="Name")
private String name;
//Setters Getters
}
#RestController
public class TableAController {
#Autowired
TableARepository tableARepository;
#Transactional(rollbackFor = Exception.class)
#PostMapping(value="/CreateTableA")
public void createTableA(#RequestBody TableA newTableA){
TableA tableA = new TableA();
tableA = newTableA;
tableARepository.save(tableA);
}
}
The Id column value will be generated by the DB, so I used the #JsonProperty. But, when I test the REST API using the following as a request:
{
"name" : "Leo Messi"
}
I am getting the aforementioned error message. I have also tried the #JsonIgnore property with the same result. Is there a way to except the id property from the deserialization process? Or should I use another class dedicated the API Request? I am not comfortable with creating different models for every new API.
I am not sure if I should focus on resolving the error, or if I should design the classes using a Design Pattern that never produces it.
I have a model which i want to save to database.
#Data
public class Model {
#Id
private UUID id;
private String name;
private ModelSettings settings;
#Data
static class ModelSettings {
boolean fuelEngine;
}
}
create table model
(
id uuid not null,
name varchar(25) not null,
settings jsonb
)
i try to save modelSettings as jsonb object using simple repository method save(), but i got error
ERROR: relation "settings" does not exist
i wrote custom Converter and i see when modelSettings is converted to json, but after prepare statement Spring Data try to save settings field to related table. How to tell Spring Data save field as json only, not row in related table?
Sorry, i forgot #WritingConverter with JdbcValue.
Hi Please use Embedded Annotation:
Embedded entities are used to have value objects in your java data model, even if there is only one table in your database.
#Data
public class Model {
#Id
private UUID id;
private String name;
#Embedded(onEmpty = USE_NULL)
private ModelSettings settings;
#Data
static class ModelSettings {
boolean fuelEngine;
}
}
You can not have an object in your entity and expect JDBC to save it as json for you.
you need to define a String column and write a converter for it for saving in and reading from database.
also some databases like Oracle supports json values but you have not mentioned which database you are using.
in Oracle database you can define a table including a json column as below:
CREATE TABLE "USERS"
(
"ID" NUMBER(16,0) PRIMARY KEY,
"USER_NAME" VARCHAR2(85) UNIQUE NOT NULL,
"PASSWORD" VARCHAR2(48) NOT NULL,
"PROFILE" NCLOB NOT NULL CONSTRAINT profile_json CHECK ("PROFILE" IS JSON),
"SETTINGS" NCLOB NOT NULL CONSTRAINT settings_json CHECK ("SETTINGS" IS JSON),
);
And you need to create your entity class as below:
#Entity
#Table(name = "Users")
public class User {
#Id
#Column(name = "ID")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "USER_GENERATOR")
#SequenceGenerator(name = "USER_GENERATOR", sequenceName = "USERS_SEQ", allocationSize = 1)
private Long id;
#Column(name = "USER_NAME")
private String userName;
#Column(name = "PASSWORD")
private String password;
#Lob
#Nationalized
#Column(name = "PROFILE",columnDefinition="NCLOB NOT NULL")
private String profile;
#Lob
#Nationalized
#Column(name = "SETTINGS",columnDefinition="NCLOB NOT NULL")
private String settings;
}
as you can see here profile and setting are my json columns.
I have the following hibernate entity
#Data
#Entity
#TypeDef(
typeClass = JsonStringType.class,
defaultForType = MetaData.class
)
public class DbEntity(){
#Column(name = "id", unique = true, nullable = false)
private String id;
#Column(name = "user_id", nullable = false, updatable = false)
private String userId;
#Column(name = "meta_data", columnDefinition = "json")
private MetaData metaData;
}
The MetaData class is as follows:
#Data
#NoArgsConstructor
#AllArgsConstructor
public class MetaData {
private Long amount;
private Date date;
}
The metadata field is stored as json in db. This works with mysql. But I'm writing tests using h2 and am not able to read values in field metaData.
Exception I'm getting is:
Exception: The given string value: "{\"amount\":100,\"date\":1593690610000}" cannot be transformed to Json object
..
..
Caused by: java.lang.IllegalArgumentException: The given string value: "{\"amount\":100,\"date\":1593690610000}" cannot be transformed to Json object
..
..
Caused by: com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `foo.bar.MetaData` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('{\"amount\":100,\"date\":1593690610000}')
at [Source: (String)""{\"amount\":100,\"date\":1593690610000}""; line: 1, column: 1]
I'm using 1.4.200 version of h2.
Most of the solutions mentioned for the problem are around h2 supporting json or jsonb. But my version of h2 supports json.
Also, if I remove columnDefinition = "json" from #Column of metaData, tests work as expected. But, in that case, mysql implementation doesn't work.
This h2 official page suggests to add FORMAT JSON in insert sql statement. But I'm not sure how to add it as I'm using hibernate.
If you don't have a really good reason to use json columns, just change de columnDefinition attribute in #Column
#Column(name = "meta_data", columnDefinition = "text")
#Convert(converter = JsonConverter.class)
private MetaData metaData;
And define a custom converter:
#Converter
public static class JsonConverter implements AttributeConverter<MetaData, String> {
private static final ObjectMapper mapper = new ObjectMapper();
#Override
#SneakyThrows
public String convertToDatabaseColumn(MetaData metaData) {
return mapper.writeValueAsString(metaData);
}
#Override
#SneakyThrows
public MetaData convertToEntityAttribute(String s) {
return mapper.readValue(s, MetaData.class);
}
}
I just had the same problem you had.
fixed it by using JsonType, it will work no matter what DB you are using.
in class level:
#TypeDef(name = "json", typeClass = JsonType.class)
in column i have:
#Type(type = "json")
#Column(columnDefinition = "json")
I am using hibernate-types-55 2.16.2
There is a given database structure and graphql schema.
Fortunately they have a lot in common but unfortunately there are some difference.
Let's say there are entities in java to match the following database structure.
SQL:
TABLE ANIMAL
+ID NUMBER(19)
+NR_OF_LEGS NUMBER(19)
TABLE SHEEP
+ID NUMBER
+LAST_TIME_SHEARED DATETIME
+ANIMAL_ID NUMBER(19)
TABLE COW
+MILK_IN_L NUMBER(3)
+ANIMAL_ID NUMER(19)
Java:
#Entity
#Table(name = "ANIMAL")
public class Animal
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#Column(name="nrOfLegs", nullable=false)
private long nrOfLegs;
}
#Entity
#Table(name = "SHEEP")
public class SheepE
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#Column(name="lastTimeSheared", nullable=false)
private Datetime lastTimeSheared;
#ManyToOne(targetEntity = AnimalE.class, cascade = CascadeType.ALL, fetch = FetchType.LAZY, optional = true)
#JoinColumn(name = "animalId", nullable = false, insertable = false, updatable = false)
private Animal animal;
}
#Entity
#Table(name = "COW")
public class CowE
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#Column(name="milkInL", nullable=false)
private int milkInL;
#ManyToOne(targetEntity = AnimalE.class, cascade = CascadeType.ALL, fetch = FetchType.LAZY, optional = true)
#JoinColumn(name = "animalId", nullable = false, insertable = false, updatable = false)
private Animal animal;
}
The existing GraphQl schema is considered to be like this:
type Sheep{
id: int!
lastTimeSheard: String!
nrOfLegs: int!
}
type Cow {
id: int!
milkInL: int!
nrOfLegs: int
}
The project uses graphql-java in version 11.0 (guess we should update soon)
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-java</artifactId>
<version>11.0</version>
</dependency>
The graphql works fine and isimplemented like this:
#Component
public class GraphQLProvider {
#Autowired
GraphQLDataFetchers graphQLDataFetchers;
private GraphQL graphQL;
#PostConstruct
public void init() {this.graphQL = /*init;*/null;}
private RuntimeWiring buildWiring() {
RuntimeWiring.Builder b = RuntimeWiring.newRuntimeWiring()
.type(TypeRuntimeWiring.newTypeWiring("Query")
.dataFetcher("freightCarrier", graphQLDataFetchers.getCow()))
.type(TypeRuntimeWiring.newTypeWiring("Query")
.dataFetcher("personCarrier", graphQLDataFetchers.getSheep())));
return b.build();
}
}
#Component
public class GraphQLDataFetchers {
#AutoWired
private CowRepository cowRepo;
#AutoWired
private sheepRepository sheepRepo;
public DataFetcher getCow() {
DataFetcher dataFetcher = (DataFetchingEnvironment dfe) -> {
int id = dfe.getArgument("id");
return getGraphQlCowFromCowEntity(cowRepo.getById(id));//dirty!
};
return dataFetcher;
}
public DataFetcher getCow() {
DataFetcher dataFetcher = (DataFetchingEnvironment dfe) -> {
int id = dfe.getArgument("id");
return getGraphQlSheepFromSheepEntity(cowRepo.getById(id));//dirty!
};
return dataFetcher;
}
private Cow getGraphQlCowFromCowEntity(CowE ce){//dirty!
return new Cow(ce.getId(), ce.getMilkInL(),ce.getLegs());
}
private Sheep getGraphQlSheepFromSheepEntity(SheepE se){//dirty!
return new Sheep(se.getId(), se.getLastTime(),se.getLegs());
}
public class Sheep
private long id;
private Datetime lastTimeSheared;
private int nrOfLegs;
public Sheep(long id, DateTime lasttimeSheared, int nrOfLegs){
//u know what happens here
}
}
public class Cow
private long id;
private int milkInL;
private int nrOfLegs;
public Sheep(long id, int milkInL, int nrOfLegs){
//u know what happens here
}
}
So how to get rid of getGraphQlCowFromCowEntity and getGraphQlSheepFromSheepEntity. It double ups the code and also is in direct conflict to what graphql is suppose to be abstraction of the data. With this design here each time all fields are loaded through jpa and not only requested fields.
Imagine this is a way more complex environment with more fields.
The graphql schema can't be changed as it's not my responsibility, changing the entire back-end to match schema is also not what I want to archive.
Kind regards
You should use DTO. Retrieving and sending entity object is bad practice as you do not want your grahql api to change every time you refactor you database model, or in your case. Your Sheep and Cow objects are DTO, but you will need some way to convert your entity to DTO (getGraphQlCowFromCowEntity is fine, but you could use polymorphism - CowEntity.toDTO() - or have a service layer do the conversion, there are plenty of way to do this).
To answer your concerns about loading only the requested data, you want your DTO object to only be populated with the requested fields. One way to do this is, instead of populating all fields, have the DTO own a reference to the entity object and retrieve the data from the entity object only when requested.
public class Sheep {
private SheepE entity;
public Sheep(SheepE entity){
this.entity=entity;
}
public getId() {
return entity.getId();
}
public getLastTimeSheared() {
return entity.getLastTimeSheared();
}
...
}
Please see this answer I wrote to a similar question: Graphql Tools: Map entity type to graphql type
In my project, I need to support multiple databases from multiple vendors (notably, Oracle, MSSQL and MySQL).
I have a class which creates .sql files for each DB type based on my annotated hibernate model classes.
I have a class MyEntity.java like this:
#Entity
#Table(name = "my_table")
public class MyEntity implements java.io.Serializable {
private Integer id;
private Date timestamp;
private String data;
public MyEntity() {
}
#Id
#SequenceGenerator(name = "my_table_seq", sequenceName = "my_table_seq")
#GeneratedValue(strategy = GenerationType.AUTO, generator = "my_table_seq")
#Column(name = "id", unique = true, nullable = false)
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "timestamp", nullable = false)
public Date getTimestamp() {
return this.timestamp;
}
public void setTimestamp(Date timestamp) {
this.timestamp = timestamp;
}
#Column(name = "data", length = 65535)
public String getData() {
return this.data;
}
public void setData(String data) {
this.data = data;
}
}
This class was produced by hbm2java using reverse engineering from a MySQL database. The "data" column was a TEXT and the "timestamp" column was a TIMESTAMP.
When I use the SchemaExporter class to generate SQL for other DB types (like oracle for example) it produces invalid plsql. This class (using the Oracle10gDialect produces oracle sql like this:
create table my_table (
id integer not null,
data varchar(65535),
timestamp datetime not null
);
varchar(65535) is invalid because varchars can't be that long, and datetime is apparently not a real datatype.
When using the MySQL dialect, it correctly defines "data" as a MEDIUMTEXT type.
Why does it generate invalid oracle SQL? Is there some way I can hint to hibernate that it should use a text type? Or am I going to have to extend the oracle dialect to fix up all the data types?
Note: I'm using oracle 11.2.0.2.v7 and hibernate 4.2.8.FINAL
Another Note: Similar invalid results are produced for MSSQL (varchar(65535) is invalid).
Disclaimer: I'm new to Oracle