According to the following tutorial, I created two configruation files for two database sources: Baeldung-JPA-Multiple-Databases
It works fine, but it seems that the implicit naming strategy is ignored. That means that an Entity CustomerContact is not mapped to a table customer_contact.
I tried to add the following two properties, but nothing changes:
public LocalContainerEntityManagerFactoryBean primaryEntityManager() {
...
properties.put("hibernate.naming.implicit-strategy", "org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy");
properties.put("hibernate.naming.physical-strategy", "org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy");
em.setJpaPropertyMap(properties);
...
}
One solution would be to use the name attribute of the persistence annotations, like
#Entity(name = "customer_contact"), but I would like to avoid that and use the implicit mapping instead.
The answer can be found here: Can't set JPA naming strategy after configuring multiple data sources (Spring 1.4.1 / Hibernate 5.x)
The needed properties are:
props.put("hibernate.physical_naming_strategy", SpringPhysicalNamingStrategy.class.getName());
props.put("hibernate.implicit_naming_strategy", SpringImplicitNamingStrategy.class.getName());
Related
Hibernate is not including the property annotated by Javax.Persistence.Version in dirtyProperties list which is provided by the PostUpdateEvent. Is this the default behavior of Hibernate? If yes can I configure which properties it should not blacklist?
I want to know why we have to use 2 annotations to use the second-level of cache in Hibernate.
We declare :
#Cacheable
#Cache
Why don't we declare directly #Cache with the options?
I want to know why we have to use 2 annotations to use the
second-level of cache in Hibernate.
You don't need to use both, but you can. To enable the second level cache on an entity, you have 2 options:
(1) Use #Cacheable (more below)
(2) Use #Cache(more below)
#Cacheable is the JPA cache interface(used on an entity) that together with shared cache mode property decides whether an entity will be cached or not.
By default, entities are not part of the second level cache and we
recommend you to stick to this setting. However, you can override this
by setting the shared-cache-mode element in your persistence.xml file
or by using the jakarta.persistence.sharedCache.mode property in your
configuration file. The following values are possible:
ENABLE_SELECTIVE (Default and recommended value) Entities are not
cached unless explicitly marked as cacheable (with the #Cacheable
annotation).
DISABLE_SELECTIVE Entities are cached unless explicitly marked as
non-cacheable.
ALL Entities are always cached even if marked as non-cacheable.
NONE No entity is cached even if marked as cacheable. This option can
make sense to disable second-level cache altogether.
As per this:
Some developers consider that it is a good convention to add the
standard #javax.persistence.Cacheable annotation as well (although not
required by Hibernate).
#Cache is the Hibernate cache interface, recommended to specify the CacheConcurrencyStrategy on a per entity basis instead of the global setting hibernate.cache.default_cache_concurrency_strategy.
Why don't we declare directly #Cache with the options ?
That's exactly what is recommended, so that besides telling Hibernate that you want to enable second level caching for this entity, you also keep the concurrency strategy on a per entity basis, instead of global, as explained above. Remember to enable the second level cache(as by default, it' not), by using hibernate.cache.use_second_level_cache. A basic configuration of second level cache(I am using Spring Boot):
//In build.gradle:
implementation 'org.hibernate:hibernate-ehcache' //IMPORTANT: If you are specifying a version, make sure that it is the same version as your Hibernate version that you are using.
//Hibernate properties(can also be externalized to application.properties):
properties.put("hibernate.cache.use_second_level_cache", "true"); //hibernate.cache.use_second_level will also work
properties.put("hibernate.cache.region.factory_class", "org.hibernate.cache.ehcache.EhCacheRegionFactory"); //act as a bridge between Hibernate and the caching provider
emf.setJpaProperties(hibernateProperties());
//In the entity class:
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
#Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
public class MyClass implements Serializable {
Note 1: The above is using Ehcache 2.x
Note 2: To use Ehcache 3.x, use the following properties:
properties.put("hibernate.javax.cache.provider", "org.ehcache.jsr107.EhcacheCachingProvider");
properties.put("hibernate.cache.region.factory_class", "jcache");
Note 3: Collections are not cached by default, you need to explicitly mark them with #Cache.
BONUS:
If you want to check the statistics:
//Add this property:
properties.put("hibernate.generate_statistics", "true");
//And somewhere in your code:
sessionFactory.getStatistics();
I am using Hibernate 4.3.8 without Spring. I am using Hibernate's session API. I have one entity class Category which I have annotated properly with #Entity, #Table, #Id, #Column and so on. I don't use .hbm.xml descriptor files, I just want to use the annotations in my domain/entity java source/class files.
1) OK, I create my hibernate SessionFactory in this way:
Configuration configuration = new Configuration().configure();
// configuration.addClass(Category.class);
StandardServiceRegistryBuilder builder =
new StandardServiceRegistryBuilder().applySettings(configuration.getProperties());
configuration.addPackage("com.test.db.domain");
factory = configuration.buildSessionFactory(builder.build());
2) Then when I try this:
session.createCriteria(Category.class).list();
I just get an empty list back (I was expecting to get all categories that are in the DB table). The Category class is in the com.test.db.domain package.
What could be the reason for this? I am stuck for almost a day on this.
3) Note that if I use session.createSQLQuery I can connect to my DB and get all categories.
4) Also note that I don't want to use Hibernate's EntityManager API, JPA, and the XML descriptor(s) related to JPA.
The problem turned out to be the following: calling configuration.addPackage does not do what I initially expected it to do. See also:
hibernate 4.3.x - load all entity annotated classes
Instead of calling addPackage what one should do is to call configuration.addAnnotatedClass for each class from his own entity/domain classes.
I have an issue testing a Hibernate application which queries multiple catalogs/schemas.
The production database is Sybase and in addition to entities mapped to the default catalog/schema there are two entities mapped as below. There are therefore three catalogs in total.
#Table(catalog = "corp_ref_db", schema = "dbo", name = "WORKFORCE_V2")
public class EmployeeRecord implements Serializable {
}
#Table(catalog = "reference", schema = "dbo", name="cntry")
public class Country implements Serializable {
}
This all works in the application without any issues. However when unit testing my usual strategy is to use HSQL with hibernate's ddl flag set to auto and have dbunit populate the tables.
This all works fine when the tables are all in the same schema.
However, since adding these additional tables, testing is broken as the DDL will not run as HSQL only supports one catalog.
create table corp_ref_db.dbo.WORKFORCE_V2
user lacks privilege or object not found: CORP_REF_DB
If there were only two catalogs then I think it would maybe be possible to get round this by changing the default catalog and schema in the HSQL database to that one explicitly defined:
Is there any other in-memory database for which this might work or is there any strategy for getting the tests to run in HSQL.
I had thought of providing an orm.xml file which specified the default catalog and schema (overiding any annotations and having all the defined tables created in the default catalog/schema) however these overrides do not seem to be observed when the DDL is executed i.e. I get the same error as above.
Essentially, then I would like to run my existing tests and either somehow have the tables created as they are defined in the mappings or somehow override the catalog/schema definitions at the entity level.
I cannot think of any way to achieve either outcome. Any ideas?
I believe H2 supports catalogs. I haven't used them in it myself, but there's a CATALOGS table in the Information Schema.
I managed to achieve something like this in H2 via IGNORE_CATALOGS property and version 1.4.200
However, the url example from their docs did not seem to work for me, so I added a statement in my schema.xml:
SET IGNORE_CATALOGS = true;
When I annotate a class with #Entity and try to resolve the dependencies, I get to choose the package between two different packages, javax.persistence.Entity and org.hibernate.annotations.Entity
The javax package is JPA's entity-annotation, but why is there a hibernate entity-annotation and difference does it have with JPA's annotation? Is it just an extension to allow more attributes to be defined?
org.hibernate.annotations.Entity has some extra attributes that javax.persistence.Entity has not standarized. The extra features will only work if using hibernate's AnnotationConfiguration directly or if hibernate is the JPA provider.
from the FAQ:
edit: new link the specific question:
edit: new link the answer:
I use #org.hibernate.annotations.Entity and get an Unknown entity exception
Always import #javax.persistence.Entity
#org.hibernate.annotations.Entity completes #javax.persistence.Entity but is not a replacement
For instance, there is an attribute called optimisticLock, which tells hibernate whether to use the standard version column or to compare all columns when updating. This behavior is not in the JPA spec, so in order to configure it, you must use hibernate specific extension found in their own annotation.
Like this:
#Entity
#org.hibernate.annotations.Entity(optimisticLock=OptimisticLockType.ALL)
public class MyEntity implements Serializable {
...
}
#org.hibernate.annotations used in your project, if suppose you want to use JDBC template or ibatis we need to change the code. if we use javax.persistence there is no need to change the code. This is the main difference between org.hibernate.annotations and javax persistence
I'm not sure about the differences but I am sure that if you have the Hibernate jars in your classpath you are using Hibernate JPA. Hibernate provides an implementation of JPA. Even though you are using the javax.persistence package you are using Hibernate JPA.
The difference could be only in the naming. They might provide the same classes both in the Hibernate package space and the javax package space.