JPA filter entity nested list of objects - jpa

I'm Using JPA 2.1. I have 3 entities: Dr01 , Dr02 and Dr03 with the following structure:
public class Dr01 implements Serializable {
#OneToMany(cascade = CascadeType.ALL, mappedBy = "dr01")
private List<Dr02> dr02List;
}
public class Dr02 implements Serializable {
#OneToMany(cascade = CascadeType.ALL, mappedBy = "dr02")
private List<Dr03> dr03List;
#JoinColumn(name = "DR2CLM", referencedColumnName = "DR1CLM", insertable = false, updatable = false)
#ManyToOne(optional = false)
private Dr01 dr01;
}
public class Dr03 implements Serializable {
#JoinColumns({
#JoinColumn(name = "DR3CLM", referencedColumnName = "DR2CLM", insertable = false, updatable = false),
#JoinColumn(name = "DR3PTFN", referencedColumnName = "DR2PTFN", insertable = false, updatable = false)})
#ManyToOne(optional = false)
private Dr02 dr02;
private elementOBJ element;
}
public class elementOBJ implements Serializable {
#Column(name = "XXX")
private int id;
#Column(name = "YYY")
private int status;
}
I want to select from Dr01 and get only the Dr03 objects that have element objects which contains a value of 1 inside the status field.
How do I retrieve dr03List filtered by it's status value? (filtered not after the select).
Thank's In Advance.

Options that may be of assistance:
Create a DB view based on status of DR03 table and map your
entity to that.
Use JPA Inheritance using status as a
DiscriminatorColumn.
If using Hibernate use the non-JPA #Where
annotation to filter the collection

Related

How to delete entities in a chained one-to-many and many-to-many JPA relationship

I have a chain of entities as follows:
#Entity
#Table(name = "Patients")
public class Patient extends TimeStampedPersistable{
private static final long serialVersionUID = 1L;
#OneToMany(mappedBy="patient", cascade = CascadeType.ALL)
#PrivateOwned
private List<Insurance> insurances;
}
#Entity
#Table(name = "insurance")
public class Insurance extends PersistableEntity {
private static final long serialVersionUID = 1L;
#ManyToOne(optional=false)
#JoinColumn(name="patient_id", nullable=false)
private Patient patient;
#Column(name = "policy_number", unique = false, nullable = true)
private String policyNumber;
#ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
#JoinTable(name = "insurance_companycodes", joinColumns = {
#JoinColumn(name = "insurance_id", referencedColumnName = "id", nullable = false, updatable = false) }, inverseJoinColumns = {
#JoinColumn(name = "insuranceCompanyCode_id", referencedColumnName = "id", nullable = false, updatable = false) })
private Set<InsuranceCompanyCode> insuranceCompanyCodes = new HashSet<>();
}
#Entity
#Table(name = "insurance_company_codes")
public class InsuranceCompanyCode extends PersistableEntity {
private static final long serialVersionUID = 1L;
#Column(name = "identifier", unique = true, nullable = true)
private String identifier;
#ManyToMany(mappedBy = "insuranceCompanyCodes", fetch = FetchType.LAZY)
private Set<Insurance> insurances = new HashSet<>();
}
I need to remove insurance items from the Patient object. I am using the following code:
for (Iterator<Insurance> iterator = patient.getInsurances().iterator(); iterator.hasNext();) {
iterator.next();
iterator.remove();
}
This seems to work for child entities that don't have child entities, however in this situation the Insurance entity has child entities and is not actually removed (no exceptions are displayed). Note, I am using the EclipseLink specific annotation #PrivateOwned which I expected would have forced the removal of the Insurance entities.
Any guidance, suggestions appreciated!

JPARepository - sometimes create duplicate records

