How to annotate a PostgreSQL GIN index in Hibernate - java

How do I properly annotate a PostgreSQL GIN index with Hibernate?
#Index(...)
String text;
Does hibernate create a GIN index by default, or do I have to set a special property somewhere?

Looks like you can't create custom indexes directly with Hibernate's annotations. See related: How to use Hibernate Annotations to add an index on a Lob / Clob / tinyblob, where an answer mentions how to do it with auxillary objects.
In your situation I would query the system catalogs (information_schema or pg_catalog) for the index at startup and, if it wasn't found, execute CREATE INDEX statement with native SQL.
See this answer to a very similar question about creating triggers in Hibernate.

Related

JPA #Formula without Schema Name or Configure with entity class

I have two tables, A_TABLE and B_TABLE. in A_TABLE entity class need on formula which has B_TABLE column combination like below code,
Working Code:
A_TABLEEntity {
#Column("BM_NAME_I")
private String bmdName;
#Formula("(select b.LAST_NAME || ', '||b.FIRST_NAME||' ('||b.BM_NAME||')'
from BR_SCHEMA.B_TABLE b where UPPER(b.BM_NAME)=UPPER(BM_NAME_I))")
private string nameCombinationB;
}
Need solution in Formula :
1) Is it possible to provide any way to give B_TABLEEntity class instead of B_TABLE directly and columns from B_table entity class?
And I have tried with entity class its throwing error, - table or view does not exist
2) Is it possible to avoid to give SCHEMA name in B_TABLE before in formula?
And without schema error is throwing - table or view does not exist
Please help me above #Formula JPA code
You should definitely look here:
https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#mapping-column-formula
According to the described comment, #Formula takes only native sql and the article warns you about coupling to the specific database in some cases.
You should be aware that the #Formula annotation takes a native SQL
clause which may affect database portability.
As the #Formula requires native SQL, you should always include schema. I think that some DB's have default schema that does not need to be defined explicitly.
For some advanced operations, I would probably provide some annotation like #PostLoad and load desired properties using good old entitymanager or direct jdbc.
Maybe these links may help:
https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#basic
https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#fetching

how to search similar entities in database using Example class from hibernate

i know that there are an Hibernate class called Example that we can use to get similar entities in order to do a search, but is it possible that this class permit to get entities searching in a generic way.
I explain, I build an example entity having a property called name with value = "myname", is Hibernate capable to return an entity which has property having value = "mname" ?
Yes that's possible but to enable text-level similarity you need a Lucene index to speed-up the query, as it would otherwise be extremely inefficient to run on a relational database.
This is provided by Hibernate Search, the extension of Hibernate to integrate with Lucene and manage the indexes transparently.

Hibernate Unique Indices with condition [duplicate]

I need to use these unique constraints in PostgreSQL
CREATE UNIQUE INDEX favorites_3col_uni_idx
ON favorites (user_id, menu_id, recipe_id)
WHERE menu_id IS NOT NULL;
CREATE UNIQUE INDEX favorites_2col_uni_idx
ON favorites (user_id, recipe_id)
WHERE menu_id IS NULL;
The first one I annotate in JPA:
#Table(uniqueConstraints= {
#UniqueConstraint(name="favorites_3col_uni_idx", columnNames = {"user_id", "menu_id", "recipe_id"})
})
But, ¿it is possible to annotate in JPA the second unique index?
Thx.
You appear to want to create partial indexes (CREATE INDEX ... ON ... WHERE) using JPA constraint definitions.
These are fairly PostgreSQL specific, and aren't specified by JPA. You will need to use native syntax to create them. I don't believe JPA offers any features for index definition.
You cannot use a unique constraint for this purpose because unique partial indexes are not unique constraints. Partial unique indexes cannot be created with CONSTRAINT constraint_name UNIQUE(columns) in PostgreSQL. It's only an implementation detail that PostgreSQL creates a unique index for a unique constraint at all.
See:
Specifying an Index (Non-Unique Key) Using JPA
JPA: defining an index column
Some JPA providers offer extension annotations specific to that JPA provider that add features for running native DDL scripts, defining indexes with annoations, etc. Since you haven't mentioned which JPA provider you are using I can't tell you more. Here's the documentation for EclipseLink index DDL; this will not work if you are using Hibernate, OpenJPA, or something other than EclipseLink.
A JPA standard workaround is to check for the presence of those indexes during startup by querying pg_catalog.pg_index. If you don't find them, use an EntityManager native query to send the appropriate native SQL CREATE UNIQUE INDEX commands. A #Startup #Singleton bean is useful for this sort of task if you're using EJB3.1. See the PostgreSQL documentation for the structure of pg_catalog.pg_index. To just check if an index of a given name exists, run:
SELECT EXISTS(
SELECT 1
FROM pg_index
WHERE indexrelid = 'public.indexname'::regclass
);
Note that the above query does nothing to verify it's the index you expect, but you can do that with some additional checks. Just examine the contents of pg_index after creating the index so you know what to test for. I don't recommend trying to check for any particular value of indpred; just make sure it isn't null.

