I have already built projects similar to this one, I even based this one in a different project I have. Thing is, I don't see why it keeps failing when I try to save an object to the Database. These are my Classes:
Car
#Data
#AllArgsConstructor
#NoArgsConstructor
#Entity(name = "cars")
public class Car {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column
#NotBlank
private String brand;
#Column
#NotBlank
private String model;
#Column
#NotBlank
private String color;
#Column
#NotBlank
private int kilometers;
#Column(name = "fabrication_date")
private LocalDate fabricationDate;
#Column
#PositiveOrZero
private float price;
#Override
public String toString() {
return "------------------------------------------------------------"+ "\n"
+brand + " - " + model;
}
#OneToMany(mappedBy = "car")
#JsonBackReference(value = "car-purchases")
private List<Purchase> purchases;
}
Purchase
#Data
#NoArgsConstructor
#AllArgsConstructor
#Entity
#Table(name = "purchases",
uniqueConstraints = { #UniqueConstraint(columnNames =
{ "user_id", "car_id" }) })
public class Purchase {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column(name = "creation_date")
private LocalDate creationDate;
#Column
private float price;
#ManyToOne
#JoinColumn(name = "user_id")
private User user;
#ManyToOne
#JoinColumn(name = "car_id")
private Car car;
}
This is the Add to Database function:
#Override
public CarOutDTO addCar(CarInDTO carInDTO) {
Car car = new Car();
modelMapper.map(carInDTO, car);
car.setFabricationDate(LocalDate.now());
car.setKilometers(0);
Car newCar = carRepository.save(car); <--- It fails here
CarOutDTO carOutDTO = new CarOutDTO();
modelMapper.map(car, carOutDTO);
return carOutDTO;
}
And, this is the info that comes when I try sending a POST:
I can't find the error here, I assume it has something to do with this part, maybe the #JsonBackReference part?
#OneToMany(mappedBy = "car")
#JsonBackReference(value = "car-purchases")
private List<Purchase> purchases;
Related
customer
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
#Entity
#Table(name = "customer")
public class Customer {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "customer_id")
private Long customerId;
#NonNull
#Column(name = "name")
private String name;
#NonNull
#Column(name = "address")
private String address;
#NonNull
#Column(name = "house_no")
private String houseNo;
#Column(name = "active")
private boolean active = true;
#NonNull
#Column(name = "customer_type")
private String customerType;
#NonNull
#Column(name = "pack")
private String pack;
#JsonIgnore
#OneToOne(mappedBy = "customer",cascade = CascadeType.ALL)
private Stb stb;
#JsonIgnore
#OneToOne(mappedBy = "customer",cascade = CascadeType.ALL )
private Payment payment;
#JsonIgnore
#OneToMany(mappedBy = "customer", cascade = CascadeType.ALL)
private List<History> history;
}
History
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
#Entity
#Table(name = "history")
public class History {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "history_id")
private Long historyId;
#Column(name = "amount_paid")
private Long AmountPaid;
#LastModifiedDate
#Column(name = "payment_date")
private String paymentDate;
#Column(name = "due")
private Long due;
#JsonIgnore
#ManyToOne(optional = false,fetch=FetchType.LAZY)
#JoinColumn(name = "customer_f_id",referencedColumnName = "customer_id")
private Customer customer;
payment
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
#Entity
#Table(name = "payment")
public class Payment {
public Long normalPrice =220L;
public Long sportsPrice = 250L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "payment_id")
private Long paymentId;
#Nonnull
#Column(name = "amount_paid")
private Long paid;
#Nullable
#LastModifiedDate
#Column(name = "payment_date")
private String paymentDate;
#Nullable
#Column(name = "due")
private Long due;
#JsonIgnore
#OneToOne(fetch=FetchType.EAGER,optional=false)
#JoinColumn(name = "customer_f_id",referencedColumnName = "customer_id")
private Customer customer;
stb
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
#Entity
#Table(name = "stbox")
public class Stb {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "stb_id")
private Long StbId;
#NonNull
#Column(name = "stbox_number")
private String StboxNumber;
#NonNull
#Column(name = "stbox_id")
private String StboxId;
#NonNull
#Column(name = "stbox_cust_number")
private String StboxCustNumber;
#NonNull
#Column(name = "stbox_type")
private String StboxType;
#JsonIgnore
#OneToOne(optional = false,fetch=FetchType.LAZY)
#JoinColumn(name = "customer_f_id",referencedColumnName = "customer_id")
private Customer customer;
im new to springboot , i just assigned foreign key in many ways i watched many tutorials and blogs and tried it out but it all failed , the foreign key is always set to null, anybody help , thanks in advance :) .
im trying to create a foreign key in stb , payment ,history but i refered it correctly but it ssets to null
Are you setting both sides of the joins?
public class Customer {
public void setStb(Stb stb) {
this.stb = stb;
stb.customer = this;
}
}
or outside maybe?
public void setCustomerStb(Customer customer, Stb stb) {
customer.setStb(stb);
stb.setCustomer(customer);
}
The same also applies to the other joins.
I am having a faq entity as below. Here createdBy field is having a manyToOne relationship with the user entity. Below joinColumns shows the association.
In the User entity, i have OneToMany relationship with UserRoles and UsersUnit which is EAGER load for User and not for faq. So i added #JsonIgnoreProperties
for UsersUnit and UsersRole and the corresponding User entity is shown below.
#Entity
#Table(name = "FAQ", catalog="abc")
public class Faq implements Serializable {
public Faq() {
super();
}
#Column(name = "CREATE_DATE")
private Timestamp createDate;
#Where(clause = "DELETE_DATE is null")
#Column(name = "DELETE_DATE")
private Timestamp deleteDate;
#Column(name = "DELETED_BY")
private BigDecimal deletedBy;
#Column(name = "DOC_BLOB", nullable = false)
#JsonIgnore
private byte[] docBlob;
#Column(name = "DOC_NAME", nullable = false, length = 100)
private String docName;
#Id
private BigDecimal id;
#Column(name = "ORDER_BY")
private BigDecimal orderBy;
#Column(name = "UPDATE_DATE")
private Timestamp updateDate;
#Column(name = "UPDATED_BY")
private BigDecimal updatedBy;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumns({
#JoinColumn(name="created_by", referencedColumnName="id")
})
private User faqCreatedBy;
}
User entity:
#Entity
#Table(name = "USERS", catalog="abc")
#JsonInclude(Include.NON_NULL)
public class User extends EntityLog{
private BigDecimal id;
private BigDecimal edipi;
private String firstname;
private String lastname;
private String email;
..///
private Set<UsersRoles> userRoles;
private Set<UsersUnit> usersUnit;
#Id
#Column(name="id")
public BigDecimal getId() {
return id;
}
...///
#Column
#JsonIgnoreProperties({ "faqCreatedBy" })
#OneToMany(fetch = FetchType.EAGER,mappedBy = "user",cascade = {CascadeType.ALL})
#JsonManagedReference
public Set<UsersRoles> getUserRoles() {
return userRoles;
}
...///
#Column
#JsonIgnoreProperties({ "faqCreatedBy" })
#OneToMany(fetch = FetchType.EAGER,mappedBy = "user",cascade = {CascadeType.ALL})
#JsonManagedReference
public Set<UsersUnit> getUsersUnit() {
return usersUnit;
}
////...
}
With this change I am expecting the faq to load with User entity but I am not execting UsersRoles and UsersUnit to load.
But that is not what i see. When faq loads it loads User and UsersRoles and UsersUnit. I am using Spring JPA fyi. Any leads what is wrong ? Appreciate any inputs.
I have two spring boot entities MeetingSetting and MeetingTime, MeetingSetting can have multiple MeetingTimes. I am trying to save these to at the same time with the DTO structure, so I can avoid the circular reference problem when I am getting MeetingTimes. Saving partially works. MeetingSettings has a property called meetingName which is a foreign key in meetingTimes. Everything except meetingName is saved which is for some reason null, but I can not find the reason, could someone maybe look at my code and tell me what I am missing?
MeetingSetting Entity:
#Entity
#Table(name = "meeting_settings")
#Setter
#Getter
public class MeetingsSetting implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "meeting_name", unique = true)
private String meetingName;
#Column(name = "meeting_url")
private String meetingUrl;
#Column(name = "meeting_pw")
private String meetingPw;
#OneToMany(mappedBy = "meetingName", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Set<MeetingTime> meetingTime = new HashSet<>();
}
MeetingSettingDTO:
#Getter
#Setter
public class MeetingSettingDTO {
private Long id;
#NotNull
private String meetingName;
#NotNull
private String meetingUrl;
#NotNull
private String meetingPw;
private Set<MeetingTime> meetingTime;
}
MeetingTime Entity:
#Entity
#Table(name = "meeting_times")
#Getter
#Setter
public class MeetingTime implements Serializable {
#JsonIgnore
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "meeting_date")
private String date;
#Column(name = "start_time")
private String startTime;
#Column(name = "end_time")
private String endTime;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "meeting_name" , referencedColumnName = "meeting_name")
private MeetingsSetting meetingName;
}
MeetingTimeDTO:
#Getter
#Setter
public class MeetingTimeDTO {
private Long id;
#NotNull
private String date;
#NotNull
private String startTime;
#NotNull
private String endTime;
private Set<MeetingSettingDTO> meetingSettings;
}
And finally the controller where I am saving everything (Just save method):
#PostMapping("/")
public void saveMeeting(#RequestBody MeetingSettingDTO meetingSettingDTO){
MeetingsSetting meetingsSetting = new MeetingsSetting();
meetingsSetting.setMeetingName(meetingSettingDTO.getMeetingName());
meetingsSetting.setMeetingPw(meetingSettingDTO.getMeetingPw());
meetingsSetting.setMeetingUrl(meetingSettingDTO.getMeetingUrl());
Set<MeetingTime> meetingTimeSet = meetingSettingDTO.getMeetingTime();
meetingsSetting.setMeetingTime(meetingTimeSet);
meetingSettingService.saveMeeting(meetingsSetting);
}
My service is just implementing a jpaRepository which takes MeetingSetting as parameter
In your MeetingTime entity class you have a parent:
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "meeting_name" , referencedColumnName = "meeting_name")
private MeetingsSetting meetingName;
You have to set it explicitly for each MeetingTime, so add this:
Set<MeetingTime> meetingTimeSet = meetingSettingDTO.getMeetingTime();
meetingTimeSet.forEach(m -> m.meetingName(meetingsSetting));
I have a spring boot application with two entities in a relationship. MeetingSetting and MeetingTime meetingSetting can have unlimited meetingTimes. So far the databases are generating without problem, but When I try to save my Entity they are saved but different from each other, they are saved independently. Meaning MeetingName which is a foreign key inside MeetingTime is not saved but seen as null (I debugged and tried finding out why but could not find anything) THe other values are saved-
could someone point me out what my error is?
this is the json I am sending:
{
"meetingName":"TEst",
"meetingPw":"",
"meetingTime":[
{
"date":"2021-05-31",
"startTime":"15:30",
"endTime":"16:30"
},
{
"date":"2021-06-21",
"startTime":"15:30",
"endTime":"17:30"
},
{
"date":"2021-06-21",
"startTime":"11:01",
"endTime":"11:01"
}
]
}
MeetingSettings:
#Entity
#Table(name = "meeting_settings")
#Data
public class MeetingsSetting {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "meeting_name", unique = true)
private String meetingName;
#Column(name = "meeting_url")
private String meetingUrl;
#Column(name = "meeting_pw")
private String meetingPw;
#OneToMany(mappedBy = "meeting_Name", cascade = CascadeType.ALL)
private Set<MeetingTime> meetingTime = new HashSet<>();
}
MeetingTime:
#Entity
#Table(name = "meeting_times")
#Data
public class MeetingTime {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "meeting_date")
private String date;
#Column(name = "start_time")
private String startTime;
#Column(name = "end_time")
private String endTime;
#ManyToOne
#JoinColumn(name = "meeting_name" ,insertable = false, updatable = false , referencedColumnName = "meeting_name")
private MeetingsSetting meeting_Name;
}
this is how I try to save the entity:
#RestController
#RequestMapping("/api/meetingSetting")
public class MeetingSettingController {
#Autowired
MeetingSettingService meetingSettingService;
#PostMapping("/")
public void saveMeeting(#RequestBody MeetingsSetting meetingsSetting){
meetingSettingService.saveMeeting(meetingsSetting);
}
}
My service calls the save method of an jpaRepository.
In a bi-directional One to Many, you have to synchronize both sides of the association.
You can simply iterate over all MeetingTime objects and set the corresponding MeetingSetting to it.
Your MeetingSettingService's saveMeeting method could do this:
public void saveMeeting(MeetingsSetting meetingsSetting) {
// ...
// here you're synchronizing both sides of the association
meetingsSetting.getMeetingTime()
.forEach(mt -> mt.setMeetingSetting(meetingSetting));
// ...
repository.save(meetingSetting);
}
Solution to my question, I am not sure if this is a good or correct way of solving this maybe someone can advice me a better solution:
#Entity
#Table(name = "meeting_times")
#Data
public class MeetingTime implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "meeting_date")
private String date;
#Column(name = "start_time")
private String startTime;
#Column(name = "meeting_name")
private String meeting_name;
THIS IS THE PART WHICH IS CALLED FROM THE METHOD INSIDE MEETINGSCONTROLLER
#Column(name = "end_time")
private String endTime;
#ManyToOne
#JoinColumn(name = "meeting_name" ,insertable = false, updatable = false, referencedColumnName = "meeting_name")
private MeetingsSetting meetingName;
}
MeetingsTime Entity:
#RestController
#RequestMapping("/api/meetingSetting")
public class MeetingSettingController {
#Autowired
MeetingSettingService meetingSettingService;
#PostMapping("/")
public void saveMeeting(#RequestBody MeetingsSetting meetingsSetting){
meetingsSetting.getMeetingTime()
.forEach(mt -> mt.setMeeting_name(meetingsSetting.getMeetingName()));
// ...
meetingSettingService.saveMeeting(meetingsSetting);
}
}
I have two tables, user and transaction. Where one user can have many transactions. So, everytime I create new user, they automatically make new transaction and the transaction type is SEND MONEY. But I don't understand how to write it in Spring JPA. Please take a look on my code and help me.
User.java
#Entity
#Table(name = "user")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private long id;
#Column(name = "name")
private String name;
#Column(name = "email")
private String email;
#Column(name = "password")
private String password;
#Column(name = "money")
private int money;
//Getter Setter Constructor
}
Transaction.java
#Entity
#Table(name = "transaction")
public class Transaction {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id_trans")
private long id_trans;
#Column(name = "id_user")
private long id_user;
#Column(name = "transaction_date")
private Timestamp transaction_date;
#Column(name = "type") //Default set as "SEND MONEY"
private String type;
#Column(name = "trans_money") //From money in User.class
private int trans_money;
//Getter Setter Constructor
}
I know I should do something in my UserDAO.java, but I still don't know how to send data from body and split(?) it into two object (user and transaction, so I can persist it in UserDAO).
First of all, you have to write the relationship between User and Transaction.
#Entity
#Table(name = "user")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private long id;
#Column(name = "name")
private String name;
#Column(name = "email")
private String email;
#Column(name = "password")
private String password;
#Column(name = "money")
private int money;
#OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
private Set<Transaction> transactions = new HashSet<>();
//Getter Setter Constructor
}
#Entity
#Table(name = "transaction")
public class Transaction {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id_trans")
private long id_trans;
#Column(name = "id_user")
private long id_user;
#Column(name = "transaction_date")
private Timestamp transaction_date;
#Column(name = "type") //Default set as "SEND MONEY"
private String type;
#Column(name = "trans_money") //From money in User.class
private int trans_money;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(referencedColumnName = "id")
private User user;
//Getter Setter Constructor
}
Then you have to create the JPA repository interface for the User
#Repository
public interface UserRepo extends CrudRepository <User, Long> {
}
Then in a service, you can do the following
#Service
public class UserService {
private UserRepo userRepo;
#Autowired
MealService(UserRepo userRepo){
this.userRepo = userRepo;
}
public void CreateNewUser(){
User user = new User();
// set its values
Transaction transaction = new Transaction();
transaction.setType("SEND MONEY");
// set other values
user.getTransactions().add(transaction);
userRepo.save(user);
}
}
Looking at the #Entity classes mentioned it seems to me that there exists an #ManyToOne association between Transaction and User which is not captured in the entity relationship modeling/mapping.
Please consider modeling that in your Transaction entity as follows,
#Entity
#Table(name = "transaction")
public class Transaction {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id_trans")
private long id_trans;
#ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.REFRESH, CascadeType.MERGE}, fetch = FetchType.LAZY)
#JoinColumn(name = "user_id")
private User user;
#Column(name = "transaction_date")
private Timestamp transaction_date;
#Column(name = "type") //Default set as "SEND MONEY"
private String type;
#Column(name = "trans_money") //From money in User.class
private int trans_money;
//Getter Setter Constructor
}
Once you do that you can create a JPA repository class for Transaction and User and simply use the save method to do what you want in a transaction after constructing your instances. More on transactions in Spring Data JPA here
public interface TransactionRepository extends JpaRepository<Transaction, Long> {
}