A.class
#Getter
#Entity
#Table(name = "A")
public class A extends JpaEntity<Long> {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "aId", nullable = false)
private Long id;
#OneToMany(fetch = FetchType.EAGER)
#JoinColumn(name = "aId")
#Setter
private Set<relationship_table_between_a_and_b> bOfa;
}
relationship_table_between_a_and_b.class
#Entity
#Table(name = "relationship_table_between_a_and_b")
#Getter
public static relationship_table_between_a_and_b extends JpaEntity<relationship_table_between_a_and_b.Id> {
#EmbeddedId
#Setter
private Id id;
#Embeddable
#Getter
public static class Id implements Serializable {
#Setter
#Column(name="aId", nullable = false)
private Long aId;
#Setter
#OneToOne(fetch = FetchType.EAGER, optional = false)
#JoinColumn(name="bId", nullable = false)
private B b;
}
}
B.class
public static B extends JpaEntity<Long> {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "bId", nullable = false)
private Long id;
#OneToMany(fetch = FetchType.EAGER)
#JoinTable(
name = "relationship_table_between_b_and_a",
joinColumns = #JoinColumn(name = "bId", nullable = false),
inverseJoinColumns = #JoinColumn(name = "aId", nullable = false))
#Setter
#JsonIgnoreProperties("bOfa")
private List<A> as;
}
I tried several ways but didn't solve the stackoverflowerror
Could not solve the infinite reference that occurs when as of class B refers to bToa of a again.
I want to solve this problem... please help
Related
I am trying to get the versions field within my MachineGroup Entity that is ManyToMany relationship. I am trying to fetch it in a custom serializer using ObjectMapper but for some reason I always get the LazyInitializationException - org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.altair.autoTester.entities.machinegroup.MachineGroup.versions, could not initialize proxy - no Session.
MachineGroup
#Entity
#Table(name="machine_groups")
#Getter
#Setter
#AllArgsConstructor(access = AccessLevel.PUBLIC)
#NoArgsConstructor
public class MachineGroup {
#Id
#GeneratedValue(strategy= GenerationType.AUTO, generator = "machine_groups_seq")
#SequenceGenerator(name = "machine_groups_seq", allocationSize = 1, initialValue = 2)
#Column(name = "id")
private long id;
#ManyToMany(cascade = CascadeType.MERGE)
#JoinTable(name = "machine_groups_to_versions",
joinColumns = #JoinColumn(name = "machine_group_id"),
inverseJoinColumns = #JoinColumn(name = "version_id"))
#JsonManagedReference(value="machineGroups-versions")
private Set<Version> versions = new HashSet<>();
#ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinTable(name = "machine_groups_to_tr_types",
joinColumns = #JoinColumn(name = "machine_group_id"),
inverseJoinColumns = #JoinColumn(name = "tr_type_id"))
private Set<TrType> trTypes = new HashSet<>();
}
Version.java
#Entity
#Table(name="versions")
#Getter
#Setter
public class Version {
#Id
#GeneratedValue(strategy = GenerationType.AUTO, generator = "versions_seq")
#SequenceGenerator(name = "versions_seq", allocationSize = 1)
#Column(name = "id")
private long id;
#Column(name = "name", unique = true)
private String name;
#Column(name = "creation_time")
private Date creationTime;
#Column(name = "exe_file")
#Lob
private Blob exeFile;
#JsonBackReference(value="machineGroups-versions")
#ManyToMany(mappedBy = "versions", cascade = CascadeType.MERGE)
private Set<MachineGroup> machineGroups = new HashSet<>();
public Version(){};
public Version(String name) {
this.name = name;
}
}
MachineGroupSerializer.java
public class MachineGroupSerializer extends StdSerializer<MachineGroup> {
public MachineGroupSerializer() {
this(null);
}
public MachineGroupSerializer(Class<MachineGroup> t) {
super(t);
}
#Transactional
#Override
public void serialize(MachineGroup machineGroup,
JsonGenerator jsonGenerator,
SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeStartObject();
jsonGenerator.writeNumberField("id",machineGroup.getId());
jsonGenerator.writeObjectField("versions", machineGroup.getVersions().stream().map(Version::getId).collect(Collectors.toSet()));
jsonGenerator.writeObjectField("trTypes", machineGroup.getTrTypes().stream().map(TrType::getId).collect(Collectors.toSet()));
jsonGenerator.writeEndObject();
}
}
TrTypes.java
#Table(name = "tr_types", indexes = {
#Index(name = "tr_types_type_name_uindex", columnList = "type_name", unique = true)
})
#Entity
#AllArgsConstructor(access = AccessLevel.PUBLIC)
#NoArgsConstructor
public class TrType {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", nullable = false)
private Long id;
#Column(name = "type_name", nullable = false)
private String typeName;
}
I put the JsonManagedReference and JsonBackReference so I won't have infinite loop calling one another, not sure if it's causing any issues.
Calling the getTrTypes() function works but has the EAGER fetchType which I do not want to add to the versions collection.
What can cause this lazy exception to occur and how can I prevent it?
Also the function calling the serialzier within my MachineGroupService has the #Transactional annotation, I saw something that is related to the hibernate session that might be close at the serializer level.
I have two tables, A and B (not defined by me, inherited from old legacy software), with the following structure:
A: PK (idA, ente),
B: PK(idB, ente), FK(idA, ente) --> A
I need to use #IdClass/#Id, rather than #Embeddeble/#EmbeddebleId, because #GeneratedValue on id columns.
I'd like to insert a new couple of rows this way:
A a = new A();
a.setEnte('E1');
a = repA.save(a);
B b = new B();
b.setA(a);
b = repB.save(b);
I use Spring Data JPA's repositories class. My best try, was:
#Getter
#ToString
#Setter
#Entity
#Table(name = "address")
#IdClass(BPK.class)
#NoArgsConstructor
public class B implements Serializable{
#ManyToOne
#JoinColumns({
#JoinColumn(name="idA", referencedColumnName="idA", nullable=false, insertable=false, updatable=false),
#JoinColumn(name="ente", referencedColumnName="ente", nullable=false, insertable=false, updatable=false)
})
private A a;
#Id
#org.hibernate.annotations.GenericGenerator(name = "incrementGenerator", strategy = "org.hibernate.id.IncrementGenerator")
#GeneratedValue(generator="incrementGenerator")
#Column(name = "idB", columnDefinition = "int(10)", nullable = false)
private Integer idB;
#Id
#Column(insertable=false, updatable=false, unique=true, nullable=false, length=6)
private String ente;
}
#Getter
#ToString
#Setter
#Entity
#Table(name = "Users")
#IdClass(APK.class)
#NoArgsConstructor
public class A implements Serializable {
#Id
#org.hibernate.annotations.GenericGenerator(name = "incrementGenerator", strategy = "org.hibernate.id.IncrementGenerator")
#GeneratedValue(generator="incrementGenerator")
#Column(name = "idA", columnDefinition = "int(10)", nullable = false)
private Integer idA;
#Id
#Column(name = "ente", columnDefinition = "char(6)", nullable = false)
public String ente;
}
This solution doesn't work, because idA and ente are not inserted in save(b) instruction. If I change insertable=true in the #ManyToOne lines, there will be error on ente field.
Any suggestions?
Your b.setA() method could also set this automatically
Thanks to Christian Beikov's suggestion, I found an acceptable solution to the problem.
Why it should not infer data directly from the entities is not clear to me.
However, the solution is to force the missing data to be set before persisting using #PrePersist.
The model for B becomes:
#Getter
#ToString
#Setter
#Entity
#Table(name = "address")
#IdClass(BPK.class)
#NoArgsConstructor
public class B implements Serializable{
#ManyToOne
#JoinColumns({
#JoinColumn(name="idA", referencedColumnName="idA", nullable=false, insertable=false, updatable=false),
#JoinColumn(name="ente", referencedColumnName="ente", nullable=false, insertable=false, updatable=false)
})
private A a;
#Id
#org.hibernate.annotations.GenericGenerator(name = "incrementGenerator", strategy = "org.hibernate.id.IncrementGenerator")
#GeneratedValue(generator="incrementGenerator")
#Column(name = "idB", columnDefinition = "int(10)", nullable = false)
private Integer idB;
#Id
#Column(insertable=false, updatable=false, unique=true, nullable=false, length=6)
private String ente;
//New lines (In the real code I used getters, of course) <--
#Column(name = "idA", nullable = false, columnDefinition = "int(10)")
private Integer idA;
#PrePersist
private void init() {
this.ente = a.ente;
this.idA= a.idA;
}
}
I'm having problem with mapping two classes with composite keys.
The first class is Product:
#Entity
#Table(name = "Products")
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
#SuperBuilder
public class Product {
#EmbeddedId
private ProductKey prodPK;
#Column(name = "name", length = 50, nullable = false)
private String name;
#Column(name = "description", length = 80)
private String description;
#Column(name = "totalStock", columnDefinition = "double(8,2) default 0")
private double totalStock;
#ManyToOne
#JoinColumn(name = "companyId", referencedColumnName = "id", nullable = false)
private Company company;
}
With this #EmbeddedId:
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
#EqualsAndHashCode
#Embeddable
public class ProductKey implements Serializable {
#Column(name = "sku", length = 50)
private String sku;
#Embedded
private LotKey lot;
}
At the same time, this embedded class has as part of its composite key another composite key "LotKey"
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
#EqualsAndHashCode
#Embeddable
public class LotKey implements Serializable {
#Column(name = "lot")
private String lot;
#ManyToOne
#JoinColumn(name = "company", referencedColumnName = "id")
private Company company;
}
which belongs to the class:
#Entity
#Table(name = "Lots")
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
#SuperBuilder
public class Lote {
#EmbeddedId
private LotKey lotpk;
#Column(name = "stock")
private double stock;
#Column(name = "expirationDate", columnDefinition = "default current_timestamp()")
private Date expirationDate;
}
But I'm having trouble referencing to them:
#Entity
#Table(name = "quantityProduct")
public class QuantityProduct{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private long id;
#ManyToOne
#JoinColumns({
#JoinColumn(
name = "sku",
referencedColumnName = "sku"),
#JoinColumn(
name = "lot")
})
private Product product;
#Column(name = "quantity", columnDefinition = "double(8,2) default 0")
private double quantity;
}
I am getting the following error
image
Thank you so much !
In QuantityProduct, set also referencedColumnName in
#JoinColumn(
name = "lot")
I have problems to solve this relationship between User and Roles.
I was able to resolve the relations between User-Organization and Organization-Roles
How can I solve it using notations?
EDIT
I have these classes:
Organization Class
#Entity
#Table(name = "Organizations")
public class Organization implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
private String name;
private String imgLogo;
#ManyToMany
#JoinTable(
name = "OrganizationRoles",
joinColumns = {#JoinColumn(name = "organizationId",
referencedColumnName = "id", updatable = false)},
inverseJoinColumns = {#JoinColumn(name = "roleId",
referencedColumnName = "id", updatable = false)}
)
private List<Role> roles;
....
}
User Class
#Entity
#Table(name = "Users")
public class User implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
private String name;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "organizationId", nullable = false)
private Organization organization;
????????
private List<Role> roles;
...
}
Thank you!
Tables
I have 3 tables:
Principals: PK -> PrincipalID
Roles_type: PK -> roles_type
Roles: PK -> PrincipalID (Foreign Key), PK -> Role (Foreign Key).
My Entity are:
PRINCIPALS
#Entity
#Table(name = "principals")
#Cache(usage=CacheConcurrencyStrategy.READ_WRITE)
public class Principals implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#javax.persistence.GeneratedValue(strategy=GenerationType.AUTO)
#Column(name = "PrincipalID", nullable = false)
private String principalID;
#OneToMany(fetch = FetchType.LAZY,cascade = CascadeType.ALL, mappedBy = "principals")
private Collection<Roles> rolesCollection;
}
ROLES
#Entity
#Table(name = "roles")
#Cache(usage=CacheConcurrencyStrategy.READ_WRITE)
public class Roles implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
protected RolesPK rolesPK;
#Column(name = "RoleGroup")
private String roleGroup;
#JoinColumn(name = "Role", referencedColumnName = "roles_type", insertable = false, updatable = false)
#ManyToOne(optional = false)
private RolesType rolesType;
#JoinColumn(name = "PrincipalID", referencedColumnName = "PrincipalID", insertable = false, updatable = false)
#ManyToOne(fetch = FetchType.EAGER)
private Principals principals;
}
ROLESPK
#Embeddable
public class RolesPK implements Serializable {
#Column(name = "PrincipalID", nullable = false)
private String principalID;
#Column(name = "Role", nullable = false)
private String role;
}
ROLES_TYPE
#Entity
#Table(name = "roles_type")
#Cache(usage=CacheConcurrencyStrategy.READ_WRITE)
public class RolesType implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#Column(name = "roles_type")
private String rolesType;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "rolesType")
private Collection<Roles> rolesCollection;
}
My code for persist a new principals:
Principals principals = new Principals();
principals.setPrincipalID("PRINCIPAL");
RolesType rolesType = em.find(RolesType.class, "TYPE_1");
RolesPK rolesPk = new RolesPK();
rolesPk.setPrincipalID(principals.getPrincipalID());
rolesPk.setRole(rolesType.getRolesType());
Collection<Roles> collRoles = new ArrayList<Roles>();
Roles roles = new Roles();
roles.setRolesType(rolesType);
roles.setRolesPK(rolesPk);
roles.setPrincipals(principals);
collRoles.add(roles);
principals.setRolesCollection(collRoles);
rolesType.setRolesCollection(collRoles);
em.persist(principals);
So I get:
javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: package.entity.Principals
I tried many combinations (persist roles, change CascadeType etc...)
Please help me :-)
Resolved:
I changed Principals.java from
#Id
#javax.persistence.GeneratedValue(strategy=GenerationType.AUTO)
#Column(name = "PrincipalID", nullable = false)
to
#Id
#Basic(optional = false)
#Column(name = "PrincipalID")