I am beginner with Spring Boot and trying to improve my skills to get new job, so I hope you help me even if the question maybe easy for you as I search a lot and gain nothing.
I need to get by id, but return data is duplicated with only one record, I will show you what I do and the result for more explanation.
In DB side:
I have VW_Prices view in DB and it's data as shown below:
In Spring Boot side:
VW_Prices class is :
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.annotations.Immutable;
#Entity
#Table(name = "VW_PRICES")
public class VW_Prices implements Serializable {
private long dealId;
private Long quotationId;
private Long productPriceForEjada;
private Long productPriceForClient;
private Long productId;
private Long productQuantity;
private String productName;
#Id
#Column(name = "ID")
public long getDealId() {
return dealId;
}
public void setDealId(long dealId) {
this.dealId = dealId;
}
#Column(name = "PRODUCT_QUANTITY")
public Long getProductQuantity() {
return productQuantity;
}
public void setProductQuantity(Long productQuantity) {
this.productQuantity = productQuantity;
}
#Column(name = "PRODUCT_NAME")
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
#Column(name = "PRODUCT_PRICE_FOR_EJADA")
public Long getProductPriceForEjada() {
return productPriceForEjada;
}
public void setProductPriceForEjada(Long productPriceForEjada) {
this.productPriceForEjada = productPriceForEjada;
}
#Column(name = "PRODUCT_PRICE_FOR_CLIENT")
public Long getProductPriceForClient() {
return productPriceForClient;
}
public void setProductPriceForClient(Long productPriceForClient) {
this.productPriceForClient = productPriceForClient;
}
#Column(name = "PRODUCT_ID")
public Long getProductId() {
return productId;
}
public void setProductId(Long productId) {
this.productId = productId;
}
#Column(name = "QUOTATION_ID")
public Long getQuotationId() {
return quotationId;
}
public void setQuotationId(Long quotationId) {
this.quotationId = quotationId;
}
}
and I create VW_PricesRepository
import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import springboot.deals_tracker_system.models.VW_Prices;
import springboot.deals_tracker_system.models.VW_Prices_interface;
public interface VW_PricesRepository extends JpaRepository<VW_Prices, Long> {
#Query( nativeQuery = true,value = "SELECT distinct * from VW_Prices v where v.id = :dealID " )
List<VW_Prices> findByDealId( #Param("dealID") Long id);
}
and my in my Service
public List<VW_Prices> findByDealId(Long dealId) {
System.out.println("we are in service");
List<VW_Prices> variableForDebug = VW_pricesRepository.findByDealId(dealId);
for (VW_Prices vw_Prices : variableForDebug) {
System.out.println(vw_Prices.getDealId() + " " + vw_Prices.getProductName());
}
return variableForDebug;
//return VW_pricesRepository.findByDealId(dealId);
}
When I pass dealId = 39 the result comes duplicated and not correct as in below:
how can I get correct data??
The view is made for Quotation Product Table to get product name.
i think the problem is the id annotation you must add GeneratedValue
fro the class:
#Entity
#Table(name = "VW_PRICES")
public class VW_Prices implements Serializable {
#Id
#GeneratedValue (strategy = GenerationType.IDENTITY)
private long dealId;
private Long quotationId;
private Long productPriceForEjada;
private Long productPriceForClient;
private Long productId;
private Long productQuantity;
private String productName;
//code..
}
You dont have to use JPQL for this type of queries it's already exist in jpa:
VW_PricesRepository:
public interface VW_PricesRepository extends JpaRepository<VW_Prices, Long> {
}
to get data by id use findById like that:
public VW_Prices findByDealId(Long dealId) {
System.out.println("we are in service");
VW_Prices vw_Prices = VW_pricesRepository.findById(dealId);
System.out.println(vw_Prices.getDealId() + " " +
vw_Prices.getProductName());
}
return vw_Prices;
}
All data should be deleted from VW_Prices table because ids are not unique, try to insert new data with unique id then try the above code
I detect the problem, The view has main table Quotation and I didn't select it's ID and I used ID of the secondary table as the main ID for the View
I just write it if any one Google for such problem
Related
What is wrong with my to-do application? I want the user to be able to add a todo and have it be saved in my MySQL database with the time it was created, but I don't know what I'm doing wrong.
I am new to learning Springboot and would appreciate any suggestions or advice.
Todo Entity:
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.CreationTimestamp;
import javax.persistence.*;
import java.util.Date;
#Entity(name = "Todo")
#NoArgsConstructor
#Table(name = "todos")
public class Todo {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
#Column(name="description")
private String description;
#Column(name="target_date")
#CreationTimestamp
private Date targetDate;
public Todo(String description) {
this.description = description;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Date getTargetDate() {
return targetDate;
}
public void setTargetDate(Date targetDate) {
this.targetDate = targetDate;
}
#Override
public String toString() {
return "Todo{" +
"id=" + id +
", description='" + description + '\'' +
", targetDate=" + targetDate +
'}';
}
}
Adding a Todo with Spring Data JPA
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
import javax.transaction.Transactional;
import java.util.List;
#Repository
#Component
public interface TodoRepository extends JpaRepository<Todo, Integer> {
#Modifying
#Query(value = "INSERT INTO todos (description) VALUES (:description)", nativeQuery=true)
#Transactional
void addTodo(#Param("description") String description);
}
TodoController
#RestController
#RequestMapping(value = "/api/v1/todos")
#AllArgsConstructor
public class TodoController {
#Autowired
private ITodoService todoService;
#PostMapping(value = "/add-todo")
public String addTodo(#RequestParam String description) {
Todo todo = new Todo();
todo.setDescription(description);
todoService.addTodo(todo);
return todo.toString();
}
after getting a post request, the target_date is getting NULL in MySQL
I assume you can solve it by using persist():
#Autowired EntityManager entityManager;
#PostMapping(value = "/add-todo")
public String addTodo(#RequestParam String description) {
Todo todo = new Todo();
todo.setDescription(description);
entityManager.persist(todo);
return todo.toString();
}
Employee.Java
`
import lombok.ToString;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
#ToString
#Entity
public class Employee {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int empid;
private String empname;
private String empcontact;
private String empemail;
private String empphoto;
#OneToMany(mappedBy = "employee", cascade = CascadeType.ALL)
private List<Skillset> skillset;
public int getEmpid() {
return empid;
}
public void setEmpid(int empid) {
this.empid = empid;
}
public String getEmpname() {
return empname;
}
public void setEmpname(String empname) {
this.empname = empname;
}
public String getEmpcontact() {
return empcontact;
}
public void setEmpcontact(String empcontact) {
this.empcontact = empcontact;
}
public String getEmpemail() {
return empemail;
}
public void setEmpemail(String empemail) {
this.empemail = empemail;
}
public String getEmpphoto() {
return empphoto;
}
public void setEmpphoto(String empphoto) {
this.empphoto = empphoto;
}
public List<Skillset> getSkillset() {
return skillset;
}
public void setSkillset(List<Skillset> skillset) {
this.skillset = skillset;
}`
SkillSet.Java
`
package aurozen.assign.aurozenassign.entity;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.ToString;
import javax.persistence.*;
#Entity
public class Skillset {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int skillid;
private String skillname;
#JsonIgnore
#ManyToOne
#JoinColumn(name = "empId", nullable = false,updatable = false, insertable = true)
private Employee employee;
public int getSkillid() {
return skillid;
}
public void setSkillid(int skillid) {
this.skillid = skillid;
}
public String getSkillname() {
return skillname;
}
public void setSkillname(String skillname) {
this.skillname = skillname;
}
public Employee getEmployee() {
return employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
#Override
public String toString() {
return "Skillset{" +
"skillid='" + skillid + '\'' +
", skillname='" + skillname + '\'' +
", employee=" + employee +
'}';
}
}
`
EmployeeRepositry.java
package aurozen.assign.aurozenassign.repositry;
import aurozen.assign.aurozenassign.entity.Employee;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.Optional;
#Repository
public interface EmployeeRepositry extends JpaRepository<Employee, Integer> {
Optional<Employee> findByEmpcontact(String s);
}
SkillSetRepositry.java
package aurozen.assign.aurozenassign.repositry;
import aurozen.assign.aurozenassign.entity.Skillset;
import org.springframework.data.jpa.repository.JpaRepository;
public interface SkillsetRepositry extends JpaRepository<Skillset, Integer> {
}
Controller
#PostMapping(value = "/signup",produces = {"application/json"})
public Employee addEmployee(#RequestBody Employee employee) {
empRepo.save(employee);
return employee;
}
Json Data
{
"empname": "sandep",
"empcontact": "9650114890",
"empemail": "aidaih",
"empphoto": "paidpaid",
"skillset": [
{
"skillname": "jop"
}
]
}
I have attached Db Screenshot
Database Screenshot with empid as foreign key in skillset table
foreign key(empid) in the skillset table always populating to null when ever I try to post the data through postman.other fields getting populating without any problem in both the table
The relationship between Skillset and Employee is owned by Skillset. This means JPA will persist the state the Skillset objects have.
But via #RequestBody you are creating an Employee instance.
While that references a Skillset instances, that instance does not reference the Employee.
Therefor no relationship gets persisted.
To fix this add code to setSkillset to set the employee property of it.
Something like this should do:
public void setSkillset(List<Skillset> skillset) {
this.skillset = skillset;
skillset.foreach(s -> s.setEmployee(this));
}
Suppose I have two resources Person and Article
#Entity
#Table(name = "person")
public class Person {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long person_id;
private String firstName;
private String lastName;
#OneToMany(mappedBy="person", cascade=CascadeType.ALL)
private List<Article> articles = new ArrayList<>();
}
#Entity
#Table(name="article")
public class Article {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String title;
private String details;
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="person_id")
private Person person;
}
I now want to add HATEOAS support to the response of the controller for which I am using org.springframework.hateoas.ResourceAssembler
public class PersonResourceAssembler implements ResourceAssembler<Person, Resource<Person>> {
private EntityLinks entityLinks;
public UserJobResourceAssembler(EntityLinks entityLinks) {
this.entityLinks = entityLinks;
}
#Override
public Resource<Person> toResource(Person entity) {
Resource<UserJob> resource = new Resource<>(entity);
resource.add(
entityLinks.linkFor(Person.class).withSelfRel()),
entityLinks.linkFor(...logic...).withRel("articles")) //here I am hardcoding the relation link name i.e "article"
);
return resource;
}
}
So, in above code the "article" is hardcoded for the link name, but I don't want to do it this way. I want it do in the way Spring-Data-REST handles it i.e for every relationship it auto detects the name of the variable used inside the Entity class e.g articles will be picked from Person and person will be picked from Article.
I have no idea how Spring-Data-REST handles it, but are there any readymade/custom solutions for this requirement?
You can use the reflection API to introspect the entity and find associations. Something like:
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.persistence.OneToMany;
public class AssociationUtility {
public static List<Field> getAssociatedFields(Object entity) {
Stream<Field> fields = Arrays.stream(entity.getClass().getDeclaredFields());
return fields.filter(field -> field.getAnnotation(OneToMany.class)
!= null).collect(Collectors.toList());
}
public static void main(String[] args) {
List<Field> fields = getAssociatedFields(new Customer());
fields.stream().forEach(f -> System.out.println("Make a link for Class: "
+ ((ParameterizedType) f.getGenericType()).getActualTypeArguments()[0]
+ " with rel: " + f.getName()));
System.exit(0);
}
}
Hi all i have a small issue with joining two tables using jparepository using #query but i am getting error. please help me with this.
UserAddress.java
package com.surya_spring.example.Model;
import java.io.Serializable;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
#Entity
#Table(name = "user_address")
//#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class UserAddress implements Serializable {
/**
*
*/
private static final long serialVersionUID = -3570928575182329616L;
/*#ManyToMany(cascade = {CascadeType.ALL},fetch=FetchType.EAGER,mappedBy = "userAddress",targetEntity=UserData.class)*/
#ManyToOne(cascade=CascadeType.ALL)
#JoinColumn(name="user_id")
private UserData userdata;
#Id
#Column(name = "addr_id")
#GeneratedValue(strategy = GenerationType.AUTO)
private Long addrid;
#Column(name = "dr_no")
#NotNull
private String doorNo;
#Column(name = "strt_name")
#NotNull
private String streetName;
#Column(name = "city")
#NotNull
private String city;
#Column(name = "country")
#NotNull
private String country;
/*#OneToOne(cascade=CascadeType.ALL)
#Column(name="user_id")*/
public UserData getUserdata() {
return userdata;
}
public void setUserdata(UserData userdata) {
this.userdata = userdata;
}
public Long getAddrid() {
return addrid;
}
public void setAddrid(Long addrid) {
this.addrid = addrid;
}
public String getDoorNo() {
return doorNo;
}
public void setDoorNo(String doorNo) {
this.doorNo = doorNo;
}
public String getStreetName() {
return streetName;
}
public void setStreetName(String streetName) {
this.streetName = streetName;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
}
UserData.java
package com.surya_spring.example.Model;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.NonNull;
#Entity
#Table(name = "user_data")
public class UserData implements Serializable{
/**
* Serialization ID
*/
private static final long serialVersionUID = 8133309714576433031L;
/*#ManyToMany(targetEntity=UserAddress.class ,cascade= {CascadeType.ALL },fetch=FetchType.EAGER)
#JoinTable(name="userdata",joinColumns= #JoinColumn(name="userid"),inverseJoinColumns = #JoinColumn(name="userid"))
*/
#Id
#Column(name = "user_id")
#GeneratedValue(strategy = GenerationType.AUTO)
private Long userId;
#Column(name = "user_name")
#NonNull
private String userName;
#Column(name = "user_email")
#NonNull
private String userEmail;
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserEmail() {
return userEmail;
}
public void setUserEmail(String userEmail) {
this.userEmail = userEmail;
}
}
Repository:
package com.surya_spring.example.Repository;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import com.surya_spring.example.Model.UserData;
public interface UserDataRepository extends JpaRepository<UserData, Long>{
#Query(" FROM UserData where userId= :id")
public List<UserData> findBySearchTerm(#Param("id") Long id);
}
any one let me know the query to join this both the table to get city name from user_address where user_id=? joining user_data table
If you want to get the city for a user you can do:
#Query("SELECT ua.city FROM UserAddress ua WHERE ua.userdata.userId = ?1")
String findCityByUserId(Long userId);
Note that your entity names are used (like in your java classes) and not the table names in database! You do not have to do the join by yourself as you can use the properties of your domain models to access the related data
I am using spring MVC with Hibernate, The aim is to get the table data and store it in a list.Here the entity class being used :
package com.bng.core.entity;
// default package
// Generated Oct 25, 2015 4:38:03 PM by Hibernate Tools 3.4.0.CR1
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* servicenames generated by hbm2java
*/
#Entity
#Table(name = "servicenames")
public class ServiceNames implements java.io.Serializable {
private Integer id;
private String serviceName;
public ServiceNames() {
}
public ServiceNames(String servicename) {
this.serviceName = servicename;
}
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id", unique = true, nullable = false)
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
#Column(name = "servicename", length = 25)
public String getServiceName() {
return this.serviceName;
}
public void setServiceName(String servicename) {
this.serviceName = servicename;
}
}
And the method used to get the list :
#Transactional
#Override
public List<ServiceNames> getServiceNames() {
Logger.sysLog(LogValues.APP_INFO, this.getClass().getName(), "Getting all Service names.");
Session session = sessionFactoryGlobal.openSession();
Criteria criteria = session.createCriteria(ServiceNames.class);
List<ServiceNames> serviceNamesList = criteria.list();
session.close();
return serviceNamesList;
}
When the method is called it returns an empty list. Please suggest where its going wrong ?
I think you are sure your table servicenames has data. So such problem can be when #Transactional is not working properly. Try to get list without #Transactional by open and close a transaction manually.