I have the following entity class.
#Data
#EqualsAndHashCode(callSuper=false)
#ToString(callSuper=true)
#Entity
#Table(name = "storeitem")
public class StoreItem extends SellableStoreItem {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private UUID id;
#EqualsAndHashCode.Exclude
#ToString.Exclude
#ManyToOne
#JoinColumn(name = "store_id")
private Store store;
#EqualsAndHashCode.Exclude
#ToString.Exclude
#ManyToOne
#JoinColumn(name = "storeitemcategory_id", nullable = true)
private StoreItemCategory storeItemCategory;
#EqualsAndHashCode.Exclude
#OneToMany(fetch = FetchType.EAGER, mappedBy = "storeItem")
private List<StoreItemTranslation> storeItemTranslationList = new ArrayList<>();
#EqualsAndHashCode.Exclude
#OneToMany(mappedBy = "storeItem",
cascade = CascadeType.ALL,
orphanRemoval = true)
private List<StoreItemOptionCollectionSelection> storeItemOptionCollectionSelections = new ArrayList<>();
#EqualsAndHashCode.Exclude
#Column(name = "uid")
private UUID uid = UUID.randomUUID();
#EqualsAndHashCode.Exclude
#CreationTimestamp
#Column(name = "createddate", nullable = false)
private LocalDateTime createdDate;
#EqualsAndHashCode.Exclude
#Column(name = "iscurrent", nullable = false)
private boolean isCurrent = true;
And in my service layer, I do the following.
private StoreItemResponse setStoreItemCreate(StoreItemDTO storeItemDTO, Store store, StoreItemCategory storeItemCategory) {
StoreItem storeItem = new StoreItem(storeItemDTO, store, storeItemCategory);
if(storeItemDTO.getUid() != null){
storeItem.setUid(storeItemDTO.getUid());
}
storeItem = storeItemRepository.save(storeItem);
// Create Translations for store Item
for (TranslationDTO translationDTO : storeItemDTO.getTranslationDTOs()) {
StoreItemTranslation translation = new StoreItemTranslation(translationDTO, storeItem);
storeItemTranslationRepository.save(translation);
}
return new StoreItemResponse(storeItem.getId(), DtoResponseStatus.OK);
}
However, when testing the code, I notice that there are times (not often but some cases) I see duplicate records (with different id) are being saved to database. And the duplicates are saved 2ms apart so I suspect storeItem = storeItemRepository.save(storeItem); created the duplicate records.
Why would this happen?

spring data #ManyToOne #MapsId

can some one help me to map this 3 entities correctly, because i have tried many solution but not working.
i have this 3 entities :
Product,Item and Pack that should be mapped like this:
Product entity
public class Product implements Serializable {
#OneToMany(mappedBy="parentProduct", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
#PrimaryKeyJoinColumn
private List<Pack> packListParent;
#OneToMany(mappedBy="childProduct", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
#PrimaryKeyJoinColumn
private List<Pack> packListChild;
}
Pack entity
public class Pack implements Serializable {
#EmbeddedId
protected PackPK PackPK;
#MapsId("itemId")
#JoinColumn(name = "item_id", referencedColumnName = "item_id", insertable = true, updatable = true)
#ManyToOne(fetch = FetchType.LAZY)
private Item item;
#MapsId("parentProductId")
#JoinColumn(name = "product_id", referencedColumnName = "product_id", insertable = true, updatable = true)
#ManyToOne(fetch = FetchType.LAZY)
private Product parentProduct;
#MapsId("childProductId")
#JoinColumn(name = "child_product_id", referencedColumnName = "product_id", insertable = true, updatable = true)
#ManyToOne(fetch = FetchType.LAZY)
private Product childProduct;
}
#Embeddable
public class PackPK implements Serializable {
#Basic(optional = false)
#Column(name = "product_id")
private Long parentProductId;
#Basic(optional = false)
#Column(name = "item_id")
private Long itemId;
#Basic(optional = false)
#Column(name = "child_product_id")
private Long childProductId;
}
Item entity
public class Item implements Serializable {
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
#PrimaryKeyJoinColumn
private List<Pack> PackList;
}
this mapping work in eclipselink but when i have migrated to spring data jpa with eclipselink i have this warning when i launch the server application.
This is the error message :
WARN - [AnnotationConfigServletWebServerApplicationContext]
Exception encountered during context initialization - cancelling refresh attempt:
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'produitService': Unsatisfied dependency expressed through field 'PackService';
nested exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'PackService': Invocation of init method failed;
nested exception is java.lang.IllegalArgumentException: Expected id attribute type [class com.project.jpa.domain.PackPK]
on the existing id attribute [SingularAttributeImpl[EntityTypeImpl#1851998201:Item
[ javaType: class com.project.jpa.domain.Item descriptor: RelationalDescriptor(com.project.jpa.domain.Item --> [DatabaseTable(item)]), mappings: 47],
org.eclipse.persistence.mappings.ManyToOneMapping[item]]] on the identifiable type [EntityTypeImpl#1341697553:Pack [ javaType: class com.project.jpa.domain.Pack descriptor:
RelationalDescriptor(com.project.jpa.domain.Pack --> [DatabaseTable(pack_svod_content)]), mappings: 6]] but found attribute type [class com.project.jpa.domain.Item].

Hibernate error: mappedBy reference an unknown target entity property

