Hibernate/JPA - Annotating Bean Methods VS Fields

Hibernate/JPA - annotating bean methods vs fields

Yes, I believe you want to search on field versus property access:

Hibernate Annotations - Which is better, field or property access?

The Spring preference is field access. That's what I follow.

Hibernate Annotations - Which is better, field or property access?

I prefer accessors, since I can add some business logic to my accessors whenever I need.
Here's an example:

@Entity
public class Person {

@Column("nickName")
public String getNickName(){
if(this.name != null) return generateFunnyNick(this.name);
else return "John Doe";
}
}

Besides, if you throw another libs into the mix (like some JSON-converting lib or BeanMapper or Dozer or other bean mapping/cloning lib based on getter/setter properties) you'll have the guarantee that the lib is in sync with the persistence manager (both use the getter/setter).

Where to put hibernate annotations?

You place them either on the field or on the getter. From the Hibernate Annotations Reference Guide:

2.2.1. Marking a POJO as persistent entity


(...)

Depending on whether you annotate
fields or methods, the access type
used by Hibernate will be field or
property. The EJB3 spec requires that
you declare annotations on the element
type that will be accessed, i.e. the
getter method if you use property
access, the field if you use field
access. Mixing annotations in both
fields and methods should be avoided.
Hibernate will guess the access type
from the position of @Id or
@EmbeddedId.

You might also want to read about the @Access annotation that allows to force/override the access type (prior to Hibernate Annotations 3.5 and JPA 2.0, it was part of Hibernate Annotation Extensions):

2.2.2.2. Access type


By default the access type of a class
hierarchy is defined by the position
of the @Id or @EmbeddedId annotations.
If these annotations are on a field,
then only fields are considered for
persistence and the state is accessed
via the field. If there annotations
are on a getter, then only the getters
are considered for persistence and the
state is accessed via the
getter/setter. That works well in
practice and is the recommended
approach.

Note


The placement of annotations within a class hierarchy has to be consistent
(either field or on property) to be
able to determine the default access
type. It is recommended to stick to
one single annotation placement
strategy throughout your whole
application.


However in some situations, you need
to:

  • force the access type of the entity hierarchy
  • override the access type of a specific entity in the class hierarchy
  • override the access type of an embeddable type

The best use case is an embeddable
class used by several entities that
might not use the same access type. In
this case it is better to force the
access type at the embeddable class
level.

(...)

Regarding the pros and cons of both styles, I suggest to read the following questions:

  • Hibernate/JPA - annotating bean methods vs fields
  • Hibernate Annotations - Which is better, field or property access?
  • Performance difference between annotating fields or getter methods in Hibernate / JPA

What is the easiest way to ignore a JPA field during persistence?

@Transient complies with your needs.

Field repository in '' required a bean named 'entityManagerFactory' that could not be found

This bean definition is usually provided automatically by Spring Boot Auto-Configuration. The spring reference manual explains how to diagnose such issues:

The Spring Boot auto-configuration tries its best to “do the right thing”, but sometimes things fail, and it can be hard to tell why.

There is a really useful ConditionEvaluationReport available in any Spring Boot ApplicationContext. You can see it if you enable DEBUG logging output. If you use the spring-boot-actuator (see the Actuator chapter), there is also a conditions endpoint that renders the report in JSON. Use that endpoint to debug the application and see what features have been added (and which have not been added) by Spring Boot at runtime.

Many more questions can be answered by looking at the source code and the Javadoc. When reading the code, remember the following rules of thumb:

  • Look for classes called *AutoConfiguration and read their sources. Pay special attention to the @Conditional* annotations to find out what features they enable and when. Add --debug to the command line or a System property -Ddebug to get a log on the console of all the auto-configuration decisions that were made in your app. In a running application with actuator enabled, look at the conditions endpoint (/actuator/conditions or the JMX equivalent) for the same information.

In your case, a simple full text search finds that Hibernate is auto-configured by org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration, which is declared as follows:

@AutoConfiguration(after = { DataSourceAutoConfiguration.class })
@ConditionalOnClass({ LocalContainerEntityManagerFactoryBean.class, EntityManager.class, SessionImplementor.class })
@EnableConfigurationProperties(JpaProperties.class)
@Import(HibernateJpaConfiguration.class)
public class HibernateJpaAutoConfiguration {

}

As you can tell from the ConditionalOnClass annotation, this configuration is only applied if your classpath contains the classes LocalContainerEntityManagerFactoryBean from spring-orm-jpa, EntityManager from the JPA spec, and SessionImplementor from the hibernate jar.

Most likely, you are missing one of these JAR files (maven dependencies), or have the wrong version of one. The ConditionEvaluationReport should tell you which, and the precise package names to check for.

Spring configuring bean with component scan - Field userRepository in service.UserService required a bean of type 'repository

Omg. I have found it. I have just added

basePackages = {"com.practice.multiDatabase.repository"}

to config and it is working now.

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
basePackages = {"com.practice.multiDatabase.repository"},
entityManagerFactoryRef = "entityManagerFactory",
transactionManagerRef = "transactionManager")
public class UserDbConfig {


Related Topics



Leave a reply



Submit