MySQL LONGTEXT with h2 embedded database - java

I am trying to make my application run on MySQL (for production) and H2 (for dev/testing). My (Flyway) script to create the tables is almost identical now, except for a column that needs to be declared 'LONGTEXT' for MySQL. If I also use this for H2 (which is running in MySQL compatibility mode), I get:
Wrong column type in public.public.customer_license for column license.
Found: clob, expected: varchar(65535)
The Java code of my entity:
#Column(name = "license", length = 65535)
private String m_license;
If I change the column declaration to VARCHAR(65535), then it works for H2, but not for MySQL:
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Column length too big for column 'license'
(max = 21845); use BLOB or TEXT instead
How can I make it work for both?

I had the same problem. I solved it by using the #Lob Annotation. This validates ok with LONGTEXT in a mysql table. When using an H2 in-memory, a CLOB field is created.
import javax.persistence.Lob;
...
#Lob
private String lotsOfText;

That is one of the reasons there is orm.xml, so you can have one mapping for one datastore, and one for a different datastore, and hence no need to recompile the code between runs

Related

Hibernate: Value too long for column

For a project I am working on, we use Spring Boot JPA with H2 database to store certain objects and information. However, after testing the application a bit, I got the following error:
2022-04-03 17:41:19 jdbc[3]: exception
org.h2.jdbc.JdbcSQLDataException: Value too long for column "LIST_OF_PLAYERS VARBINARY(255)": "X'aced0005737200136a6176612e7574696c2e41727261794c6973747881d21d99c7619d03000149000473697a6578700000000a77040000000a7372000e6a61... (262)"; SQL statement:
update lobby set host_id=?, is_public=?, is_started=?, list_of_players=?, token=? where id=? [22001-200]
So I figured that I had to change the maximum allowed number of characters and did the following:
#Column(name = "listOfPlayers", length = 10000)
public ArrayList<Long> playerIds;
It appears that the length attribute only works for VARCHAR and not for VARBINARY. Is it possible to set the maximum for VARBINARY too? If so how?

Avoid ORA-00904 - invalid identifier error while doing sql query in java as the column may or may not be preset in the database

I am trying to write java code to migrate data from oracle database to other database.
My use case is that different client have different version of code and so the database columns may vary. Clients with later version have additional column.
For eg : Client with new version as COL99 in the table SAMPLE_TABLE.
While writing the migration code, if I try to select the COL99 from SAMPLE_TABLE, it will work fine for the new client. But for clients on old version, the code fails with
ORA-00904 Invalid Identifier error.
Is there a way to handle in sql query or java code such that, if the column doesn't exist in the database table, simply ignore and do not return the value instead of throwing the exception.
You should first check, whether COL99 exists for your current database connection.
For Oracle you can use a query like this:
SELECT
COL.COLUMN_ID,
COL.OWNER AS SCHEMA_NAME,
COL.TABLE_NAME,
COL.COLUMN_NAME
FROM
SYS.ALL_TAB_COLUMNS COL
INNER JOIN
SYS.ALL_TABLES T
ON COL.OWNER = T.OWNER
AND
COL.TABLE_NAME = T.TABLE_NAME
WHERE
COL.OWNER = 'SCHEMA'
AND
COL.TABLE_NAME = 'SAMPLE_TABLE'
AND
COL.COLUMN_NAME = 'COL99'
Then you create your query with or without COL99.

Hibernate - strategy="increment" in table ,Multiple tomcat gives duplicate primary key

Single Database MySql
Multiple Tomcat on different location which shared same code
Hibernate 5.2.2
On Table level
#GenericGenerator(name="employee" , strategy="increment")
#GeneratedValue(generator="employee")
When another server enters value gives duplicate primary key error
In future we are also supporting Sql Server, Oracle, HSQL
Use the following
#GeneratedValue(strategy = GenerationType.IDENTITY)
Increment
generates identifiers of type long, short or int that are
unique only when no other process is inserting data into the same
table. Do not use in a cluster.
Identity
supports identity columns in DB2, MySQL, MS SQL Server,
Sybase and HypersonicSQL. The returned identifier is of type long,
short or int.
Sequence uses a sequence in DB2, PostgreSQL, Oracle, SAP DB, McKoi or
a generator in Interbase. The returned identifier is of type long,
short or int
Ref : http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/mapping.html#mapping-declaration-id