I am having an issue in setting up a many to many relationship in my entities. And I don't understand why
failed; nested exception is org.hibernate.AnnotationException: mappedBy reference an unknown target entity property: cardgame.bean.User.card in cardgame.bean.Card.users
My Entities:
#MappedSuperclass
#Data
public class BaseEntity implements Serializable {
#Id
#Column(name = "id", nullable = false, unique = true)
private String id;
public BaseEntity() {
this.id = UUID.randomUUID().toString();
}
}
My user emtity:
#Data
#Entity
#Table(name = "users")
public class User extends BaseEntity {
#Column(name = "username", nullable = false, unique = true)
private String username;
#Column(name = "uuid", nullable = false)
private String uuid;
#Column(name = "email", nullable = false, unique = true)
private String email;
#OneToMany(mappedBy = "user", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
private List<Card> cards;
#Column(name = "isActive", nullable = false)
private boolean isActive;
}
My card entity:
#Data
#Entity
#Table(name = "cards")
public class Card extends BaseEntity {
#OneToMany(mappedBy = "card")
private List<User> users;
#Column(name = "strength", nullable = false)
private int strength;
#Column(name = "isActive", nullable = false)
private boolean isActive;
}
The users and cards tables have a many-to-many relationship via user_card table:
#Data
#Entity
#Table(name = "user_card")
public class UserCard implements Serializable {
#Id
#ManyToOne
#JoinColumn(name = "user_id", nullable = false)
private User user;
#Id
#ManyToOne
#JoinColumn(name = "card_id", nullable = false)
private Card card;
#Column(name = "cardCount", nullable = false)
private int cardCount;
}
What am i doing incorrect. Please help me

Insert object with composite primary key

I need help with this. With code is more clear, this is my function to persist:
public String finalizarCompra() {
Pedido pedido = new Pedido();
pedido.setEstado("almacen");
pedido.setFechaVenta(new Date());
pedido.setIdUsuario(loginBean.getUsuario());
Producto p;
Integer i;
DetPedido detPedido;
List<DetPedido> lista = new ArrayList<>();
for (Map.Entry e : productos.entrySet()) {
detPedido = new DetPedido();
p = (Producto) e.getKey();
i = (Integer) e.getValue();
detPedido.setProducto(p);
detPedido.setCantidad(i);
detPedido.setPrecioUnidad(p.getPrecioUnidad());
detPedido.setPedido(pedido);
lista.add(detPedido);
detPedidoBean.insert(detPedido);
}
pedido.setDetPedidoCollection(lista);
pedidoBean.insert(pedido);
return "";
}
This is my Pedido Entity:
#Entity
public class Pedido implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "ID_PEDIDO")
private Integer idPedido;
#Basic(optional = false)
#NotNull
#Column(name = "FECHA_VENTA")
#Temporal(TemporalType.TIMESTAMP)
private Date fechaVenta;
#Column(name = "FECHA_ENVIO")
#Temporal(TemporalType.TIMESTAMP)
private Date fechaEnvio;
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 50)
#Column(name = "ESTADO")
private String estado;
#JoinColumn(name = "ID_USUARIO", referencedColumnName = "ID_USUARIO")
#ManyToOne(optional = false)
private Usuario idUsuario;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "pedido")
private Collection<DetPedido> detPedidoCollection;
// Getters and Setters //
This is my DetPedido Entity:
#Entity
public class DetPedido implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
protected DetPedidoPK detPedidoPK;
#Basic(optional = false)
#NotNull
#Column(name = "CANTIDAD")
private Integer cantidad;
#Basic(optional = false)
#NotNull
#Column(name = "PRECIO_UNIDAD")
private Double precioUnidad;
#JoinColumn(name = "ID_PRODUCTO", referencedColumnName = "ID_PRODUCTO", insertable = false, updatable = false)
#ManyToOne(optional = false)
private Producto producto;
#JoinColumn(name = "ID_PEDIDO", referencedColumnName = "ID_PEDIDO", insertable = false, updatable = false)
#ManyToOne(optional = false)
private Pedido pedido;
// Getters and Setters //
And this is my DetPedidoPK:
#Embeddable
public class DetPedidoPK implements Serializable {
#Basic(optional = false)
#NotNull
#Column(name = "ID_PEDIDO")
private Integer idPedido;
#Basic(optional = false)
#NotNull
#Column(name = "ID_PRODUCTO")
private Integer idProducto;
// Getters and Setters //
The Entities ara generated automatically from the Database, also DetPedidoPK, and now I don't know how to save a Pedido. I tried with the code above, but it doesn't work.
Can anybody help me?
Greetings.
If you are using JPA 1.0 and this entity model, then you will need to persist and flush both Producto and Pedido instances to have their IDs assigned before you can persist the DetPedido instance that will reference them. Once that is done, you will need to manually set the id values in DetPedido's DetPedidoPK instance so that they match the referenced Producto and DetPedido key values. You cannot insert DetPedido without the DetPedidoPK values having been set.
JPA 2.0 supports derived IDs, which allows marking the relationship as either #ID or #MapsId, indicating that the ID values should be pulled from the joincolumn associated to the relationship. In this case, it would become:
#ManyToOne(optional = false)
#MapsId("idProducto")
private Producto producto;
#ManyToOne(optional = false)
#MapsId("idPedido")
private Pedido pedido;
If you wanted, you could do away with the embeddable within DetPedido and just mark the relationships as the #Id, and because it is composite you would use the DetPedidoPK as the PK class.