Ignore column if not extist in table Spring Data JPA - spring-boot

I have an abtract class like below:
#MappedSuperclass
public abstract class BaseEntity {
#Id
Long id;
String name;
//getters and setters
}
and two entity extend BaseEntity
Fist class
#Entity
#Table(name= "table1")
public class TValideB extends BaseEntity {
#Column(name = "phone")
String phone;
}
Second class
#Entity
#Table(name= "table2")
public class TValide extends BaseEntity {
#Colmun(name = "mail")
String mail;
}
When i try to save TValide i get error like this non valid column "name";
In my table2 non column exsit for name.
My question is how can i ignore this column and save my entity?
Exist an other approaches without delete column name from abstract
class?

If you must use base classes, you can create two.
#MappedSuperclass
public abstract class BaseEntityWithId {
#Id
Long id;
//getters and setters
}
#MappedSuperclass
public abstract class BaseEntityWithName extends BaseEntityWithId {
String name;
//getters and setters
}
Then you simply have to pick the right one depending on the column layout of the table.

I just add #Column in name with insertable=false, updatable=false edit my abstract class like below:
#MappedSuperclass
public abstract class BaseEntity {
#Id
Long id;
#Column(name = "name", insertable=false, updatable=false)
String name;
//getters and setters
}
This approach avoid me to create a lot of abstract class or rewrite override attributes.

This should solve your problem.
In your class that extends BaseEntity, do this for the column that you don't want.
#Entity
#AttributeOverride(name = "name", column = #Column(name = "name", insertable = false, updatable = false)
public class TValide extends BaseEntity {
#Colmun(name = "mail")
String mail;
}

Change the way you use abstraction. Create a new abstract class that extends BaseEntity contains fields that are rarely used.
Example:
#MappedSuperclass
public abstract class BaseEntity {
#Id
Long id;
//getters and setters
}
#MappedSuperclass
public abstract class BaseNameEntity extends BaseEntity {
String name;
//getters and setters
}
#Entity
#Table(name= "table1")
public class TValideB extends BaseNameEntity {
#Column(name = "phone")
String phone;
//getters and setters
}
#Entity
#Table(name= "table2")
public class TValide extends BaseEntity {
#Column(name = "mail")
String mail;
//getters and setters
}
By doing this you can configure all your structure.

Related

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
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);
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

JPARepository CPRQ modified does not save full object

