I'm trying to build a search query to find all Test entity data.
Here are my classes...
TestParent.java
#Entity
public class TestParant{
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String createdBy;
#OneToMany(
targetEntity = Channel.class,
cascade = {CascadeType.ALL},
fetch = FetchType.LAZY)
#JoinColumn(name = "test_id")
private List<Channel> channels;
}
Channel.java
#Entity
#Getter
#Setter
#Builder
#AllArgsConstructor
#NoArgsConstructor
public class Channel{
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Enumerated(EnumType.STRING)
private Channel channelName;
#ManyToOne
#JoinColumn(name = "id", referencedColumnName = "id")
#JsonBackReference
private Test test;
#OneToMany(
targetEntity = TvSet.class,
cascade = {CascadeType.ALL},
fetch = FetchType.LAZY)
#JoinColumn(name = "channel_id")
private List<TvSet> tvSets;
}
My specification query...
public Specification<TEST> generateFilterTestQuery(FilterRequest filterRequest) {
log.info("start to build query from" + filterRequest);
return (root, cq, cb) -> {
Predicate p = cb.conjunction();
Join<Channel, Campaign> channel = root.join("channels", JoinType.INNER);
if (!filterRequest.getStartCreatedDate().isEmpty() && !filterRequest.getEndCreatedDate().isEmpty())
p = cb.and(p,
cb.between(root.get(CREATED_DATE),
filterRequest.getStartCreatedDate(), filterRequest.getEndCreatedDate()));
else if (!(filterRequest.getStartCreatedDate().isEmpty()))
p = cb.and(p,
cb.greaterThanOrEqualTo(root.get(CREATED_DATE),
filterRequest.getStartCreatedDate()));
else if (!(filterRequest.getEndCreatedDate().isEmpty()))
p = cb.and(p,
cb.lessThanOrEqualTo(root.get(CREATED_DATE),
filterRequest.getEndCreatedDate()));
if (!filterRequest.getCreatedBy().isEmpty()) {
p = cb.and(p,
cb.equal(root.get("createdBy"), filterRequest.getCreatedBy()));
}
if (!filterRequest.getBrandId().isEmpty()) {
p = cb.and(p,
cb.equal(root.get("brandId"), filterRequest.getBrandId()));
}
if (!filterRequest.getChannel().isEmpty()) {
p = cb.and(p,
cb.equal(channel.get("channelName"), Channel.valueOf(filterRequest.getChannel())));
}
if (filterRequest.getSort().equals(SortEnum.ASC)) {
cq.orderBy(cb.asc(root.get(CREATED_DATE)));
} else {
cq.orderBy(cb.desc(root.get(CREATED_DATE)));
}
return p;
};
}
And my service method...
public Page<TEST> filter(FilterRequest filterRequest) throws BaseException {
try {
log.info("Getting campaign for filterRequest : {} ", filterRequest);
// Find Sorted Creatives By filterRequest
Pageable pageable =
PageRequest.of(filterRequest.getPageNumber(), filterRequest.getPageSize());
return repository.findAll(generateFilterTestQuery(filterRequest),pageable);
} catch (IllegalArgumentException e) {
log.error(e.getMessage());
throw new BaseException(e.getMessage());
}
}
The result I'm getting...
"content": [
{
"id": 516,
"name": "Tes",
"createdBy": "test",
"brandId": "1",
"createdDate": 1671529546,
"channels": [
{
"id": 312,
"channelName": "TV1",
"channelStatus": "DONE",
"tvSet": [
{
"id": 312,
"locations": [
{
"id": 302,
"isGeoLocation": true,
"cities": [
{
"id": 282,
"distanceUnit": "kilometer",
},
{
"id": 283,
"distanceUnit": "kilometer",
}
],
}
But I want to get results(channels ) that without getting tvSet array like in below
"content": [
{
"id": 516,
"name": "Tes",
"createdBy": "test",
"brandId": "1",
"createdDate": 1671529546,
"channels": [
{
"id": 312,
"channelName": "TV1",
"channelStatus": "DONE",
"tvSet": [],
}
Can someone please help me to resolve this issue?? Thank you!!
Related
I want the Employee object to only display the id property when adding a CV. When I put #JsonIgnore on the employee object in the CV, the id doesn't come either. How can I hide property that I do not want to appear in employee class (password, national identity) on the CV class?
Cv Class :
#Entity
#Table(name = "cvs")
#Data
#AllArgsConstructor
#NoArgsConstructor
public class CV {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
#OneToOne
#JoinColumn(name = "employee_id")
private Employee employee;
#OneToMany(mappedBy = "cv", cascade = CascadeType.ALL, orphanRemoval = true)
List<Education> educations;
#OneToMany(mappedBy = "cv", cascade = CascadeType.ALL, orphanRemoval = true)
List<Work> works;
#OneToMany(mappedBy = "cv", cascade = CascadeType.ALL, orphanRemoval = true)
List<Languege> langueges;
#OneToMany(mappedBy = "cv", cascade = CascadeType.ALL, orphanRemoval = true)
List<Technology> technologies;
#Column(name = "github")
private String github;
#Column(name = "linkedin")
private String linkedin;
#NotNull
#NotBlank
#Column(name = "cover_letter")
private String coverLetter;
#Column(name = "photo")
private String photo;
}
Employee Class :
#Data
#AllArgsConstructor
#NoArgsConstructor
#Table(name = "employees")
#Entity
#PrimaryKeyJoinColumn(name = "user_id", referencedColumnName = "id")
public class Employee extends User {
#NotNull
#NotBlank
#Column(name = "first_name", length = 50)
private String firstName;
#NotNull
#NotBlank
#Column(name = "last_name", length = 50)
private String lastName;
#NotNull
#NotBlank
#Column(name = "national_identity", length = 11)
private String nationalIdentity;
#NotNull
#Column(name = "year_of_birth")
private int yearOfBirth;
#JsonIgnore
#OneToOne(mappedBy = "employee")
private CV cv;
}
I read data this format;
{
"id": 0,
"employee": {
"id": 0, //visible
"email": "string", //not visible
"password": "string", //not visible
"firstName": "string",
"lastName": "string",
"nationalIdentity": "string", //not visible
"yearOfBirth": 0 //not visible
},
"educations": [
{
"id": 0,
"schoolName": "string",
"department": "string",
"startingDate": "2022-02-11",
"graduationDate": "2022-02-11"
}
],
"works": [
{
"id": 0,
"workplace": "string",
"job": {
"id": 0,
"jobName": "string"
},
"startingDate": "2022-02-11",
"endDate": "2022-02-11"
}
],
"langueges": [
{
"id": 0,
"languege": "string",
"level": 0
}
],
"technologies": [
{
"id": 0,
"technology": "string"
}
],
"github": "string",
"linkedin": "string",
"coverLetter": "string",
"photo": "string"
}
You can use a custom serializer that you would use on your CV employee field : #JsonSerialize(using = CustomEmployeeSerializer.class)
public class CustomEmployeeSerializer extends SerializerBase<Employee> {
public CustomEmployeeSerializer() {
super(Employee.class, true);
}
#Override
public void serialize(Employee employee, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonProcessingException {
jgen.writeString(employee.getId());
}
I have created a many to many relationship. It is returning the data correctly. However, I noticed that if the data exist in canUse section of the json and has been called before by another Player, it does not print the data again only the new values are printed.
JOSN
[
{
"id": 12,
"firstname": "asdfghjkl ",
"surname": "asda",
"canUse": [
{
"id": 0,
"techniqueName": "JAVA"
},
{
"id": 1,
"techniqueName": "PHP"
},
{
"id": 2,
"techniqueName": "PYTHON"
}
]
},
{
"id": 49,
"firstname": "asc",
"surname": "as",
"canUse": []
},
{
"id": 90,
"firstname": "LOL",
"surname": "LOL",
"canUse": []
}*,
{
"id": 91,
"firstname": "Kareem",
"surname": "LOL",
"canUse": [
1,
2,
{
"id": 3,
"techniqueName": "HASKELL"
}
]
},*
{
"id": 92,
"firstname": "Omar",
"surname": "LOL",
"canUse": []
}
]
Player entity
#Entity
#Table(name = "players")
#EntityListeners(AuditingEntityListener.class)
#JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id")
public class Players {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="player_id")
private int id;
private String firstname;
private String surname;
#ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinTable(
name = "able_to_use",
joinColumns = {#JoinColumn(name = "player_id", referencedColumnName = "player_id")},
inverseJoinColumns = {#JoinColumn(name = "technique_id", referencedColumnName = "id")}
)
private List<Technique> canUse;
//Getters and Setters
Technique entity
#Entity
#Table(name = "technique")
#EntityListeners(AuditingEntityListener.class)
#JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id")
public class Technique {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#Column(name = "technique_name")
private String techniqueName;
#JsonIgnore
#ManyToMany(mappedBy = "canUse", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private List<Players> ableToUse;
//Getters and Setters
Thank you in advance, the problem is occurring for player with ID 91. this player should also print PHP and PYTHON but only the ID is printed.
I have json like as shown below which comes from a third party service which I gets it through open feign client. I am trying to save these details into my MySQL database using Spring JPA2.
[
{
"request_id": 111,
"name": "ABC",
"groups": [
{
"id": 21,
"group": "grp_A"
},
{
"id": 22,
"group": "grp_B"
}
]
},
{
"request_id": 222,
"name": "ABC",
"groups": [
{
"id": 23,
"group": "grp_C"
}
]
},
{
"request_id": 333,
"name": "ABC",
"groups": [
{
"id": 24,
"group": "grp_A"
}
]
},
{
"request_id": 444,
"name": "ABC",
"groups": [
{
"id": 25,
"group": "grp_C"
}
]
},
{
"request_id": 555,
"name": "ABC",
"groups": []
}
]
I have wrote the mappings for the above json like as shown blow
Requests.java
#Entity
#Table(name = "requests")
#JsonIgnoreProperties(ignoreUnknown = true)
public class Requests {
#Id
#Column(name = "request_id")
private String id;
#Column(name = "name")
private String name;
#OneToMany(mappedBy = "id", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Set<Groups> groups = Sets.newHashSet();
// getters and setters
}
Groups.java
#Entity
#Table(name = "groups")
#JsonIgnoreProperties(ignoreUnknown = true)
public class Groups{
#Id
#Column(name = "id")
private String id;
#Column(name = "group")
private String group;
#ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinColumn(name = "request_id")
private Requests requests;
// getters and setters
}
now within my service class I have done like as shown below
List<Requests> allRequests = requestFeignClient.getRequests();
requestRepository.saveAll(allRequests);
all details are saved into the database except the request_id like as shown below. My Expected group table is also shown below
Can anyone please tell me why the request_id is not getting saved.
Try replacing this:
#OneToMany(mappedBy = "id", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
With this:
#OneToMany(mappedBy = "requests", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
I have problem getting only ID from objects that are in nested collection in Hibernate.
Here is my code:
public class Company {
private int id;
private Set<Account> owners = new HashSet<Account>();
#Id
public int getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
#ManyToMany(cascade = CascadeType.MERGE, fetch = FetchType.LAZY, targetEntity = Account.class)
#Fetch(org.hibernate.annotations.FetchMode.JOIN)
#JoinTable(
name = "company_accountOwners",
joinColumns = #JoinColumn(name = "company_id", referencedColumnName = "id"),
inverseJoinColumns = #JoinColumn(name = "account_id", referencedColumnName = "id")
)
public Set<Account> getOwners() {
return owners;
}
public void setOwners(Set<Account> owners) {
this.owners = owners;
}
Account.class
public class Account {
private String id;
private String name;
private int age;
#Id
#GeneratedValue(generator = "uuid2")
#GenericGenerator(name = "uuid2", strategy = "uuid2")
#Column(columnDefinition = "VARCHAR(36)")
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
How only get JSON with all Company.class data and array of owners (Account.class) that has only ID, not all other attributes (name, age)?
I'm in complete dark.
Json i get now:
{
"id": 1,
"owners": [
{
"id": "testID",
"name": "name",
"age": 45
},
{
"id": "testID2",
"name": "name2",
"age": 90
}]
}
I want json like:
{
"id": 1,
"owners": [
{
"id": "testID"
},
{
"id": "testID2"
}]
}
I have 2 tables email_address and group_email
I want to get a list of email addresses and if it is group also list the emails of group. Here is my hibernate dom object:
#Entity
#Table(name = "email_address")
public class EmailAddressDom {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "email_address_id_seq")
#SequenceGenerator(name = "email_address_id_seq", sequenceName = "email_address_id_seq")
private int id;
#Column(name = "name")
private String name;
#Column(name = "email")
private String email;
#Column(name = "is_group")
private boolean isGroup;
#Column(name = "status")
private boolean status;
// Getters and setters
And here is the implementation how I am getting the list
public List<EmailAddressDom> getEmailAddresses() {
Session session = getCurrentSession();
Criteria criteria = session.createCriteria(EmailAddressDom.class);
List<EmailAddressDom> emailAddresses = criteria.list();
return emailAddresses;
}
And the result is
[
{
"id": 451,
"name": "HS",
"isGroup": true,
"status": true
},
{
"id": 452,
"name": "test4",
"email": "test4#mail.com",
"isGroup": false,
"status": true
},
{
"id": 450,
"name": "test3",
"email": "test3#mail.com",
"isGroup": false,
"status": true
},
{
"id": 402,
"name": "test2",
"email": "test2#mail.com",
"isGroup": false,
"status": true
},
{
"id": 401,
"name": "test1",
"email": "test1#mail.com",
"isGroup": false,
"status": true
}
]
I want to get result like this
[
{
"id":451,
"name":"HS",
"isGroup":true,
"status":true,
"groupEmails":[
{
"id":450,
"name":"test3",
"email":"test3#mail.com",
"isGroup":false,
"status":true
},
{
"id":452,
"name":"test4",
"email":"test4#mail.com",
"isGroup":false,
"status":true
}
]
},
{
"id":402,
"name":"test2",
"email":"test2#mail.com",
"isGroup":false,
"status":true
}
]
Which mapping should I use in EmailAddressDom entity?
Updated accordingly to comments
I have written a simple application mapping following way and it is working fine
#ManyToMany(fetch= FetchType.EAGER, cascade={CascadeType.ALL})
#JoinTable(name="group_email",
joinColumns={#JoinColumn(name="group_id")},
inverseJoinColumns={#JoinColumn(name="email_addr_id")})
private List<EmailAddressDom> groupEmails;
But I have confused setting it in my web application, it throws following exception:
Association has already been visited: AssociationKey(table=group_email, columns={email_addr_id})
What can be the reason?
Either Do Eager loading
#OneToMany(fetch = FetchType.EAGER)
#JoinTable(name = "group_email",
joinColumns = #JoinColumn(name = "email_addr_id", referencedColumnName = "id"),
inverseJoinColumns=#JoinColumn(name="group_id", referencedColumnName="id" ))
private List<EmailAddressDom> emailAddressDoms;
OR
//explicitly join in criteria
public List<EmailAddressDom> getEmailAddresses() {
Session session = getCurrentSession();
Criteria criteria = session.createCriteria(EmailAddressDom.class);
criteria.setFetchMode("emailAddressDoms", fetchMode.JOIN);
List<EmailAddressDom> emailAddresses = criteria.list();
return emailAddresses;
}
To achieve self join, in your EmailAddressDom class add reference to itself like:
#OneToMany(fetch = FetchType.LAZY)
#JoinTable(name = "group_email",
joinColumns = #JoinColumn(name = "email_addr_id", referencedColumnName = "id"),
inverseJoinColumns=#JoinColumn(name="group_id", referencedColumnName="id" ))
private List<EmailAddressDom> emailAddressDoms;
In group_email table you do not require id column as email_addr_id and group_id combination would be unique or do you allow same email more than once in a group?
Update after comment from OP:
To group by email groups, change the mapping like shown below.
#ManyToOne(fetch = FetchType.LAZY)
#JoinTable(name = "group_email",
joinColumns = #JoinColumn(name="group_id", referencedColumnName="id" ),
inverseJoinColumns=#JoinColumn(name = "email_addr_id", referencedColumnName = "id"))
private List<EmailAddressDom> emailAddressDoms;