select length of oracle long raw with sql statement

storing filedata via a hibernate (using postgresql or oracle 10g/11g) property mapped as
<property name="fileData" type="binary">
<column name="fileData" length="104857600" />
</property>
from a java application i need to access the length of the field from the db (i do not want to load whole the object, for performance reasons). i did not find any hibernate (hql) solution to query that information, so i decided to search for features of the different databases that were used. for postgresql i found:
select BIT_LENGTH(filedata) from table
which works perfectly (and astonishing fast). now i need something similar for the use with oracle. i already tried
select utl_raw.length(filedata) from table
and
select DBMS_LOB.GETLENGTH(filedata) from table
which both results in the error msg:
"Error: ORA-00997: illegal use of LONG datatype"
is there any possibilty to query the length of that hibernate property on an oracle db without selecting the object itself?
(hibernate creates a "long raw" field on oracle, and a "bytea" field on postgresql)
thx in advance
(addition: statement will be used in a migration-context, newly created filedata entities will get a filesize property programatically)
Well, looks like i found an answer here:
https://community.oracle.com/thread/2137593
create table temp_deleteme as select to_lob(<long raw field>) obj from <tablename>;
select dbms_lob.getlength(obj) from temp_deleteme;
after creating the tempTable i can select the filedatalength from it, write it to my entities, and delete the table again. still not really good performance, but that let the db do the work and i will not have to transfer entities to my server for only calculating the needed information.

Hibernate generates invalid SQL query with MySQL

I have the following JPA entity classes (example case). A House belongs on a single Street. A Street has many Houses.
#Entity
public class House {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
public Integer id;
public String name
#ManyToOne
public Street street;
}
#Entity
public class Street {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
public Integer id;
#OneToMany(mappedBy="street")
public Set<House> houses;
}
I have the generation type set to identity, which is supposed to auto assign a new ID.
When creating a new House with a new Street, I have to first create and persist Street, followed by House. This is because I do not have CascadeType set to PERSIST, so it has to be done manually [1]. However, while inserting a newly created Street:
Street street = new Street();
entityManager.persist(street);
Hibernate/JPA generates the following SQL query:
insert into Street default values
which MySQL doesn't like.
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: 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 'default values' at line 1
Any ideas why? I'm using Java 6, MySQL 5.0.67 with Hibernate's implementation of JPA (version 3.2.1.ga).
[1] EJB 3 in Action pages 318-319
If you don't have an error in your SQL statement, then you might want to check your table column name as it can contain a predefined name that Mysql uses; for example 'column' which can't be used as a table column name
Standard SQL specifies this optional syntax for INSERT:
INSERT INTO <Table Name> DEFAULT VALUES
This is legal SQL syntax, supported, for example, by Microsoft SQL Server, PostgreSQL, and SQLite, but not by Oracle, IBM DB2, or MySQL.
MySQL supports other syntax that achieve the same result:
INSERT INTO <Table Name> () VALUES ()
INSERT INTO <Table Name> (col1, col2, col3) VALUES (DEFAULT, DEFAULT, DEFAULT)
In Hibernate, you should configure the SQL dialect properly, and it's up to Hibernate to generate valid SQL for the target RDBMS brand.
import org.hibernate.cfg.Configuration;
Configuration cfg = new Configuration();
cfg.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQLInnoDBDialect");
You can also specify properties by placing a file named hibernate.properties in a root directory of the classpath.
Another situation when you might have this exception is when you have reserved words as columns for the table. For example 'to' and 'from' are not suitable clumn names for MySQL. It is obviously bug in Hibernate, that it doesn't check such columns and moreover continues to work with no error even if table is not created.
Make sure spring.jpa.database-platform=org.hibernate.dialect.MySQL5Dialecthas correct version of MySQL

Categories

Resources