jpa one-to-many self reference is fetching all levels - java

I'm trying to create a social app service. I have user with confirmed or nonconfirmed relationships.
When I load UserA, the result look like belove.
"result":{
"idUser":"UserA",
"unconFriendships":[
{
"idUser":"UserB",
"unconFriendships":[
{
"idUser":"UserC",
"unconFriendships":[
...
While it has to be look like
"result":{
"idUser":"UserA",
"unconFriendships":[
{
"idUser":"UserB",
"unconFriendships":null //only one level have to fetched
....
I thought that this was because jackson json library, I debbuged the code. Before serialization, I inspected userA object and I saw that userA.unconFriendships.userB.unconFriendships was not null and with size bigger than 0.
Nearly it has been 12 hours, still couldn't solve the problem. Please help me to solve this. Thanks in advence.
Here is UserEntity.java
#Entity
#Table(name="aduser",uniqueConstraints=#UniqueConstraint(columnNames = {"idUser","nmEmail"}))
#JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="cdUser")
public class UserEntity extends BaseEntity {
protected static final long serialVersionUID = 8864033727886664353L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO, generator = "admin_seq")
#SequenceGenerator(name = "admin_seq", sequenceName = "CDUSER_SEQUENCE", allocationSize = 1)
#Column(name="cdUser")
private long cdUser;
#OneToMany(mappedBy = "owner", targetEntity=Friendship.class)
#JsonProperty
protected Set<UnconfirmedFriendship> unconFriendships;
#OneToMany(mappedBy = "owner", targetEntity=Friendship.class)
#JsonProperty
protected Set<UnconfirmedFriendship> conFriendships;
...
Friendship.java
#Entity
#Table(name="aduserfriend")
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name = "verified")
#JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="friend_cduser",scope=UserEntity.class)
public abstract class Friendship extends BaseEntity{
protected static final long serialVersionUID = -670863816551430192L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "cdFriendship")
private long cdFriendship;
#ManyToOne
#JsonIgnore
#JoinColumn(name = "owner_cduser")
protected UserEntity owner;
#ManyToOne
#JoinColumn(name = "friend_cduser")
protected UserEntity friend;
#Column(name = "verified",insertable=false,updatable=false)
private boolean verified;
...
UnconfirmedFriendship.java and ConfirmedFriendship.java
#Entity
#DiscriminatorValue(value = "0")//this value is 1 for Confirmed relationship
public class UnconfirmedFriendship extends Friendship {
private static final long serialVersionUID = 57796452166904132L;
}

Related

One table has two same joins in another table

I have one table called image and another table called duplicate. There are two OneToMany relations are associated.
I am not quite sure whether below implementation is the right approach for that. Moreover whether we require that second private List<DuplicateEntity> duplicateEntities2; ?
ImageEntity:
#Entity
#Table(name = "image")
public class ImageEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "filename")
private String fileName;
#OneToMany(mappedBy = "imageEntity1")
private List<DuplicateEntity> duplicateEntities1;
#OneToMany(mappedBy = "imageEntity2")
private List<DuplicateEntity> duplicateEntities2;
}
DuplicateEntity:
#Entity
#Table(name = "duplicate")
public class DuplicateEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#ManyToOne
#JoinColumn(name = "image_a_id")
private ImageEntity imageEntity1;
#ManyToOne
#JoinColumn(name = "image_b_id")
private ImageEntity imageEntity2;
}

Hibernate one to one criteria fetching

I am using hibernate one to one mapping between car and person table. But a person might have car and might not have a car. now while fetching the records from the person table using hibernate criteria , I want to fetch only those persons who have a car, i.e only those entries in person table for which a corresponding entry in car table exists. How this can be done using hibernate criteria/alias?
Below is the piece of code. kindly help with the criteria or alias that has to written to fetch result:
#Getter
#Setter
#Entity
#Table(name = "Person")
public class Person implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "Person_ID")
private Long personId;
#OneToOne(mappedBy = "personAsset", cascade = CascadeType.ALL)
private Car car;
}
#Getter
#Setter
#Entity
#Table(name = "Car")
public class Car implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "Car_ID")
private Long carId;
#OneToOne
#JoinColumn(name = "Person_ID")
private Person personAsset;
}
what you are looking for is the cascadeType orphanRemoval=true on the #OneToOne annotation.
here is your class how would look like :
#Getter
#Setter
#Entity
#Table(name = "Car")
public class Car implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "Car_ID")
private Long carId;
#OneToOne(fetch=FetchType.EAGER , cascade=CascadeType.ALL, orphanRemoval=true)
#JoinColumn(name = "Person_ID")
private Person personAsset;
}
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Person> query = cb.createQuery(Person.class);
Root<Person> person = query.from(Person.class);
Predicate predicate = cb.isNotNull(person.join("car"));
predicates.add(predicate );

