File in Database Object POJO (Springboot) - java

Say I have a SQL DO named "Team" that has a name, description, id, and profile picture.
It would look something like this:
#Entity
#Table(name = "Team")
public class TeamDO implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="team_id")
private Long id;
private String description;
private String name;
#ManyToOne(fetch=FetchType.EAGER)
#JoinColumn(name="user_id", nullable = false)
private Users users;
public TeamDO() {}
public TeamDO(Users user) {
this.setUsers(user);
}
#Override
public String toString() {
return String.format(
"TeamDO[id=%d, inital='%s', description='%s', name='%s']"
, getId()
, getUsers().getInitialName()
, getDescription()
, getName()
);
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Users getUsers() {
return users;
}
public void setUsers(Users users) {
this.users = users;
}
}
What kind of variable stores a file such as a jpg? Or would my POJO have a String profilePictureURL which would be used to fetch the image (logo) for each team?

It's preferred to store the file in a hosting service of some sort and save only the URL in the DB but you can also save it as a byte array.

Related

JSON deserializer returns "null" for Collection type in REST api #RequestBody

I Have a rest controller that is not de-serializing the array type in json..
#PostMapping()
#ResponseBody
public ResponseEntity<Team> createteam(#RequestBody Team team) throws JsonProcessingException {
Team savedTeam = teamService.createTeam(team);
return new ResponseEntity<Team>(savedTeam, HttpStatus.CREATED);
}
below is my entity class.
#Entity
#JsonIdentityInfo(generator = IntSequenceGenerator.class)
public class Team {
#Id
#GeneratedValue
private Long id;
private String name;
#OneToMany(mappedBy = "team", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private List<Developer> developers;
public Team(String name, List<Developer> developer) {
super();
this.name = name;
this.developers = developer;
}
public Team() {
super();
}
public List<Developer> getDeveloper() {
return developers;
}
public void setDeveloper(List<Developer> developer) {
this.developers = developer;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
and my other entity..
package com.demo.springbootdemo.entity;
#Entity
#JsonIdentityInfo(generator = IntSequenceGenerator.class)
public class Developer {
#Id
#GeneratedValue
private Long id;
#ManyToOne
private Team team;
private Long phone;
private String name;
public Developer() {
super();
}
public Developer(Team team, Long phone, String name) {
super();
this.team = team;
this.phone = phone;
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Team getTeam() {
return team;
}
public void setTeam(Team team) {
this.team = team;
}
public Long getPhone() {
return phone;
}
public void setPhone(Long phone) {
this.phone = phone;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
below is my JSON payload, which returns null "developers" when i call the post method.i have tried changing the number of properties in json payload but, still i am not able to figure out why my json is not de-serilaized to List of developers..
{
"id": 1004,
"name": "claim",
"developers": [
{
"id" :1,
"phone": 9092123,
"name": "raina"
}
]
}
I am not sure what Deserializer are you using, but with the Jackson ObjectMapper I solved it changing the method names of the getter and setter for the developers properties: they should be called setDevelopers and getDevelopers. In your code they are called setDeveloper and getDeveloper, without the final S.
To avoid problem like these, I just add Lombok as a dependency and it takes care of creating setters and getters.
With Lombok your Team class would look like this:
// ... more imports here...
import lombok.Data;
#Data
#JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class)
public class Team {
#Id
#GeneratedValue
private Long id;
private String name;
#OneToMany(mappedBy = "team", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private List<Developer> developers;
}
You may need to add more Lombok annotations for generating constructor methods according to your needs.

Java multiple join query

I am trying to create a REST service in Java with Spring Boot.
I have 2 tables Topic and Course and i want to retrieve NAME and DESCRIPTION from Topic and PRICE from Course.
The connection between these 2 tables is made with TOPIC_ID from Course.
Result MUST be a JSON.
[
{
"id": "course1",
"name": "name course1",
"description": "course1"
},
{
"id": "course2",
"name": "course2 name",
"description": "course2"
},
{
"id": "course3",
"name": "course3 name",
"description": "course3"
}
]
The query is below.
I know it's possible with DTO and JPA but I need to write a lot of code for a simple database query.
Thank you.
package com.example.course;
import com.example.topic.Topic;
import javax.persistence.*;
#Entity
#Table(name = "topic", schema = "topic")
public class Topic {
#Id
private String id;
private String name;
private String description;
public Topic() {
}
public Topic(String id, String name, String description) {
this.id = id;
this.name = name;
this.description = description;
}
public String getDescription() {
return description;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setDescription(String description) {
this.description = description;
}
}
package com.example.topic;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "course", schema = "topic")
public class Course {
#Id
#Column(name = "ID")
private String id;
#Column(name = "NAME")
private String name;
#Column(name = "DESCRIPTION")
private String description;
#Column(name="PRICE")
private Integer price;
#ManyToOne
#JoinColumn(name="TOPIC_ID", nullable=false)
private Topic topic;
public Course() {
}
public Course(String id, String name, String description, String topicId) {
this.id = id;
this.name = name;
this.description = description;
this.topic = new Topic(topicId, "", "");
}
public String getDescription() {
return description;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setDescription(String description) {
this.description = description;
}
public Topic getTopic() {
return topic;
}
public void setTopic(Topic topic) {
this.topic = topic;
}
public void setPrice(Integer price) { this.price = price; }
public Integer getPrice() { return price; }
}
package com.example.dto;
public class TopicDescDTO {
private String id;
private String name;
private String description;
public TopicDescDTO(String id, String name, String description) {
this.id = id;
this.name = name;
this.description = description;
}
public TopicDescDTO() {
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
select t.name, t.description, c.price as course_price
from topic.course c
inner join topic.topic t on t.id = c.topic_id
Take advantage of the projection interface offered by Spring Data JPA:
public interface TopicDescDTO{
Integer getPrice();
String getName();
String getDescription();
}
and then just land a proper method in one of your repositories:
#Query(select t.name, t.description, c.price
from Course c
inner join c.topic t)
List<TopicDescDTO> getTopicDescs();
Spring will do the mapping for you.

Cannot delete resource in Spring Hateoas

I have a spring boot application which exposes resources using Spring HATEOAS. All the method GET, POST, PATCH works fine except DELETE. When I send a delete request to a resource, it returns 204 No content response but when I request for all resource, the item which I deleted appears again. No exception is logged on the console. No error in postman request.
The resource I am trying to delete is having many-to-one association with another POJO. But those resources which doesn't have many-to-one(some have one-to-many) is getting deleted.
The Mode Entity
#Entity
#Table(name="Modes")
public class Mode {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name;
#OneToMany(mappedBy = "mode", fetch=FetchType.EAGER, cascade = CascadeType.ALL)
private Set<Expense> expense;
public Mode() {}
#Autowired
public Mode(String name,Set<Expense> expense) {
this.name = name;
this.expense = expense;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
The Category Entity
#Entity
#Table(name="Categories")
public class Category {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name;
#OneToMany(mappedBy = "category", fetch=FetchType.EAGER, cascade = CascadeType.ALL)
private Set<Expense> expense;
public Category() { }
#Autowired
public Category(String name, Set<Expense> expense) {
this.setName(name);
this.expense = expense;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
The Expense Entity
#Entity
#Table(name="Expenses")
public class Expense {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name;
private BigDecimal amount;
#ManyToOne
#JoinColumn(name="categoryId")
private Category category;
#ManyToOne
#JoinColumn(name="modeId")
private Mode mode;
private Date date;
public Expense() {}
public Expense(String name, BigDecimal amount, Category category, Mode mode, Date date) {
this.name = name;
this.amount = amount;
this.category = category;
this.mode = mode;
this.date = date;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public BigDecimal getAmount() {
return amount;
}
public void setAmount(BigDecimal amount) {
this.amount = amount;
}
public Category getCategory() {
return category;
}
public void setCategory(Category category) {
this.category = category;
}
public Mode getMode() {
return mode;
}
public void setMode(Mode mode) {
this.mode = mode;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
}
The repositories I used
public interface CategoryRepository extends CrudRepository<Category, Integer> {
}
public interface ExpenseRepository extends CrudRepository<Expense, Integer> {
}
public interface ModeRepository extends CrudRepository<Mode, Integer> {
}
The delete request for Expense is not working
I use MySQL as database and use Postman to test the URL
Try Changing from the cascade cascade = CascadeType.ALL)
and set cascade = CascadeType.REMOVE, orphanRemoval = true it should work
Read the docs for more information:
https://docs.oracle.com/cd/E19798-01/821-1841/giqxy/

Trouble with one to many relationship hibernate

hello i'm trying to learn one to many mapping but i really having trouble with hibernate. I was able to persist to database but when trying to apply one to many relationship it doesn't persist to DB and also doesn't display the relationship when viewing the response body in postman. I really need help been on this problem since yesterday morning. I have looked on tutorials on youtube and on internet but every tutorial seem basic and when applying same idea no success. I have an entity person and another entity organization. A person can belong up to one organization but different persons can belong to the same organization. So my approach was using a one to many relationship.
Below is my entity of Organization:
#Entity
#Table(name="organization")
public class Organization {
#Id
#Column(name="org_Id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String name, description;
#OneToMany(/*fetch = FetchType.EAGER, cascade = CascadeType.ALL*/)
#JoinTable(joinColumns = #JoinColumn(name="org_Id"),
inverseJoinColumns = #JoinColumn(name="person_Id"))
// #JsonIgnore
//#JoinColumn(name="org_Id")
private Collection<Person> personCollection = new ArrayList<Person>();
public Collection<Person> getPersonCollection() {
return personCollection;
}
public void setPersonCollection(Collection<Person> personCollection) {
this.personCollection = personCollection;
}
private Address address;
public Organization() {}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
}
And below is my Person entity:#Entity
#Table(name = "Person")
public class Person {
#Id
#Column(name="person_Id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column(name="Email",unique = true)
private String email;
#Column(name="FirstName")
private String first_name;
#Column(name="LastName")
private String last_name;
#Column(name="Description")
private String description;
//#Embedded
private Address address;
#ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JsonIgnore
private Organization organization;
public Organization getOrganization() {
return organization;
}
public void setOrganization(Organization organization) {
this.organization = organization;
}
public Person() {}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getFirst_name() {
return first_name;
}
public void setFirst_name(String first_name) {
this.first_name = first_name;
}
public String getLast_name() {
return last_name;
}
public void setLast_name(String last_name) {
this.last_name = last_name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
when trying to create person. Below is my create method:
public Person createPerson(String f_name, String l_name, String email, String city, String state,
String zipCode, String street, String description, Long id) {
Person person = null;
//f_name, l_name, email are required parameters if empty return null and throws an exception..
if(f_name.isEmpty() || l_name.isEmpty() || email.isEmpty()) {
return person;
}
else {
Session session = null;
Transaction transaction = null;
try {
session = sessionFactory.openSession();
transaction = session.beginTransaction();
person = new Person();
person.setFirst_name(f_name);
person.setLast_name(l_name);
person.setEmail(email);
person.setDescription(description);
Address address = new Address();
address.setStreet(street);
address.setZipCode(zipCode);
address.setState(state);
address.setCity(city);
person.setAddress(address);
/* checks to see if id of organization exist if so add to list if not don't do anything.*/
if(id!=null) {
Organization organization = session.get(Organization.class, id);
if (organization != null) {
/* adds id of organization to person table and vice versa.*/
person.setOrganization(organization);
organization.getPersonCollection().add(person);
} else {
//do nothing
}
}
session.save(person);
transaction.commit();
} catch (HibernateException ex) {
if (transaction != null)
transaction.rollback();
ex.printStackTrace();
} finally {
if (session != null)
session.close();
}
return person;
}
}
I am able to create both person and organization and persist to database. But when i try to add an organization to a person Row in database i cannot add the relationship(verified when i tried looking up database itself) and also no response as i get a lazy initialization collection error as well. Please has anyone encountered this problem
I just executed the code snippet you gave in hibernate with the following simplified structure which works perfectly fine. You should start from here and modify as per your needs.
Entity
#Table(name="organization")
public class Organization {
#Id
#Column(name="org_Id")
private long id;
private String name, description;
#OneToMany(cascade = CascadeType.ALL)
private Collection<Person> personCollection = new ArrayList<Person>();
public Collection<Person> getPersonCollection() {
return personCollection;
}
public void setPersonCollection(Collection<Person> personCollection) {
this.personCollection = personCollection;
}
public Organization() {}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
and
#Entity
#Table(name = "Person")
public class Person {
#Id
#Column(name="person_Id")
private long id;
#Column(name="Email",unique = true)
private String email;
#Column(name="FirstName")
private String first_name;
#Column(name="LastName")
private String last_name;
#Column(name="Description")
private String description;
#ManyToOne()
private Organization organization;
public Organization getOrganization() {
return organization;
}
public void setOrganization(Organization organization) {
this.organization = organization;
}
public Person() {}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getFirst_name() {
return first_name;
}
public void setFirst_name(String first_name) {
this.first_name = first_name;
}
public String getLast_name() {
return last_name;
}
public void setLast_name(String last_name) {
this.last_name = last_name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
EDIT : The CascadeType.ALL from Person side of the relationship has been moved to the Organization side of the relationship.Because you want when organization is deleted Person should also get deleted, but not the other way round.

hibernate.hbm2ddl.auto=update don't work

I have model. there is this part:
model was mapped by jpa annotations.Everywhere I use fetchType = EAGER. If I load vacancy from database, I have 2 duplicates status_for_vacancy objects.
I use property hbm2ddl.auto = update.
If I make new schema of database and fill data, I haven't duplicates status_for_vacancy objects.
It really?
code:
vacancy:
#Entity
#Table(name = "vacancy")
#XmlRootElement(name="vacancy")
public class Vacancy {
private List<VacancyStatus> statusList = new LinkedList<VacancyStatus>();
#OneToMany(mappedBy = "vacancy", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
public List<VacancyStatus> getStatusList() {
return statusList;
}
public void setStatusList(List<VacancyStatus> statusList) {
this.statusList = statusList;
}
}
status_for_vacancy:
#Entity
#Table(name = "status_for_vacancy")
public class StatusForVacancy extends AbstractStatus {
public StatusForVacancy() {
super();
}
public StatusForVacancy(Integer id, String name) {
super(id, name);
}
}
#MappedSuperclass
#XmlRootElement
public abstract class AbstractStatus {
private Integer id;
private String name;
public AbstractStatus() {
super();
}
public AbstractStatus(String name) {
super();
this.name = name;
}
public AbstractStatus(Integer id, String name) {
super();
this.id = id;
this.name = name;
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column (name ="id")
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
#Column(name = "name")
#NotEmpty
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
vacancy_status:
#Entity
#Table(name = "vacancy_status")
public class VacancyStatus extends AbstractHistoryStatus {
private Vacancy vacancy;
private StatusForVacancy status;
public VacancyStatus() {
super();
}
public VacancyStatus(Integer id, User author, Date date,
Vacancy vacancy, StatusForVacancy status) {
super(id, author, date);
this.vacancy = vacancy;
this.status = status;
}
#ManyToOne
#JoinColumn(name = "vacancy_id")
public Vacancy getVacancy() {
return vacancy;
}
public void setVacancy(Vacancy vacancy) {
this.vacancy = vacancy;
}
#ManyToOne
#JoinColumn(name = "status_id")
public StatusForVacancy getStatus() {
return status;
}
public void setStatus(StatusForVacancy status) {
this.status = status;
}
}
#MappedSuperclass
public abstract class AbstractHistoryStatus {
private Integer id;
private User author;
private Date date;
public AbstractHistoryStatus() {
}
public AbstractHistoryStatus(Integer id, User author, Date date) {
super();
this.id = id;
this.author = author;
this.date = date;
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
#ManyToOne
public User getAuthor() {
return author;
}
public void setAuthor(User author) {
this.author = author;
}
#Column(name="creation_date")
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
}
It is all mapping code for these entities.
in debugger:
both id==500 ==> hibernate understand, that it is same objects.
I try add all data from old database to new database - I get old error(
I fix cause of appearance of this problem. It appearances if I add record to note table:
I highly recommend you write equals() and hashCode() methods. The standard equals()/hashCode() implement referential equality (do 2 objects reference the same memory location). So if hibernate has 2 of the 'same' object in memory, but they don't reference the same memory location then you will see the object show up twice. But if you implement equals() based on primary key being equal, then even if there are two copies of the same object in memory, Hibernate won't give you duplicates.
See the JPA spec:
2.4 Primary Keys and Entity Identity
Every entity must have a primary key. ... The value of its primary key
uniquely identifies an entity instance within a persistence context
and to EntityManager operations
Also see this SO post.

Categories

Resources