jOOQ: Find constraints in a specific table - java

While working in jOOQ-agnostic (without code generation) migrations I've encountered a situation in which I need to check if a constraint (unique, foreign key) already exists in the database in order to complete further operations.
What I've tried so far is to run the drop and try to catch the exception, but it fails the transaction and stops following migrations from happening
dsl.alterTable(table).dropConstraint(constraintName).execute();
...
>> ERROR: constraint "t_client_name_unique" of relation "t_client" does not exist
Setup:
Spring
jOOQ without code generation
FlywayDB as migrations library
Postgres

Future solutions (not available in jOOQ 3.12)
For jOOQ 3.13+, we're investing heavily in supporting more such migration scenarios. In the future, we'll support some vendor agnostic information_schema style views that produce this kind of meta information for all databases: #8301
Another feature that could help you here immediately would be native DROP CONSTRAINT IF EXISTS support: #9557. You could, of course, use plain SQL to run this particular statement on PostgreSQL, until #9557 is available
A solution right now
Alternatively, in your case, since you're only using PostgreSQL, you could do this directly by querying PostgreSQL's information_schema. You could generate information_schema tables and then run this query:
select *
from information_schema.table_constraints
where constraint_schema = :constraint_schema
and constraint_name = :constraint_name

Related

How can one add constraints on existing tables via JPA / Hibernate?

I am using a Postgresql database with JPA / Hibernate. When I'm adding a constraint to a column, i.e. "nullable=false", the database column is not altered to reflect this. Deleting the table and rerunning the application does the job.
Can this be achieved with JPA/Hibernate - mechanisms only WITHOUT deleting entries or the table? Like "Try to alter the table and refuse to do so on inconsistent data"? In my application.properties, I've set
hibernate.hbm2ddl.auto=update
Any other setting seems to be deleting data and/or tables.
A working solution would be to run an ALTER TABLE script and adding a constraint annotation accordingly, but I'm not really fond of this.
It is impossible to add constraints to the existing table. Think wide about it - what if the data in the table is not satisfied with the constraint? You will get the whole application crash. So Hibernate not even trying to apply the potential harmful operation.
In general, there is the wrong way to manage database schema with hibernate. Auto-generation schema is appropriate for learning or MVP purposes but not for production. Also, SQL migration is a bad idea for many reasons. You should use a special tool for schema management: liquibase (better for me) or flywaydb

What to use: sql migration or entity setups in Spring/Hibernate?

I am little confused, when see, why most programmers use annotation-based setup for database table constraints. For example
#Column(unique=true, nullable=false)
Why do we need that, if(as I heard) in real projects mostly used SQL migrations, so you are able to create this constraints in table creations, like CREATE table... name varchar UNIQUE NOT NULL.
Do I need to setup it in both ways, or is it enough to do in SQL?
And how often SQL migrations used(Flyway, Liquibase) in projects?
Additionally, Hibernate creates unreadable constraints in database, otherwise in SQL you create understandable names of constrains.
You can choose whether to let Hibernate to manage your schema or not. If yes , the database schema will be created or updated based on the changes of the annotation mapping.
I personally will not let Hibernate to manage my database schema as I want to be exactly know what is going on with the schema changes . The hibernate documentation also suggests it somehow:
Although the automatic schema generation is very useful for testing
and prototyping purposes, in a production environment, it’s much more
flexible to manage the schema using incremental migration scripts.
while Flyway, Liquibase is the kind of incremental migration scripts tool.
Do I need to setup it in both ways, or is it enough to do in SQL? And
how often SQL migrations used(Flyway, Liquibase) in projects?
If you do not use the automatic schema generation feature , you don't need to specify unique in #Column which only has meaning in case of automatic schema generation.
For nullable , it depends on hibernate.check_nullability setting.If it is turned on and you set #Column(nullable=false) , Hibernate will help to check this column cannot be null in the application level without asking the DB to check it. But even if do not set it , the database constraint (assuming you create a non-null constraint for it in DB) will eventually check it and not allow you to save the null value

Apache Flink Table 1.4: External SQL execution on Table possible?

is it possible to query an existing StreamTable externally, without uploading a .jar get the execution environment and retrieve the table environment? I had waited for Apache Flink Table 1.4 release, because of its dynamic (continuous) table features. I expected something else, I thought it would be possible to alter the table at runtime and modify its parameters. In order to do some live queries, instead of defining (continuous or append-only) database views on top of a data stream. I know I could export my table into some database and query this database dynamically using SQL, but this is kind of awkward behavior. The beauty of Flink is that everything is in real-time and everything is a stream, so is it possible to query a Flink table in real time from some external program?
No, this is not supported at the moment.
There has been some work on storing the result table of a streaming query as queryable state. This would allow for point (key look-up) queries on a fixed key attribute. This feature might become available with Flink 1.5.
There are not concrete plans to support SQL queries on a dynamic table produced by a streaming SQL (or Table API) query. You would have to emit the table to a RDBMS and query the data from there.

Enhance persistence.xml for database update

For development and deployment of my WAR application I use the drop-and-create functionality. Basically erasing everything from the database and then automatically recreating all the necessary tables and fields according to my #Entity-classes.
Obviously, for production the drop-and-create functionality is out of question. How would I have to create the database tables and fields?
The nice thing about #Entity-classes is that due to OQL and the use of EntityManager all the database queries are generated, hence the WAR application gets database independent. If I now had to create the queries by hand in SQL and then let the application execute them, then I would have to decide in which sql dialect they are (i.e. MySQL, Oracly, SQL Server, ...). Is there a way to create the tables database independently? Is there a way to run structural database updates as well database independently (i.e. for database version 1 to database version 2)? Like altering field or table names, adding tables, droping tables, etc.?
Thank you #Qwerky for mentioning Liquibase. This absolutely is a solution and perfect for my case as I won't have to worry about versioning anymore. Liquibase is very easy to understand and studied in minutes.
For anyone looking for database versioning / scheme appliance:
Liquibase

HSQLDB Constraint Violation & SQL Query Log for an HSQLDB in-memory setup

We have a setup where we are using an embedded HSQLDB for backing Hibernate/JPA unit tests in java, and we are using the in-memory database mode since we simply want the database thrown away after the test run. My problem is that one of the tests is failing due to a constraint violation and HSQLDB lists the column as SYS_CT_286, and the query that appears in the log is the prepared statement where I cant see what the actual parameter values are (they are replaced by '?'). My questions are:
1- Is there a way in which I can see the actual SQL being executed? (like the mysql query log for example?).
2- What exactly is SYS_CT_286? it is not one of my columns, is it a generated column? is there something obvious that may be wrong with it?
Thanks.
Is there a way in which I can see the actual SQL being executed?
I'm not sure HSQLDB allows to log the SQL statements (like select) being executed but you can use a proxy JDBC driver like P6Spy for this (already mentioned in this answer).
What exactly is SYS_CT_286?
This is a constraint (and I would bet on a unique constraint).
HSQLDB keeps a redo log, which might be useful for debugging what sql has been run, but I'm not sure if it does this for an in-memory db. If you change your db temporarily to a file-based db named test, the redo log should be named test.log, but it disappears on a clean shutdown.
SYS_CT_286 is most likely a constraint with a system-generated name. Again, if you make a file-based DB, you might be able to look at it and find out what it's a constraint for. And if it's a constraint you're defining, you might even be able to change your mapping so it gets a sensible name. I know you can do this with foreign key constraints anyway.

Categories

Resources