How to save data-from-parent-to-child-tables-based-on-entities-in-spring-jpa

I have a table master table user ,topics table and comments table
where in for a single topic there can be multiple comments
user table will be already populated.
I will get a post request to save the topic with structure like below
{
"topicId":"T001",
"title":"stackoverflow",
"commentBeans":[
{
"comment":"developer platform"
},
{
"comment":"developer communtiy"
}
]
}
Frameworks used:
spring boot
JPA
DB : postgressql
I am able to save the data the traditional way (i.e get the request and save topic bean first. get the primarykey from saved entity and loop the list of commentbean where user num will be set dynamically by another get service and save them)
I wanted to know if there is anyway to save the data with single save query.
#Entity
#Table(name ="user")
public class User implements Serializable {
#Id
#Column(name = "user_num")
#GeneratedValue(strategy = GenerationType.AUTO)
private Long userNum;
#Column(name = "user_id")
private String userId;
#Column(name = "username")
private String userName;
}
#Entity
#Table(name = "topics")
public class TopicBean implements Serializable {
#Id
#Column(name = "topic_num")
#GeneratedValue(strategy = GenerationType.AUTO)
private Long topicNum;
#Column(name = "topicId")
private String topicId;
#Column(name = "title")
private String title;
#OneToMany(mappedBy="topicBean")
private List<CommentBean> commentBeans;
}
#Entity
#Table(name = "comments")
public class CommentBean implements Serializable {
#EmbeddedId
private CommentBeanKey key;
#Column(name = "comment")
private string comment;
#ManyToOne
#JoinColumn(name="topic_num")
private TopicBean topicBean;
#ManyToOne
#JoinColumn(name="user_num")
private TopicBean topicBean;
}
#Embeddable
public class CommentBeanKey implements Serializable{
private static final long serialVersionUID = 5889249943605061539L;
#Column(name ="topic_num")
private Long topicNum;
#Column(name ="user_num")
private Long userNum;
}
I saw the below link and am little worried if am doing the wrong way. any help is appreciated.
https://thoughts-on-java.org/hibernate-tips-how-to-map-an-entity-to-multiple-tables/
Parent.java
#Entity
#Table(name = "parent")
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
#ToString
public class Parent {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int parentId;
private String name;
#OneToMany(mappedBy="parent",fetch=FetchType.LAZY,cascade = CascadeType.PERSIST)
private List<Child> child = new ArrayList<Child>();
}
Child.java
#Entity
#Table(name = "child")
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
#ToString
public class Child {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int childId;
private String account;
#ManyToOne(fetch = FetchType.LAZY, targetEntity = Parent.class)
#JoinColumn(name="parentId", referencedColumnName = "parentId", nullable = false)
private Parent parent;
}
Controller.java
//save Child with Parent at same
#PostMapping(value = "/onetomany")
public String OneToMany(#RequestBody Parent parent)
{
System.out.println("Parent: "+parent.toString());
for (Child child : parent.getChild()) {
child.setParent(parent);
}
parent.setChild(parent.getChild());
parentRepository.save(parent);
return "saved";
/*{
"name":"Romil",
"child":[
{"account":"1"},
{"account":"2"}
]
}*/
}
//save Child with Parent's ID
#PostMapping(value = "/onetomanyPID")
public String OneToMany(#RequestBody Child child)
{
child.setParent(child.getParent());
childRepository.save(child);
return "saved";
/*{
"account":"3",
"parent":{
"parentId":"1",
"name":"Romil"
}
}*/
}

How to maintain foreign key relationship in hibernate

I have two classes and I want to have a one to many relation between them, for e.g.:
Home(id<int>, rooms<string>)
Vehicle(id<int>, home_id<int>, name<string>)
I need to have a relation between Home and Vehicle class using Home.id and vehicle.home_id.
Please suggest any example which I can use here for CURD operation to implement REST service.
I need to have a relation between Home and Vehicle class using Home.id
and vehicle.home_id.
Your entities should look like this :
Vehicle Entity
#Entity
#Table(name = "vehicle", catalog = "bd_name", schema = "schema_name")
#XmlRootElement
public class Vehicle implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id")
private Integer id;
#Column(name = "name")
private String name;
#JoinColumn(name = "home_id", referencedColumnName = "id")
#ManyToOne
private Home homeId;
//constructor getter & setters
}
Home Entity
#Entity
#Table(name = "home", catalog = "bd_name", schema = "schema_name")
#XmlRootElement
public class Home implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id")
private Integer id;
#Column(name = "room")
private Character room;
#OneToMany(mappedBy = "homeId")
private List<Vehicle> vehicleList;
//constructor getter & setters
}