Entity object as HQL parameter

I have the following question, which is not covered in Hibernate documentation. Or I just couldn't find the answer there. Googling doesn't give me details also.
If we use an Entity object as a parameter and bind it to an HQL using Query.setParameter, what happens next?
Does hibernate uses only an entity ID of a mapped parameter object to build the SQL 'where' query?
Or Hibernate uses some extra logic (maybe in some cases) which is not limited to ID only? For example, hibernate add additional fields in SQL which are not primary keys.
Is it dangerous to use detached Entity object as a parameter?
Thank you in advance!
In terms of the SQL it will simply compare using the ids. The entity you bind does not have to be managed within that session as the comment on your question suggests.
Essentially what happens is that Hibernate will attempt to resolve the entity type of the entity instance it is given. It will then use that type to bind the JDBC parameter value, which will write just the identifier. So the assumption here is that the entity instance can resolved to its "entity type". That is usually easy in most situations. Where it gets difficult is in the case of Hibernate-specific "entity name" features.

What does the length attribute do when set on the #Column JPA annontation?

What exactly does setting the length on a column do in JPA?
#Column(name = "middle_name", nullable = false, length = 32)
public String getMiddleName() {
return this.middleName;
}
I understand that you can use the annotations to generate the database schema (DDL) based on the entity objects, but does length do any sort of check or truncation when persistence happens, or it solely used for schema creation?
I also realize that JPA can sit on top of various implementations, the implementation I am concerned with in this case is Hibernate.
Does length do any sort of check or truncation when persistence happens, or it solely used for schema creation?
The length attribute of the Column annotation is used to specify:
The column length. (Applies only if a string-valued column is used.)
And is only used in the generated DDL. In your example, the resulting column would be generated as a VARCHAR(32) and trying to insert a longer string would result in an SQL error.
For validation, you could add a #Size(max=32) constraint from the Bean Validation API (JSR 303). I provided a sample with a runnable test here.
Providing both Size and length may seem redundant but according to the Appendix D. of the Bean Validation spec, generating Bean Validation-aware DDL is not mandatory for Persistence Providers. So use length for the DDL, #Size for validation.
In case you're interested, just put a Bean Validation implementation on the classpath with JPA 2.0. With JPA 1.0, refer to this previous answer.
Hibernate 4.3.11 (and other Versions) should pay attention to Validation Annotations. - so you maybe have to upgrade
This are cites from Hibernate 4.3.11 manual
Chapter 22.Additional modules
Hibernate Core also offers integration with some external
modules/projects. This includes Hibernate Validator the reference
implementation of Bean Validation (JSR 303) and Hibernate Search.
Chapter 22.1 Bean Validation
...
The integration between Hibernate and Bean Validation works at two
levels. First, it is able to check in-memory instances of a class for
constraint violations. Second, it can apply the constraints to the
Hibernate metamodel and incorporate them into the generated database
schema.
...
Chapter 22.1.4 Database schema
Hibernate uses Bean Validation constraints to generate an accurate database schema:
#NotNull leads to a not null column (unless it conflicts with components or table inheritance)
#Size.max leads to a varchar(max) definition for Strings
#Min, #Max lead to column checks (like value <= max)
#Digits leads to the definition of precision and scale (ever wondered which is which? It's easy now with #Digits :) )
Note: #Lengh works too, like #Size
When you use Hibernate Validator 5.1 - then you also need an el-Implementation. For example
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>el-impl</artifactId>
<version>2.2</version>
</dependency>
If you do not have this, then Hibernate ORM will not been able to start Hibernate Validation, ad therefore it would not take (all) JSR-303 for example #Length, #Size in account!
#Column(length=32) is only for DDL purpose and not for restricting means it allows more than 32 characters unless at table level it is not restricted.To restrict size we should go for
#Size(max=32)

Categories