I have modified the design of CPRQ a bit to help my database pattern
I have an Employee table and a Department table. Both have common properties
#Column(name="tenantIDPKFK")
private Integer tenantIdpkfk;
#Column(name="status")
private Integer status;
So I created a base class ABaseEntity like below
public class ABaseEntity {
public ABaseEntity() {
}
public ABaseEntity(int tenantIdpkfk, int status) {
this.tenantIdpkfk = tenantIdpkfk ;
this.status = status ;
}
#Column(name="tenantIDPKFK")
private Integer tenantIdpkfk;
#Column(name="status")
private Integer status;
I have extended EmployeeEntity with ABaseEntity
#Entity
#Table(name = "employee")
public class EmployeeEntity extends ABaseEntity{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#Column(name = "first_name")
#NotEmpty(message = "Please provide a name")
#NotBlank
private String firstName;
My CommandHandler runs the following code
EmployeeEntity savedEmployeeEntity = this.employeeRepository.saveAndFlush(employee);
this.mediator.emit(new EmployeeCreatedEvent(savedEmployeeEntity.getId()));
Database saved the object, but only id, firstname. Does not save tenant and status columns.
I know I am missing something silly. Please help.
EDIT
Adding #MappedSuperclass to the ABaseEntity class fixed the issue.
#MappedSuperclass
public class ABaseEntity {...}
Database saved the object, but only id, firstname. Does not save
tenant and status columns.
By default JPA doesn't consider the parent class in the orm (object-relational mapping) of the current class.
You have to specify on the parent class #Inheritance with the strategy to use or use the default one.
For example :
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class ABaseEntity {...}
More info here.

Embeddable is creating 2 tables jpa springs

I have below entites
AbstractOrderEntry :
#Getter #Setter
public class AbstractOrderEntry implements Serializable
{
#ElementCollection
private List<DiscountValue> discountValues = new ArrayList<>();}
}
CartEntry extending AbstractOrderEntry
#Entity
#EntityListeners(value = AuditListener.class)
#Table(name = "cartentry")
#Getter #Setter
public class CartEntry extends AbstractOrderEntry implements Serializable,Cloneable,Auditable
{
#Id
#Column(name="CartEntryID",nullable = false)
#GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
}
DiscountValueEntity:
#Embeddable
#Getter #Setter
public class DiscountValue {
private String code;
private BigDecimal value;
private BigDecimal appliedValue;
}
When I start the server it is generating to tables like
cart_discountValue
cart_discountvalue
one with camelcase and other is with lowercase.
We are also extending AbstractOrderEntry for order entity as well hence for order also 2 tables are getting created.
How can overcome this issue.Because of this issue table data is not properly persisting.
Thanks , Inadvance.
Sree

AuditingEntityListener is not working for the entity that extends another abstract entity in spring jpa

I have used the #CreatedBy, #CreatedDate, #LastModifiedBy, and #LastModifiedDate annotation on their respective fields. By using #MappedSuperclass,#EntityListeners i able to persist above columns.
But this is not working for the below case:
#MappedSuperclass
#EntityListeners(AuditingEntityListener.class)
public abstract class Auditable<U> {
#CreatedBy
protected U createdBy;
#CreatedDate
#Temporal(TIMESTAMP)
protected Date creationDate;
#LastModifiedBy
protected U lastModifiedBy;
#LastModifiedDate
#Temporal(TIMESTAMP)
protected Date lastModifiedDate;
}
#Entity
#Table(name = "tabel1")
#PrimaryKeyJoinColumn(name = "ID")
class A extends B {
#Column(name = "NAME1", nullable = false)
private String name1;
#Column(name = "CONTENT1", nullable = false)
private String content1;
}
#Entity
#Table(name = "tabel2")
public abstract class B extends Auditable{
#Id
#GeneratedValue
#Column(name = "ID", nullable = false)
private int id;
#Column(name = "NAME", nullable = false)
private String name;
#Column(name = "CONTENT", nullable = false)
private String content;
}
AuditorAwareImpl.java
public class AuditorAwareImpl implements AuditorAware<String>
{
#Override
public Optional<String> getCurrentAuditor()
{
return Optional.ofNullable("Saravanan");
}
}
JpaAuditConfiguration.java
#Configuration
#EnableJpaAuditing(auditorAwareRef = "auditorProvider")
public class JpaAuditConfiguration
{
#Bean
public AuditorAware<String> auditorProvider()
{
return new AuditorAwareImpl();
}
}
In the case, Entity B is populated with audit columns. But Entity A is not. Is there a way to populate Entity A or did i missed anything here..??
I added #Entity annotation to your classes:
#Entity
public class A extends B {
#Id
#GeneratedValue
private Integer id;
private String name;
private String content;
}
#Entity
public class B extends Auditable<String> {
#Id
#GeneratedValue
private Integer id;
private String name;
private String content;
}
Persistence config class (for Spring Boot):
#Configuration
#EnableJpaAuditing
public class PersistenceConfig {
}
Everything works perfectly!

Base model with #Audited

I use #Audited annotation for my base model. I extend that for all my entities. but it not work. Is there any method I can use that
this is my base model
#MappedSuperclass
#Getter
#Setter
#Audited
public abstract class BaseModelObject implements Serializable {
/**
*
*/
private static final long serialVersionUID = 4194525198831057382L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
protected Long id;
}
This is my model class
#Entity
public class City extends BaseModelObject {
private static final long serialVersionUID = 1L;
#Column
private String name;
}
The #Audited annotation doesn't work the way you believe it should. By using it on a super class, it has no impact to the child classes which extend it, at least to control whether the child is or is not audited. This is by design.
Consider the notion where we have a superclass type and two different implementations, one which we want to audit with its superclass properties and one which we don't.
#MappedSuperclass
#Audited
public class Animal {}
#Entity
#Audited
public class Cat extends Animal {}
#Entity
public class Dog extends Animal {}
In this example, since #Audited isn't inherited, merely placing the annotation on the superclass and the Cat entity result in just Cat being audited. The Dog entity and its superclass property values are not.
If #Audited were treated as an inherited annotation, we'd have to introduce a series of #AuditOverride annotations to accomplish the same example, see below.
#MappedSuperclass
public class Animal {}
#Entity
#Audited
#AuditOverride(...)
public class Cat extends Animal {}
#Entity
public class Dog extends Animal {}
What makes this worse is if Animal had a subset of its properties audited, which would influence the number of #AuditOverrides.
This becomes even more complicated when you start to look at entity inheritance strategies and how those come into play with whether to audit an entity or not, and to what degree at what level of the hierarchy.
There is an entire discussion HHH-6331 and HHH-9770.
In short, if you want your child classes audited, they'll need to be explicitly annotated.
Try with this:
Superclass:
#MappedSuperclass
#EntityListeners(AuditingEntityListener.class)
public abstract class AuditableEntity implements Serializable {
private static final long serialVersionUID = 1L;
#CreatedDate
private LocalDateTime createdDate;
#LastModifiedDate
private LocalDateTime lastModifiedDate;
#CreatedBy
private String createdBy;
#LastModifiedBy
private String lastModifiedBy;
...
}
Entity class:
#Entity
public class City extends AuditableEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
...
}
Configuration:
#EnableJpaAuditing
#SpringBootApplication
#EnableTransactionManagement
#EntityScan("foo.entities")
#ComponentScan("foo")
#EnableJpaRepositories("foo.repositories")
public class ConfigApp {
...
}
Auditor service:
#Service
public class AuditorServiceImpl implements AuditorAware<String> {
#Override
public String getCurrentAuditor() {
return SecurityContextHolder.getContext().getAuthentication().getName();
}
}

Resources