Mapping composite key with Hibernate produces a raw field in Oracle

-- The Facts....
In my project every class/table should have a couple (Site,Structure) in order to provide multisite deploy.
I provided an Installation class
#Entity
#Table(name="COM_INSTALLATION")
#IdClass(InstallationPK.class)
public class Installation implements Serializable{
private static final long serialVersionUID = 3601006283578715263L;
#Id
#Column(name = "site")
private String site;
#Id
#Column(name = "structure")
private String structure;
/* ... constructor, getters, setters ... */
}
and its PK, as
public class InstallationPK implements Serializable {
private static final long serialVersionUID = 1L;
private String site;
private String structure;
/* .. constructor, getters, setters ... */
}
then I have a MappedSuperclass named BaseEntity
#MappedSuperclass
public class BaseEntity
{
private Installation installation;
#OneToOne
#JoinColumns({
#JoinColumn(name = "site", referencedColumnName = "site"),
#JoinColumn(name = "structure", referencedColumnName = "structure")
})
public Installation getInstallation() {
return installation;
}
public void setInstallation(Installation installation) {
this.installation = installation;
}
}
quite easy so far... every #Entity and #Table annotated class extending BaseEntity contains a column SITE, a column STRUCTURE and a related foreign key.
-- The Problem....
It happens that with a class implementing org.springframework.security.core.userdetails.UserDetails and extending BaseEntity, Hibernate does not create the two columns but an INSTALLATION column with RAW type. That's the class
#Entity
#Table(name="USR_USER", uniqueConstraints =
#UniqueConstraint(columnNames = { "username" }))
#SequenceGenerator(name = "userId_seq_generator", sequenceName = "S_USER")
public class User extends BaseEntity implements UserDetails{
private static final long serialVersionUID = 8698408700004341649L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO, generator = "userId_seq_generator")
private Long userId;
/* ... getter, setters, ... */
}
and that's the result
Any ideas? Thanks in advance
I don't have point reputation to comment so i'll put here my comments:
Why instalationPK field isn't in instalation.class??
You should put #EmbeddedId in the field instalationPK in Installation.class.
I don't if makes differences, but put joinCollums on the field in BaseEntity:
#OneToOne
#JoinColumns({
#JoinColumn(name = "site", referencedColumnName = "site"),
#JoinColumn(name = "structure", referencedColumnName = "structure")
})
private Installation installation;

Categories