#ManyToMany relation with composite key and extra column, nested column in intermediate table - jpa

this is my current situation :
I have a diagram like this. In the intermediate tables I have 1 more extra column. The problem here is in the table "Period_Area_CC", the column "Area_CompNo" is referenced by 2 columns ("CompNo" from table "CC" and "Area_CompNo" from tablle "Period_Area")
And here is my mapping
public class Area extends BaseEntity {
#EmbeddedId
private AreaId id;
#OneToMany(mappedBy = "area", cascade = CascadeType.ALL, orphanRemoval = true)
private List<AreaPeriod> areaPeriods;
}
public class AreaPeriod implements Serializable {
#Id
#Column(name = "periodAssignmentID")
private Long periodID;
#Id
#Column(name = "areaID")
private Long areaID;
#Id
#Column(name = "companyNo")
private Long companyNo;
private Long parentId;
#Column(name = "hierarchyPath")
private String hierarchyPath;
#ManyToOne
#JoinColumns({#JoinColumn(name = "areaID", referencedColumnName = "areaID", updatable = false, insertable = false),
#JoinColumn(name = "companyNo", referencedColumnName = "companyNo", updatable = false, insertable = false)})
private Area area;
#ManyToOne
#JoinColumns({#JoinColumn(name = "periodAssignmentID", referencedColumnName = "periodAssignmentID", updatable = false, insertable = false)})
private VirtualAreaPeriodDefinition period;
#OneToMany(mappedBy = "parent", cascade = CascadeType.ALL)
private Set<AreaPeriod> children;
#ManyToOne
#JoinColumns({#JoinColumn(name = "periodAssignmentID", referencedColumnName = "periodAssignmentID", insertable = false, updatable = false),
#JoinColumn(name = "parentId", referencedColumnName = "areaID", insertable = false, updatable = false),
#JoinColumn(name = "companyNo", referencedColumnName = "companyNo", insertable = false, updatable = false)})
private AreaPeriod parent;
#OneToMany(mappedBy = "areaPeriod", cascade = CascadeType.ALL, orphanRemoval = true)
private List<CostCenterAreaPeriod> costCenterAreaPeriods;
}
public class CostCenterAreaPeriod implements Serializable {
#Id
#Column(name = "companyNo")
private Long companyNo;
#Id
#Column(name = "periodAssignmentID")
private Long periodId;
#Id
#Column(name = "areaID")
private Long areaId;
#Id
#Column(name = "CostCenterEnum")
private Long costCenterEnum;
private String hierarchyPath;
#ManyToOne
#JoinColumns({#JoinColumn(name = "areaID", referencedColumnName = "areaID", updatable = false, insertable = false),
#JoinColumn(name = "companyNo", referencedColumnName = "companyNo", updatable = false, insertable = false),
#JoinColumn(name = "periodAssignmentID", referencedColumnName = "periodAssignmentID", updatable = false, insertable = false)})
private AreaPeriod areaPeriod;
#ManyToOne
#JoinColumns({#JoinColumn(name = "CompanyNo", referencedColumnName = "companyNo", updatable = false, insertable = false),
#JoinColumn(name = "CostCenterEnum", referencedColumnName = "CostCenterEnum", updatable = false, insertable = false)})
private CostCenter costCenter;
}
public class CostCenter extends BaseEntity {
private static final long serialVersionUID = -2290076530189347245L;
#EmbeddedId
private CXCostCenterPK id;
#OneToMany(mappedBy = "costCenter", cascade = CascadeType.ALL, orphanRemoval = true)
private List<CostCenterAreaPeriod> costCenterAreaPeriods;
}
Because I have marked the relation with insertable and updateable false so I have to insert manually.
So is there any better solution, so I just need to map the relation on the entity, then JPA will handle the insert/update/delete funtion?
Updated :
public class CXCostCenterPK implements Serializable {
private static final long serialVersionUID = 658550094878047277L;
#Column(name = "CompanyNo")
private Long companyNo;
#Column(name = "CostCenterEnum")
private Long costCenterEnum;
}
public class AreaId implements Serializable {
#Column(name = "companyNo", length = 5, nullable = false)
private Long companyNo;
#Column(name = "areaID", length = 11, nullable = false)
private Long areaEnum;
}

Related

How to save a copy of a entity

I use spring boot 3, I have this entity structure
#Data
#Entity
#Table
public class Repo {
#Id
#NotNull
private Long repoId;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "repo", cascade = {CascadeType.ALL})
private List<Pub> pubs = new ArrayList<>(0);
...
}
#Data
#Entity
#Table
public class Pub {
#Id
#Column
#NotNull
protected Long pubId;
#ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.ALL})
#JoinColumn(name = "type_id")
protected TypeDoc typeDoc;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "pub", cascade = {CascadeType.ALL}, orphanRemoval = true)
protected List<Person> persons = new ArrayList<>(0)
#ManyToMany(fetch = FetchType.LAZY, cascade = {CascadeType.ALL})
#JoinTable(name = "pub_cat", schema = "", joinColumns = { #JoinColumn(name = "pub_id", nullable = true, updatable = false) }, inverseJoinColumns = { #JoinColumn(name = "cat_pub_id", nullable = true, updatable = false) })
private List<CatPub> catPub = new ArrayList<>(0);
}
A repo has a lit of pub, in reality they can have only 2.
So I feed a Pub object..... put it it the list of depot, and i need to create exactly the same and put it in the list of depot.
what is the most effective way to do it?

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!

How to Map two entities of the same type in JPA

I have a case where I need to create a compatibility mapping between computer hardware parts.
The idea is to check for example if ComputerPart1(motherboard_yy) is compatible with ComputerPart1(hardrive_xx)
So I have an Entity called ComputerPart
#Entity
public class ComputerPart {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(nullable = false)
private String name;
#Column(nullable = false, unique = true)
private String serialNumber;
#Column(nullable = false)
private String manufacturer;
// getter and setters
I'm not sure about the best way to do next.
Do I create an object map of computerParts with a List?
Map<ComputerPart, List<ComputerPart>>
Or Do I create another Entity Called Compatible?
The solution that I will probably chose is having a list of the same Entity Type:
#Entity
public class ComputerPart {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(nullable = false)
private String name;
#Column(nullable = false, unique = true)
private String serialNumber;
#Column(nullable = false)
private String manufacturer;
#Column(nullable = false)
private String manufacturer;
// What #Annotation to put here?
//is it #ManyToMany ?
Set<ComputerPart> compatibles;
I'm not sure about the Annotation parameters.
#ManyToMany(targetEntity = ComputerPart.class, fetch = FetchType.LAZY)
#JoinTable(name = "??", joinColumns = {
#JoinColumn(name = "??", referencedColumnName = "??")},
inverseJoinColumns = {
#JoinColumn(name = "??", referencedColumnName = "??")})

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.