I am playing with Spring JPA, and not able to achieve below:
#Entity
#Table(name = "User")
public class User implements Serializable {
#Column
private String name;
#OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
private Address address;
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 Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
protected long id;
private final static long serialVersionUID = 1L;
}
#Entity
#Table(name = "Location")
public class Location implements Serializable {
#Column
private String address;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
protected long id;
private final static long serialVersionUID = 1L;
}
I have repositories for each domain model.
I want to get 'Address' by name such as 'findAddressByName()'. I have tried various different thing but always get User back. Can I get Address ? Is there a way to do ? Or that is how domain model specific works by default.
Related
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.
I'm learning Spring Framework, i followed some tutorials of relationship 1-1, so i defined my models: One Library have one Address.
I send in my body request the library data and the id from the address, the spring create the record, but he can't do the relationship, returning address null and when i make a select in database, the address_id is not saving in the table library
This is what i tried:
My model Library:
#Entity
#Table(name = "Bibliotecas")
public class Library implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String name;
#OneToOne
#JoinColumn(name = "address_id", referencedColumnName = "id")
private Address address;
public Library() {
}
public long getId() {
return this.id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return this.address;
}
public void setAddress(Address address) {
this.address = address;
}
}
My model Address:
#Entity
public class Address {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column(nullable = false)
private String location;
public long getId() {
return this.id;
}
public void setId(long id) {
this.id = id;
}
public String getLocation() {
return this.location;
}
public void setLocation(String location) {
this.location = location;
}
#OneToOne(mappedBy = "address", fetch = FetchType.LAZY, optional = false)
private Library library;
}
My repositories:
public interface LibraryRepository extends JpaRepository<Library, Long> {}
public interface AddressRepository extends JpaRepository<Address, Long> {}
My library resource:
#RestController
#RequestMapping(value = "/api")
public class LibraryResource {
#Autowired
LibraryRepository libraryRepository;
#GetMapping("/libraries")
public List<Library> listaBibliotecas() {
return libraryRepository.findAll();
}
#PostMapping("/library")
public Library salvaBiblioteca(#RequestBody Library library) {
return libraryRepository.save(library);
}
}
I do this request in Postman:
{
"name": "library test",
"address_id": 1
}
Obs: i have one address with id 1 in database, but i receive:
{
"id": 5,
"name": "Biblioteca test",
"address": null
}
Why i'm receiving null in my return? And why my register is not saving the address_id?
Please consider the following:
You switched the mapping between address & library
Better to user Hibernate annotations on public fields
Address -> Library getter & setter not implemented
Address entity missing the #table annotation
This must work for you:
Library:
#Entity
#Table(name = "library")
public class Library implements Serializable {
private static final long serialVersionUID = 1L;
private long id;
private String name;
private Address address;
public Library() {
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
public long getId() {
return this.id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
#OneToOne(mappedBy = "library", cascade = CascadeType.ALL, fetch = FetchType.LAZY, optional = false)
public Address getAddress() {
return this.address;
}
public void setAddress(Address address) {
this.address = address;
}
}
Address:
#Entity
#Table(name = "address")
public class Address {
private long id;
private String location;
private Library library;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
public long getId() {
return this.id;
}
public void setId(long id) {
this.id = id;
}
#Column(nullable = false)
public String getLocation() {
return this.location;
}
public void setLocation(String location) {
this.location = location;
}
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "id")
public Library getLibrary() {
return library;
}
public void setLibrary(Library library) {
this.library = library;
}
}
Better never expose your repositories to controller, you should instead reference a service that has access to repositoryDao.
Use same entity name as table name is better approach.
I have the following scenario:
I have a Student class and students table.
I have Course class and courses table.
Every student and course have unique ID.
I would like to put a List into the Student class which is mapped by courses IDs.
I have tried a lot of annotations and relations but nothing succeeded
#Entity
#Table(name = "courses")
public class Course {
private long id;
private String name;
public Course() {
}
public Course(String name, int size) {
this.name = name;
this.size = size;
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
#Column(name = "name", nullable = false)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
#Entity
#Table(name = "students")
public class Student {
private long id;
private String name;
#OneToMany(cascade = CascadeType.ALL)
private List<Course> courses = new ArrayList<>();
public Student() {
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
#Column(name = "name", nullable = false)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Course> getCourses() {
return courses;
}
public void setCourses(List<Course> courses) {
this.courses = courses;
}
}
Can you help me hot to achieve that because i am a little newbie into the spring
Use the following when declaring one to many relation
#Column(name="course_id")
private Set<Course> courses;
You need to use OneToMany annotation.
#OneToMany(mappedBy = "students", cascade = CascadeType.ALL)
private List<Course> courses;
You need to give your list a type. For instance
List<Courses> courseList = new ArrayList<>();
I have hibernate #OneToMany mapping I am getting the mentioned error. Does not understand the reason. As getters and setters are public
Below are the entities
#Entity
#Table(name="USER_DETAILS")
public class User implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#Column(name="USER_ID")
#GeneratedValue(strategy=GenerationType.AUTO)
private int id;
#Column(name="USER_FIRSTNAME",nullable=false, length=50)
private String userFirstName;
#Column(name="USER_LASTNAME",nullable=false, length=50)
private String userLastName;
#Column(name="USER_MIDDLENAME",length = 30)
private String userMiddleName;
#Column(name="USER_AGE")
private int userAge;
#Column(name="USER_SEX")
private String userSex;
#OneToMany(cascade=CascadeType.ALL, mappedBy="userAddress", targetEntity=Address.class)
private Set<Address> address = new HashSet<Address>();
public String getUserFirstName() {
return userFirstName;
}
public void setUserFirstName(String userFirstName) {
this.userFirstName = userFirstName;
}
public String getUserLastName() {
return userLastName;
}
public void setUserLastName(String userLastName) {
this.userLastName = userLastName;
}
public String getUserMiddleName() {
return userMiddleName;
}
public void setUserMiddleName(String userMiddleName) {
this.userMiddleName = userMiddleName;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getUserAge() {
return userAge;
}
public void setUserAge(int userAge) {
this.userAge = userAge;
}
public String getUserSex() {
return userSex;
}
public void setUserSex(String userSex) {
this.userSex = userSex;
}
public Set<Address> getAddress() {
return address;
}
public void setAddress(Set<Address> address) {
this.address = address;
}
}
#Entity
#Table(name = "ADDRESS")
public class Address implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#Column(name = "ADDRESS_ID")
#GeneratedValue(strategy=GenerationType.AUTO)
private int id;
#Column(name = "ZIP_CODE")
private String zipCode;
#Column(name="ADDRESS_USER_ID", insertable=false, updatable=false)
private Long addressUserID;
#Column(name = "ADDRESS_SEC")
private String addressSec;
#Column(name = "STREET")
private String street;
#Column(name = "CITY")
private String city;
#Column(name = "COUNTRY")
private String country;
#ManyToOne(cascade=CascadeType.ALL, targetEntity=User.class)
#JoinColumn(name="ADDRESS_USER_ID")
private Set<User> userAddress = new HashSet<User>();
public Long getAddressUserID() {
return addressUserID;
}
public void setAddressUserID(Long addressUserID) {
this.addressUserID = addressUserID;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getZipCode() {
return zipCode;
}
public void setZipCode(String zipCode) {
this.zipCode = zipCode;
}
public Set<User> getUserAddress() {
return userAddress;
}
public void setUserAddress(Set<User> userAddress) {
this.userAddress = userAddress;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getAddressSec() {
return addressSec;
}
public void setAddressSec(String addressSec) {
this.addressSec = addressSec;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
}
Part of Stack Trace are:
Exception in thread "main" org.hibernate.PropertyAccessException: could not get a field value by reflection getter of com.java.hibernate.practise.User.id at... org.hibernate.property.DirectPropertyAccessor$DirectGetter.get(DirectPropertyAccessor.java:62)
Caused by: java.lang.IllegalArgumentException: Can not set int field com.java.hibernate.practise.User.id to java.util.HashSet...
I am generating the schema using hibernate.hbm2ddl.auto= cerate-drop
Please guide on this.
Generally when we use 1..n bidirectional entity mapping, the owning side which is in general, the many side, should have only a single instance reference to the one side object (not a collection - that would be many to many), and the join column to use is the primary key from the on side class. We don't need to explicitly use the FK column in the many side like you are.
So if this is your relationship User [1]..[N] Address, then you should have something more like
public class User {
...
#OneToMany(mappedBy = "user", cascade=CascadeType.ALL)
private Set<Address> addresses;
}
public class Address {
// private Long addressUserID; // Don't need this property. We get it below
...
#ManyToOne
#JoinColumn(name = "USER_ID")
private User user;
}
I use Hibernate and
have two entities(City and Region) with OneToMany relation.
the First:
#Entity
#Table(name = "p_region")
public class Region implements Serializable{
#OneToMany(mappedBy = "region",fetch= FetchType.LAZY, cascade = CascadeType.MERGE)
private List<City> citys;
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
//++++++++++++++++++++ GETSET
public List<City> getCitys() {
return citys;
}
public void setCitys(List<City> citys) {
this.citys = citys;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
and the second one:
#Entity
#Table(name = "p_city")
public class City implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#NotEmpty(message = "Название не должно быть пустым")
#Length(max = 10, min = 2, message = "Название должно быть менее 2 символов и не
более 100")
private String cityName;
#NotEmpty(message = "Код города не должно быть пустым")
private String cityCode;
#Column(name = "zone")
private Integer zone;
#Basic(optional = true)
#Temporal(javax.persistence.TemporalType.TIMESTAMP)
private Date entryDate = Calendar.getInstance().getTime();
#ManyToOne()
private Region region;
#Basic(optional = true)
private String zip_code;
// GET SET ::::::::::::::::::::::::::::::::::
public Integer getZone() {
return zone;
}
public void setZone(Integer zone) {
this.zone = zone;
}
public Region getRegion() {
return region;
}
public void setRegion(Region region) {
this.region = region;
}
public void delete() {
System.out.println("QQQQQQQQQQQQQQQQQQQQQQ");
}
public String getCityCode() {
return cityCode;
}
public void setCityCode(String cityCode) {
this.cityCode = cityCode;
}
public String getCityName() {
return cityName;
}
public void setCityName(String cityName) {
this.cityName = cityName;
}
public Date getEntryDate() {
return entryDate;
}
public void setEntryDate(Date entryDate) {
this.entryDate = entryDate;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getZip_code() {
return zip_code;
}
public void setZip_code(String zip_code) {
this.zip_code = zip_code;
}
}
When I try to get simple Object(City) with JSON it returns the cycle:
{"id":577,"region":{"name":"нет региона","id":15,"citys":[{"id":577,"region":
{"name":"нет региона","id":15,"citys":[{"id":577,"region":{"name":"нет
региона","id":15,"citys":[{"id":577,"region":{"name":"нет
региона","id":15,"citys":[{"id":577,"region":{"name":"нет
региона","id":15,"citys":[{"id":577,"region":{"name":"нет
региона","id":15,"citys":[{"id":577,"region":{"name":"нет......so on.
Are there any solutions for this issue?
You need to break the bi-directional relationship between your entity before converting to JSON.
I think there are two options:
Iterate the child collection, e.g. citys in Region and set Region to null. This way, circular dependency would be broken. You my want to add one name mapped attribute regionId in the City so that relational info is still available.
Create another set of POJO objects without circular dependency, copy the values from Entity Objects and then get the JSON using POJO objects.