I am trying to save a list of directors of a company whenever i create a new merchant, thus i have a #ManyToOne relationship between Director and Merchant respectively.
Thus far i have managed to get it to save the list of directors and the merchant when i do a POST. However when i do a GET request i do not get back the directors, the list comes back empty. When i check in the database, the joining column is empty as shown in the image but the rest of the data is present. How can i solve this issue?
This is my code :
Director.java
#Entity
#Table(name = "Directors")
public class Director {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long directorID;
#Cascade({org.hibernate.annotations.CascadeType.ALL})
#ManyToOne
#JoinColumn(name = "merchantNumber")
private Merchant merchant;
#NotBlank
private String name;
#NotBlank
private String surname;
public Director() {
}
public Director(long directorID, Merchant merchant, String name, String surname) {
this.directorID = directorID;
this.merchant = merchant;
this.name = name;
this.surname = surname;
}
...
Getters and setters
DirectorRepository.java
public interface DirectorRepository extends CrudRepository<Director, String> {
}
Merchant.java
public class Merchant {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int merchantNumber;
#NotBlank
private String merchantID;
#NotBlank
private String businessName;
#Cascade({org.hibernate.annotations.CascadeType.ALL})
#OneToMany(mappedBy = "merchant")
private List<Director> directors;
#NotBlank
private String userName;
public Merchant(int merchantNumber, String merchantID, String businessName, List<Director> directors, String userName ) {
this.merchantNumber = merchantNumber;
this.merchantID = merchantID;
this.businessName = businessName;
this.directors = directors;
this.userName = userName;
}
...
Getter and setters
MerchantService.java
public ResponseMerchantQuery createMerchant(Merchant merchant) {
if( merchant == null || merchant.getMerchantID()== null){
throw new ResourceNotFoundException("Empty", "Missing Data Exception");
} else {
merchant.setPassword(passwordEncoder.encode(merchant.getPassword()));
merchantRepository.save(merchant);
String merchantNum = Long.toString(merchant.getMerchantNumber());
return new ResponseMerchantQuery(merchantNum, "Merchant Created Successfully");
}
}
MerchantController.java
#RequestMapping(method = RequestMethod.POST, value = "/api/merchants")
public ResponseMerchantQuery createMerchant(#Valid #RequestBody Merchant merchant){
System.out.println("size of merchnat " + merchant.getDirectors().size());
return merchantService.createMerchant(merchant);
}
Related
I'm trying to set some values to certain object if some contidions are true. It seems like code executes and reaches the "set" lines, but when I send POST request(where this logic is implemented) and then GET method, it seems like it hasn't updated this object.
This is my Car class:
import lombok.AccessLevel;
import lombok.Data;
import lombok.Setter;
import lombok.ToString;
import javax.persistence.*;
#Data
#Entity
#Table(name = "Cars")
public class Car {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Setter(AccessLevel.NONE)
private Long Id;
private int yearOfProduction;
private int price;
private String color;
private String brand;
private String model;
#ManyToOne
#JoinColumn(name = "owner")
#ToString.Exclude
private Customer owner;
public Car() {
}
public Car(int yearOfProduction, int price, String color, String brand, String model) {
this.yearOfProduction = yearOfProduction;
this.price = price;
this.color = color;
this.brand = brand;
this.model = model;
}
}
This is my Customer class:
import lombok.AccessLevel;
import lombok.Data;
import lombok.Setter;
import javax.persistence.*;
import java.util.List;
#Data
#Entity
public class Customer {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Setter(AccessLevel.NONE)
private Long Id;
private String firstName;
private String lastName;
private String email;
private String phoneNumber;
private int amountOfCash;
private int actualDiscount;
#OneToMany(mappedBy = "owner", fetch = FetchType.EAGER)
private List<Car> carList;
public Customer(String firstName, String lastName, String email, String phoneNumber, int amountOfCash, int actualDiscount) {
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
this.phoneNumber = phoneNumber;
this.amountOfCash = amountOfCash;
this.actualDiscount = actualDiscount;
}
public Customer() {
}
}
This is my POST method when I implement the logic:
public ResponseEntity<Customer> buyCar(Long customerID, Long carID) {
customerRepository
.findById(customerID)
.ifPresentOrElse(customer -> {
carRepository.findById(carID).ifPresentOrElse(car -> {
if (customer.getAmountOfCash() > car.getPrice() * (100 - customer.getActualDiscount()) / 100) {
customer.getCarList().add(car);
customer.setActualDiscount(customer.getActualDiscount() + 5);
customer.setAmountOfCash(customer.getAmountOfCash() -
car.getPrice()* (100 - customer.getActualDiscount()) / 100);
car.setOwner(customer);
} else {
throw new ResponseStatusException(HttpStatus.NOT_ACCEPTABLE,
"Customer doesn't have enough cash");
}
}, () -> {
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Car not found");
});
}, () -> {
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Customer not found");
});
return new ResponseEntity<>(HttpStatus.OK);
}
This is my GET method:
public List<Customer> getCustomers() {
return customerRepository.findAll();
}
I also want to add that when I've tried to add the customer once again to the data base like this: customerRepository.save(customer) in POST method, and then I used GET method. The fields have been updated except of the carList, this one was still empty. Also when I print the customer to the console, all of the fields are updated, even carList.
You need to set cascade on your #OneToMany annotation as CascadeType.PERSIST):
#Data
#Entity
public class Customer {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Setter(AccessLevel.NONE)
private Long Id;
private String firstName;
private String lastName;
private String email;
private String phoneNumber;
private int amountOfCash;
private int actualDiscount;
#OneToMany(mappedBy = "owner", fetch = FetchType.EAGER, cascade = CascadeType.PERSIST)
private List<Car> carList;
public Customer(String firstName, String lastName, String email, String phoneNumber, int amountOfCash, int actualDiscount) {
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
this.phoneNumber = phoneNumber;
this.amountOfCash = amountOfCash;
this.actualDiscount = actualDiscount;
}
public Customer() {
}
}
This will trigger also the persistence of the Car objects in the carList property of Customer.
There are other cascade types that might be interesting in your use case, so please take a look at the following resources:
https://docs.oracle.com/javaee/6/api/javax/persistence/CascadeType.html
https://www.baeldung.com/jpa-cascade-types
In addition, add #Transactional to your public ResponseEntity<Customer> buyCar method as follows:
#Transactional
public ResponseEntity<Customer> buyCar(Long customerID, Long carID) {
customerRepository
.findById(customerID)
.ifPresentOrElse(customer -> {
carRepository.findById(carID).ifPresentOrElse(car -> {
if (customer.getAmountOfCash() > car.getPrice() * (100 - customer.getActualDiscount()) / 100) {
customer.getCarList().add(car);
customer.setActualDiscount(customer.getActualDiscount() + 5);
customer.setAmountOfCash(customer.getAmountOfCash() -
car.getPrice()* (100 - customer.getActualDiscount()) / 100);
car.setOwner(customer);
} else {
throw new ResponseStatusException(HttpStatus.NOT_ACCEPTABLE,
"Customer doesn't have enough cash");
}
}, () -> {
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Car not found");
});
}, () -> {
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Customer not found");
});
return new ResponseEntity<>(HttpStatus.OK);
}
I have a class that has Users #entity. Which has a profile picture that needs to update, When I pass the #Query the image name update and I can see the image in the folder too. But in my API, I have a imageName return so I can do assynchronize change. The weired part is when I upload the image, image get uploaded in a folder and in the database too, but throw 500 error. Never saw this happen Before. Any help will be appreciated.
POJO Class
#Entity
#Table(name="users")
public class Users {
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#Column(name = "firstname")
private String firstName;
#Column(name = "lastname")
private String lastName;
#Id
#Column(name = "username")
private String username;
#Column(name = "email")
private String email;
#Column(name = "role")
private String role;
#Column(name = "profile_picture")
private String profilePicture;
}
Profile Picture Class
public class ProfilePicture {
private MultipartFile profileImage;
private String profileImageName;
}
Repository
public interface ProfileRepository extends JpaRepository<Users, String> {
#Query(value = "UPDATE users SET profile_picture = :saveImage WHERE username = :username", nativeQuery = true)
public String updateUserProfilePictureForUsername(#Param("saveImage") String saveImage, #Param("username") String username);
}
Service:
public void saveProfileImage(ProfilePicture saveImage, String username) {
String imageName = saveImage.getProfileImageName();
profileRepo.updateUserProfilePictureForUsername(imageName, username);
}
REST API
#PostMapping(path = "/uploadprofileimage")
#ResponseStatus(HttpStatus.CREATED)
public String uploadProfilePicture(#RequestParam("image") MultipartFile Imagefile, #RequestParam("username") String username) throws IOException {
String profileImageName = Imagefile.getOriginalFilename();
ProfilePicture profileImage = new ProfilePicture();
String fileFolderPath = "/Users/Desktop/Documents/" + username + /ProfilePictures/";
File filePath = new File(fileFolderPath);
if (!filePath.exists()) {
filePath.mkdirs();
}
File file = new File(fileFolderPath, profileImageName);
profileImage.setProfileImageName(profileImageName);
profileImage.setProfileImage(Imagefile);
profileImage.getProfileImage().transferTo(file);
profileService.saveProfileImage(profileImage, username);
return profileImage.getProfileImageName();
}
This is the Solution using Lambda Expression.
public Users saveProfileImage(ProfilePicture saveImage, String username) {
String imageName = saveImage.getProfileImageName();
return profileRepo.findById(username).map( user -> {
user.setProfilePicture(imageName);
return profileRepo.save(user);
}).orElseThrow(() -> new ResourceNotFoundException("Something went wrong "));
}
I have the following classes
// COMPANY
#Entity
#Table(name=Company.TABLE_NAME)
public class Company {
public static final String TABLE_NAME = "company";
public static final String PK_NAME = "id";
#Id
#Column(name="id")
private String id = IdGenerator.createId();
#ManyToOne(cascade={CascadeType.PERSIST, CascadeType.MERGE}, fetch=FetchType.EAGER)
#JoinColumn(name="categoryid", table=TABLE_NAME)
private Category category;
#Column(name = "name", nullable=false, table=TABLE_NAME)
#Size(min=2, max=60, message="LATER")
private String name;
#Column(name="domainName", nullable=true, table=TABLE_NAME)
private String domainName;
#Column(name="registrationNumber", nullable=true, table=TABLE_NAME)
private String registrationNumber;
#Column(name="description", table=TABLE_NAME)
private String description;
#OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
#JoinColumn(name="itemId")
private Set<Image> logos = new HashSet<>();
#OneToMany(mappedBy="company", cascade=CascadeType.ALL, fetch=FetchType.LAZY)
private List<Branch> branches = new ArrayList<>();
public Company() {}
public void addBranch(Branch branch) {
branch.setCompany(this);
branch.getAddress().setActor(this);
branches.add(branch);
}
public void addLogo(Image logo) {
}
// GETTERS AND SETTERS
}
// BRANCHES
#Entity
#Table(name=Branch.TABLE_NAME)
public class Branch {
public static final String TABLE_NAME = "branch";
#Id
#Column(name = "id")
private String id = IdGenerator.createId();
#OneToOne(cascade=CascadeType.ALL)
#JoinColumn(name="address")
private Address address;
#Column(name = "telephone")
private String telephone;
#ManyToOne
#JoinColumn(name="company")
private Company company;
public Branch() {
this.address.setAddressCategory(AddressCategory.BRANCH);
}
// GETTERS AND SETTERS
}
// ADDRESS
#Entity
#Table(name=Address.TABLE_ADDRESS)
public class Address {
public static final String TABLE_ADDRESS = "address";
#Id
#Column(name="id")
private String id = IdGenerator.createId();
#Column(name="category", nullable=false)
private AddressCategory addressCategory;;
#Column(name="streetname", nullable=true)
private String streetname;
#Column(name="number", nullable=true)
private String number;
#Column(name="postcode", nullable=true)
private String postcode;
#Column(name="city", nullable=true)
private String city;
#Column(name="country", nullable=true)
private String country;
#Column(name = "telephone")
private String telephone;
#Embedded
private EmailAddress email;
#Column(name="description", nullable=true)
private String description;
// GETTERS AND SETTERS
}
// EMAIL
#Embeddable
public class EmailAddress {
#Column(name="email")
private String emailAddress;
public EmailAddress() { }
public EmailAddress(String emailAddress) {
this.emailAddress = emailAddress;
}
public String getEmailAddress() { return emailAddress; }
public void setEmailAddress(String emailAddress) { this.emailAddress = emailAddress; }
}
// COMPANY DTO
public class CompanyDTO {
private String id;
private String categoryId;
private String name;
private String domainName;
private String registrationNumber;
private String description;
private List<Branch> branches = new ArrayList<>();
public CompanyDTO fromCompany(Company company) {
this.setId(company.getId());
this.setName(company.getName());
this.setDomainName(company.getDomainName());
this.setRegistrationNumber(company.getRegistrationNumber());
this.setDescription(company.getDescription());
return this;
}
public Company toCompany(Company company) {
company.setName(getName());
company.setDomainName(getDomainName());
company.setRegistrationNumber(getRegistrationNumber());
company.setDescription(getDescription());
//company.setLogo(new Image());
company.setBranches(this.getBranches());
return company;
}
// GETTERS AND SETTERS
}
The controller method:
#PostMapping(path = CREATE_COMPANY)
public ResponseEntity<?> save(#RequestBody CompanyDTO dto){ System.out.println("__________COMPANY----------");
Category category = categoryService.findById(dto.getCategoryId());
Company company = dto.toCompany(new Company());
company.setCategory(category);
company.setLogos(new HashSet<Image>(Arrays.asList(new Image("garden", "garden.jpg", "/garden"))));
companyService.save(company);
return new ResponseEntity<> ("", HttpStatus.CREATED);
}
This is the JSON I am sending from Postman:
{
"categoryId": "ee6e75c9-2d1b-41c1-8f12-236fbf907683",
"name": "McDonalds",
"domainName": "Vodafone.com",
"registrationNumber": "5555555",
"description": "Vodafone",
"branches": [
{
"telephone": "003325647895",
"address": {
"addressCategory": "BRANCH",
"streetname": "Milkweg",
"number": "50",
"postcode": "3014",
"city": "Vienna",
"country": "Austria",
"email": {"email": "example#mail.com"},
"telephone": "003325647895",
"description": "P. O. Box decription",
"actor": "1abaaa11-1145-432f-84b0-40b9b551acdd"
}
}
],
"logos": []
}
And I get the following error in Postman: 400 Bad Request. It is even never sent to the server because it is a bad request.
If I remove the object inside the array branches attribute (empty array), then it works.
I have double check my attributes names but everything seems to be correct. I just don't know what is wrong.
I am not able to fetch all records from two tables using the below query
I have tried this but I am getting a result from one table only. I want a result of both the tables i.e, client_software_param_mapping and client_file_configuration having the same ClientId which is a foreign key from third pojo(client_software_configuration) to first and second pojo.
public Result showClientConfiguration() {EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("defaultPU");
EntityManager entityManager = entityManagerFactory.createEntityManager();
Query q=entityManager.
createQuery("SELECT c FROM client_software_param_mapping c JOIN fetch client_file_configuration f ON c.ClientId=f.ClientId");
List data =q.getResultList();
return ok(Json.toJson(data));
}
first pojo
#Entity
public class client_file_configuration {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String sourceFolder;
private String sourceFile;
private String processingFolder;
private String processingFile;
private String processedFolder;
private int intervalInMin;
private String readAfterDelay;
private String parserClass;
private String directoryMode;
private String fileMode;
private String actionMode;
private String type;
private String fileExpressionResolver;
#OneToOne
#JoinColumn(name = "ClientId")
private client_software_configuration clientSoftwareConfiguration;
public client_software_configuration getClientSoftwareConfiguration() {
return clientSoftwareConfiguration;
}
public void setClientSoftwareConfiguration(client_software_configuration clientSoftwareConfiguration) {
this.clientSoftwareConfiguration = clientSoftwareConfiguration;
}
}
secondpojo
#Entity
public class client_software_param_mapping {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String paramKey;
private String paramValue;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getParamKey() {
return paramKey;
}
public void setParamKey(String paramKey) {
this.paramKey = paramKey;
}
public String getParamValue() {
return paramValue;
}
public void setParamValue(String paramValue) {
this.paramValue = paramValue;
}
#ManyToOne
#JoinColumn(name = "ClientId")
private client_software_configuration clientSoftwareConfiguration;
public client_software_configuration getClientSoftwareConfiguration() {
return clientSoftwareConfiguration;
}
public void setClientSoftwareConfiguration(client_software_configuration clientSoftwareConfiguration) {
this.clientSoftwareConfiguration = clientSoftwareConfiguration;
}
}
thirdpojo
#Entity
public class client_software_configuration {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String url;
private int port;
private String endPoint;
private String isPost;
private String isPing;
private String params;
private int serialNo;
private String dateFormat;
private String token;
}
this is the right query as it is returning the object of the third pojo present at that ClientId so it is able to understand the type of ClientId.JPQL never uses table and column names. It always uses entity names and their mapped fields/properties names.so here I have taken the object of the third pojo having the ClientId field.
select c,p from client_file_configuration c,client_software_param_mapping p where c.clientSoftwareConfiguration = p.clientSoftwareConfiguration
So first a bit of back story. The issue I am having is when I create a user. Previously I had tried to create a user and assign them a role separately before discovering that by inserting into the SEC_USER_ROLE table the program was also inserting into the APP_USER table and I was getting an error about inserting duplicate values into the parent table. However, now by creating the user and role together I am getting the following error:
Primary key should be primitive (or list of primitives for composite
pk) , an instance of java.lang.Long with the primary keys filled in or
an instance of WebIntSecRole.......
Code as follows, not sure where I'm goin g wrong or the best solution at this point.
Admin.java:
//New User Creation
WebIntUser newUser = new WebIntUser();
newUser.setLoginId(newLoginName);
newUser.setCreatedBy(loggedUser);
newUser.setCreatedOn(today);
newUser.setDbAuth(true);
newUser.setDeleted(false);
newUser.setDisabled(false);
newUser.setEmail(newEmail);
newUser.setEncrypted(true);
newUser.setEncryptPassword(true);
newUser.setFirstName(newFirstName);
newUser.setLastName(newLastName);
newUser.setUpdatedBy(loggedUser);
newUser.setUpdatedOn(today);
newUser.setVersion(1);
newUser.setLdapId(1);
//userService.createUser(newUser);
//Set role for new user
WebIntSecRoleUser newUserRole = new WebIntSecRoleUser();
newUserRole.setUser(newUser);
newUserRole.setDeleted(false);
newUserRole.setRole(userService.selectRoleById(1));
//newUserRole.setCreatedBy(loggedUser);
//newUserRole.setCreatedOn(today);
//newUserRole.setUpdatedBy(loggedUser);
//newUserRole.setUpdatedOn(today);
newUserRole.setVersionNumber(0);
userService.createRole(newUserRole);
WebIntUser.java
#Entity
#Table(name = "APP_USER")
#EntityListeners(value = { AuditChangeListener.class })
public class WebIntUser implements Serializable {
public WebIntUser() {
};
public WebIntUser(String login, String pass) {
this.loginId = login;
this.password = pass;
}
private Integer userId;
private String loginId;
private String password;
private String firstName;
private String lastName;
private String email;
private boolean disabled;
private boolean deleted;
private boolean dbAuth;
private boolean isEncrypted;
private boolean encryptPassword;
private Date lastLogin;
private Date prevLogin;
private Integer version;
private Date lastPasswordChange;
private Date createdOn;
private Date updatedOn;
private String createdBy;
private String updatedBy;
private Integer ldapId;
public static interface propertyName {
String userId = "userId";
String loginId = "loginId";
String password = "password";
String firstName = "firstName";
String lastName = "lastName";
String email = "email";
String disabled = "disabled";
String deleted = "deleted";
String dbAuth = "dbAuth";
String isEncrypted = "isEncrypted";
String encryptPassword = "encryptPassword";
String lastLogin = "lastLogin";
String prevLogin = "prevLogin";
String version = "version";
String lastPasswordChange = "lastPasswordChange";
String createdOn = "createdOn";
String updatedOn = "updatedOn";
String createdBy = "createdBy";
String updatedBy = "updatedBy";
String ldapId = "ldapId";
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "USER_ID", nullable = false)
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
.....getters/setters
}
WebIntSecRoleUser.java:
#Entity
#Table(name = "SEC_ROLE_USER")
#EntityListeners(value = {AuditInfoChangeListener.class})
public class WebIntSecRoleUser implements AuditableDomainObject {
private Long id;
private WebIntSecRole role;
private WebIntUser user;
private boolean deleted;
private AuditInfo auditInfo;
private long versionNumber;
private Date createdOn;
private Date updatedOn;
private String createdBy;
private String updatedBy;
public interface propertyName extends Auditable.propertyName {
String id="id";
String role="role";
String user="user";
String deleted = "deleted";
String createdOn = "createdOn";
String updatedOn = "updatedOn";
String createdBy = "createdBy";
String updatedBy = "updatedBy";
}
public static interface permissionKey{
String UPDATE="SecRoleUser.U";
}
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name = "ROLE_USER_ID",nullable = false, unique = true)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#JoinColumn(name="ROLE_ID", nullable=false)
public WebIntSecRole getRole() {
return role;
}
public void setRole(WebIntSecRole role) {
this.role = role;
}
#ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinColumn(name="USER_ID", nullable = false)
public WebIntUser getUser() {
return user;
}
public void setUser(WebIntUser user) {
this.user = user;
}
Getters/setters
}
Note: There is some commented out code that I'm either trying not to use anymore, or in the case of Created By and Created On etc I was getting errors for multiple inserts.
In my opinion you have missed the #ManyToOne mapping on the WebIntSecRole. You only specified the #JoinColumn.
#ManyToOne(/* desired options */)
#JoinColumn(name="ROLE_ID", nullable=false)
public WebIntSecRole getRole() {
return role;