Can we generate primary keys automatically without JDBC queries or calls? - java

I am trying to generate alpha-numberic (e.g. TESLA1001) primary keys automatically in Hibernate. I am currently using Oracle database, so I have a JDBC call to my_sequence.NEXTVAL (1002) to increment number and append to the prefix (TESLA).
We are considering MySQL as an option, but they do not support sequences. So I am forced to re-write the Custom ID generation technique using JDBC call to a stored procedure.
Is there any way I can have a generic implementation to generate custom primary keys without the use of JDBC and database dependent queries? So, in future, if I need to test my application with MSSQL, I need to change my hiberate configuration only and things work fine!

Because you need a way to coordinate the sequence number, you'll always have to use a centralized sequence generator. An alpha-numerical primary key will perform worse on indexing than a UUID generator.
If I were you, I'd switch to UUID identifers which are both unique and portable across all major RDBMS.

Related

How to programmatically create a MySQL index with limited length using JPA?

Similar to here I'm annotating my class with
#Table(indexes = {#Index(columnList = "name")})
which attempts to create a non-unique index with the maximum length of the varchar column. Unfortunately that's not possible because it's a varchar(255) column of type utf8mb4. phpMyAdmin added KEY '...' (name(191)) by clicking on the respective buttons in the UI, so at least my software runs efficient queries now.
Now I was wondering if it's possible to have my Java class auto-generate the index with limited length upon creating the database schema? The code builds on spring-boot-starter-data-jpa:1.4.2.RELEASE.
There are other answers than trying to get the 3rd party software to do something it may or may not allow for.
Live with 191 limitation on the column size. Or, do you really have a max between 191 and 255.
Change to utf8 (from utf8mb4). And lose the ability to store Emoji and some Chinese characters.
There is a clumsy process in 5.6 to raise the 767 limit you are bumping into.
Upgrade to 5.7, which makes virtually eliminates the problem.
You should only use the JPA generated table scripts as a starting point, and you should never use JPA to create you tables in production.
If you have "create table" privileges, so you don't need a DBA to create and modify the database, then I recommend that you use Flyway to manage database creation and migration. If you need to be database agnostic, and like long XML files, you can also use LiquideBase.
With flyway, you would add a new script every time you add one or more entities. I typically let JPA create the script, and then copy what I need, and maybe do some modifications - for instance varchar(255) means 255 bytes on some databases, so you may want modify that if you are storing something other than Latin-1.
Flyway is very simple to use, and it is fully integrated into Spring boot, so you just add the unique index the way you want it in the first (or later) flyway script src/main/resources/db/migration/V1__initial_script.sql.

Web-App using Hibernate that queries a SQL Server 2005 encrypted column

we are devolping a web-application using Spring 3.1.2 and Hibernate 4.1.7 with a database SQL Server 2005.
On a table we've got a column encrypted and we need to perform some queries like, for example, this one:
OPEN SYMMETRIC KEY PasswordFieldSymmetricKey
DECRYPTION BY PASSWORD = 'myPassword'
SELECT id,
plain,
cipher,
CONVERT(varchar(50),
DecryptByKey(cipher)) AS 'Decrypted'
FROM TS_OWN.cryptest;
GO
CLOSE SYMMETRIC KEY PasswordFieldSymmetricKey
As a solution, someone proposed to create a view that manages the decryption but we need that no one must see the decrypted data, and of course DBA for example could query that view.
At the same time we don't want to perform the decryption on java side, due to some heavy aggregation logic that is expected to be performed by database engine due to performance reasons.
A possible solution is to create a view that performs decryption, aggregations and then encrypts the result one more time, performing decryption of the aggregated values on Java side.
Does someone know alternatives?
Thank you all,
Luca
From a server-side perspective, the most transperent solution is to use Jasypt. This library comes with several Hibernate UserTypes for encrypting text/password fields.
As mentioned in the reference documentation, there are limitations:
But encryption sets a limitation on your Hibernate usage: security
standards establish that two different encryption operations on the
same data should not return the same value (due to the use of a random
salt). Because of this, none of the fields that are set to be
encrypted when persisted can be a part of a WHERE clause in your
search queries for the entity they belong to.
While your HQL/SQL queries will hide the decrypting complexity, you won't get the same performance as with a specific database decryption function.
Using database decryption functions performs better, but then all your queries will be embedded in views and that's going to change dramatically the way you use Hibernate.
You could map entities to views instead, but you'll have to pay attention to DML statements (some DBs offer updatable views, others give you materialized views or you might use INSTEAD OF triggers).
One possible solution for OPEN/CLOSE SYMETRIC is to use your own #Decrypt annotation and add an aspect to insert those right after the transaction starts and right before it ends. This will work because the sql session/connection is bound to the current transaction/thread.

