okjfokjrf
okjfokjrf

Reputation: 135

Can't access a property of a Embedded class via JPA

@Entity
@EntityListeners(AuditingEntityListener.class)
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "TIPO_CONTRATO", discriminatorType = DiscriminatorType.STRING)
@JsonIgnoreProperties({ "hibernateLazyInitializer", "handler" })
public class Contrato extends AuditorEntity implements Serializable, Clonable {
   
   @Column(name = "CIF_NIF")
   @JsonView(Views.Buscador.class)
   @JsonProperty("cifNif")
   private String cifNif;

   @Column(name = "NOMBRE_SOCIEDAD_PERSONA")
   @JsonView(Views.Buscador.class)
   private String nombreSociedadPersona;
}

And i have this Embeddable class called CuentaBancaria from Contrato table:

@Embeddable
public class CuentaBancaria implements Serializable {
    
    private static final long serialVersionUID = 6835775213299596371L;

    @Column(name = "TITULAR_CUENTA")
    @JsonView(Views.Completo.class)
    private String titularCuenta;
}

In ContratoRepository i'm trying doing a JPA Query finding the "titularCuenta" field of Cuenta Bancaria finding by the cifNif field of Contrato. But it's not working. What can i do to solve this?

@Query(value="SELECT c.CuentaBancaria.titularCuenta FROM Contrato c WHERE c.cifNif= ?1 AND c.nombreSociedadPersona IS NOT NULL AND ROWNUM = 1")
    public String getNombreLegalCliente(String cifNif);

The error which is throwing:

Caused by: org.hibernate.QueryException: could not resolve property: CuentaBancaria of: com.xxxx.Contrato

Upvotes: 0

Views: 1082

Answers (2)

RoundedHouse
RoundedHouse

Reputation: 81

Yes, since your class [ CuentaBancaria ] is annotated with @Embeddable, it needs to be embedded in the parent class in this case [ Contrato ] with @Embedded.

Then, harnessing Spring Data JPA query Lookup strategies, you can access property fields of your embedded class with ease or you could still go by the @Query() approach Query lookup Strategy from Spring documentation

Sample demo code with your problem with a minimal implementation:

Entity-Class
--------------

@Entity
public class Contrato{

   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   private Long contratoId;

   @Column(name = "CIF_NIF")
   private String cifNif;

   @Column(name = "NOMBRE_SOCIEDAD_PERSONA")
   private String nombreSociedadPersona;

   //we call the embeddable class in this parent class with @Embedded annotation
   @Embedded
   private CuentaBancaria cuentaBancaria
}

 Embeddable-Class
 -----------------

 @Embeddable
 public class CuentaBancaria{

  @Column(name = "TITULAR_CUENTA")
  private String titularCuenta;
}

Now in your ContratoRepository class, we could have

@Repository
public interface ContratoRepository extends CrudRepository<Contrato, Long> {

  Optional<Contrato> findByCuentaBancariaTitularCuenta(String cifNif);
}

which interprets to JPQL snippet:

c.cuentaBancaria.titularCuenta FROM Contrato c WHERE c.cifNif= ?1

NOTE: Notice the query method name matches the exact names in the classes and their corresponding fields, preceded by findBy

Upvotes: 0

Branislav Lazic
Branislav Lazic

Reputation: 14816

You're missing CuentaBancaria field in Contrato class. That's why JQL complains.

Add the field in the class with @Embedded annotation:

public class Contrato extends AuditorEntity implements Serializable, Clonable {
    @Embedded
    private CuentaBancaria cuentaBancaria;
}

And fix the JQL expression to:

@Query(value="SELECT c.cuentaBancaria.titularCuenta FROM Contrato c WHERE c.cifNif= ?1 AND c.nombreSociedadPersona IS NOT NULL AND ROWNUM = 1")
    public String getNombreLegalCliente(String cifNif);

Upvotes: 2

Related Questions