why generationtype.sequence in mysql doesn't work?

i am developing an application using hibernate 4.1, zk 6.5 and mySql 9.3, I tried using generationtype.sequence in my code but unfortunately it returned an error, after doing some research on the internet I found out that MySQL doesn't support sequence so instead I used #GeneratedValue(strategy = GenerationType.IDENTITY) and it fixed my problem! but I was wondering why sequence doesn't work with mySql ?
I'm leaving an answer, so this question can be removed from the "unanswered" SOF category.
KevinB, you can leave an answer, and I'll upvote it.
I just want this question to be closed out...more than (me) "getting points".
But here is a concrete answer and reference.
Short Version:
MySql does not have "true" sequences. It uses a Sequence-via-a-Table workaround...that is a bottleneck if you're trying to do alot of JPA batching.
https://thorben-janssen.com/5-things-you-need-to-know-when-using-hibernate-with-mysql/
Mappings: Primary Keys
The efficient handling and creation of primary keys are a basic but one of the most important parts of an application.
The #GeneratedValue annotation of the JPA specification allows you to define the strategy you want to use to create unique primary key values. You can choose between SEQUENCE, IDENTITY, TABLE, and AUTO.
In general, I recommend using the SEQUENCE strategy because it allows Hibernate to use JDBC batching and other optimization strategies that require the delayed execution of SQL INSERT statements.
But you can’t use this strategy with a MySQL database. It requires a database sequence, and MySQL doesn’t support this feature.

generating IDs in Oracle with hibernate backed ORM

There is an old database which needs to be ported to a new one but the porting process will take significant time during which the old db will remain operational.
In the old DB the IDs are sequential numbers in the new one we need globally unique identifiers which in case of hibernate we are (or were) going to generate using the hibernate's built in UUID generation. I have no idea about how it(hibernate's UUID) works and don't know if this is the same as the java's native UUID generation. Actually hibernate provides 2 uuid generation strategies (uuid and uuid2).
The problem is that if we use hibernates generation it's possible that there will be a collision between the hibernate generated IDs and the IDs coming from the old DB while it's still working. We are going to write a number of oracle procedures to help us "smartly" transfer the IDs from the old database to the new one but what ID generation technique we should use in those procedures so we don't have ID collisions with the IDs generated by hibernate?
We can use oracle's built in GUID generator or write a procedure in java and use java's native UUID generator. But nowhere it's written that those 2 won't produce collisions with hibernate generated IDs.

How do I get name of the target table and column of foreign key column with plain JDBC

I'm trying to make a piece of code using plain JDBC that fetches me the name of both target table and column of a foreign key of a specific column in specific table but going through the core interfaces I can't seem to find a direct way to do this.
Is there a way to get such information about foreign keys through JDBC directly or do I have to resort to metadata queries to specific database, in this case HSQLDB.
If I have to use the database specific metadata queries, which HSQLDB internal metadata tables hold that information?
Your best bet is Connection#getMetaData() which returns DatabaseMetaData with all methods to obtain information about all tables, columns, primary keys, foreign keys, etcetera. You're however dependent on the JDBC implementation (read: the JDBC driver make/version) whether this is fully supported.
JDBC does have support for this. Check out DatabaseMetaData.getCrossReference class. Other methods on DatabaseMetdata support for querying schema, catalog, tables, columns, etc. Bear in mind some databases require extra parameters on your URL to turn on Metadata (i.e. Oracle) to optimize the calls. Don't know if HQLSB requires this.

Categories

Resources