How to delete many-to-many relationship? - java

I have a many-to-many relationship (Car & driver) How, when deleting a Driver, delete a link in the driver_car table and delete cars that were bound to this driver, and vice versa, when deleting a car, simply delete a car and links in the driver_car table that are not associated with this by car?
My BaseEntity:
#MappedSuperclass
public abstract class BaseEntity {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Temporal(TemporalType.TIMESTAMP)
private Date created;
#Temporal(TemporalType.TIMESTAMP)
private Date updated;
private Boolean visible;
#Column(name = "image_url")
private String imageUrl;
public BaseEntity() {
this.created = new Date();
this.updated = new Date();
this.visible = true;
}
#PreUpdate
public void preUpdate() {
this.updated = new Date();
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
public Date getUpdated() {
return updated;
}
public void setUpdated(Date updated) {
this.updated = updated;
}
public Boolean getVisible() {
return visible;
}
public void setVisible(Boolean visible) {
this.visible = visible;
}
public String getImageUrl() {
return imageUrl;
}
public void setImageUrl(String imageUrl) {
this.imageUrl = imageUrl;
}
}
My Driver:
#Entity
#Table(name = "drivers")
public class Driver extends BaseEntity {
#Column(name = "first_name")
private String firstName;
#Column(name = "last_name")
private String lastName;
private String notes;
private double balance;
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(
name = "driver_car",
joinColumns = #JoinColumn(name = "driver_id"),
inverseJoinColumns = #JoinColumn(name = "car_id"))
private Set<Car> cars;
public Driver() {
super();
this.cars = new HashSet<>();
}
public Set<Car> getCars() {
return cars;
}
public void setCars(Set<Car> cars) {
this.cars = cars;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getNotes() {
return notes;
}
public void setNotes(String notes) {
this.notes = notes;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
}
My Car:
#Entity
#Transactional
public class Car extends BaseEntity {
#Column(name = "cars_name")
private String carName;
private String color;
#Column(name = "engine_of_capacity")
private double engineCapacity;
#Column(name = "years_of_issue")
private Integer yearsOfIssue;
#Column(name = "car_number")
private String carNumber;
#ManyToMany(mappedBy = "cars", cascade = CascadeType.ALL)
private Set<Driver> drivers;
public Car() {
super();
drivers = new HashSet<>();
}
public Set<Driver> getDrivers() {
return drivers;
}
public void setDrivers(Set<Driver> drivers) {
this.drivers = drivers;
}
public String getCarNumber() {
return carNumber;
}
public void setCarNumber(String carNumber) {
this.carNumber = carNumber;
}
public String getCarName() {
return carName;
}
public void setCarName(String carName) {
this.carName = carName;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public double getEngineCapacity() {
return engineCapacity;
}
public void setEngineCapacity(double engineCapacity) {
this.engineCapacity = engineCapacity;
}
public Integer getYearsOfIssue() {
return yearsOfIssue;
}
public void setYearsOfIssue(Integer yearsOfIssue) {
this.yearsOfIssue = yearsOfIssue;
}
}
Delete Car:
#Override
public void delete(Long id) {
entityManager.createQuery("delete from Car s where s.id = :id")
.setParameter("id", id)
.executeUpdate();
}
Delete Driver:
#Override
public void delete(Long id) {
entityManager.createQuery("delete from Driver d where d.id = :id")
.setParameter("id", id)
.executeUpdate();
}

One should be very cautious about using CascadeType.ALL for #ManyToMany associations, since this might yield surprising results as described e.g. here:
https://thorben-janssen.com/best-practices-for-many-to-many-associations-with-hibernate-and-jpa/#The_CascadeType_you_should_avoid_at_all_costs
In the best case, it only creates performance issues, but in the worst case, it might also remove more records than you intended.
So a better way would be e.g. to have a dedicated service logic which specifies exactly which entities are to be deleted and which of course also takes care of synchronizing both sides of the association.
This way there can also be a simple check whether a previously associated Car has no more associated Drivers after one was deleted, so that the "orphan" Car can then be deleted as well.

Related

Unable to retrieve data from MySQL using Spring boot JPA

I am getting a java.lang.NullPointerException error at the line where the program begins to retrieve data from the database, specifically starting with the code recordDB.setAccountName(billing.getAccountId().getAccountName());. The entity tables are joined together and at first I thought that it can't retrieve data from other other tables but I tried to run with just recordDB.setAmount(billing.getAmount()); Can someone explain what I missed or is there something wrong with the logic?
Component
#Component
public class FileProcessor {
#Autowired
private BillingRepository billingRepository;
public FileProcessor() {
}
public List<Record> retrieveRecordfromDB(List<Request> requests) throws BarsException{
List<Record> records = new ArrayList<>();
if (!requests.isEmpty()) {
for (Request request : requests) {
Billing billing = billingRepository
.findByBillingCycleAndStartDateAndEndDate(
request.getBillingCycle()
, request.getStartDate()
, request.getEndDate());
if (billing == null) {
throw new BarsException(BarsException.NO_RECORDS_TO_WRITE);
}
Record recordDB = new Record();
recordDB.setBillingCycle(request.getBillingCycle());
recordDB.setStartDate(request.getStartDate());
recordDB.setEndDate(request.getStartDate());
recordDB.setAccountName(billing.getAccountId().getAccountName());
recordDB.setFirstName(billing.getAccountId().getCustomerId().getFirstName());
recordDB.setLastName(billing.getAccountId().getCustomerId().getLastName());
recordDB.setAmount(billing.getAmount());
records.add(recordDB);
}
}
return records;
}
}
Account Entity
#Entity
public class Account {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "account_id")
private int accountId;
private String accountName;
private LocalDateTime dateCreated;
private String isActive;
private String lastEdited;
public Account() {
}
public int getAccountId() {
return accountId;
}
public void setAccountId(int accountId) {
this.accountId = accountId;
}
public String getAccountName() {
return accountName;
}
public void setAccountName(String accountName) {
this.accountName = accountName;
}
public LocalDateTime getDateCreated() {
return dateCreated;
}
public void setDateCreated(LocalDateTime dateCreated) {
this.dateCreated = dateCreated;
}
public String getIsActive() {
return isActive;
}
public void setIsActive(String isActive) {
this.isActive = isActive;
}
public String getLastEdited() {
return lastEdited;
}
public void setLastEdited(String lastEdited) {
this.lastEdited = lastEdited;
}
public Customer getCustomerId() {
return customerId;
}
public void setCustomerId(Customer customerId) {
this.customerId = customerId;
}
public Set<Billing> getBilling() {
return billing;
}
public void setBilling(Set<Billing> billing) {
this.billing = billing;
}
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "customer_id")
private Customer customerId;
#OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinColumn(name = "account_id")
private Set<Billing> billing;
}
Billing Entity
#Entity
public class Billing {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "billing_id")
private int billingId;
//private int billingId;
private int billingCycle;
private String billingMonth;
private Double amount;
private LocalDate startDate;
private LocalDate endDate;
private String lastEdited;
//private Account accountId;
public Billing() {
}
public int getBillingId() {
return billingId;
}
public void setBillingId(int billingId) {
this.billingId = billingId;
}
public int getBillingCycle() {
return billingCycle;
}
public void setBillingCycle(int billingCycle) {
this.billingCycle = billingCycle;
}
public String getBillingMonth() {
return billingMonth;
}
public void setBillingMonth(String billingMonth) {
this.billingMonth = billingMonth;
}
public Double getAmount() {
return amount;
}
public void setAmount(Double amount) {
this.amount = amount;
}
public LocalDate getStartDate() {
return startDate;
}
public void setStartDate(LocalDate startDate) {
this.startDate = startDate;
}
public LocalDate getEndDate() {
return endDate;
}
public void setEndDate(LocalDate endDate) {
this.endDate = endDate;
}
public String getLastEdited() {
return lastEdited;
}
public void setLastEdited(String lastEdited) {
this.lastEdited = lastEdited;
}
public Account getAccountId() {
return accountId;
}
public void setAccountId(Account accountId) {
this.accountId = accountId;
}
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "account_id")
private Account accountId;
}
Customer Entity
#Entity
public class Customer {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "customer_id")
private int customerId;
private String firstName;
private String lastName;
private String address;
private String status;
private LocalDateTime dateCreated;
private String lastEdited;
public Customer() {
}
public int getCustomerId() {
return customerId;
}
public void setCustomerId(int customerId) {
this.customerId = customerId;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public LocalDateTime getDateCreated() {
return dateCreated;
}
public void setDateCreated(LocalDateTime dateCreated) {
this.dateCreated = dateCreated;
}
public String getLastEdited() {
return lastEdited;
}
public void setLastEdited(String lastEdited) {
this.lastEdited = lastEdited;
}
#OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinColumn(name = "customer_id")
private Set<Account> account;
}
Repository
#Repository
public interface BillingRepository extends JpaRepository<Billing, Integer> {
public Billing findByBillingCycleAndStartDateAndEndDate (int billingCycle, LocalDate startDate, LocalDate endDate);
}
Your naming is unintuitive, which hinders people unfamiliar with the code:
recordDB implies that it is the Database for records. Instead, it is a record that is to be saved in the DB. Naming it "RecordToSave" or similar is much better, since it gets the intention across.
getAccountId() implies that the id of an account is returned (an int or long) NOT that the account itself is returned. You should rename it to getAccount()
About the issue:
What you are using as a bidirectional ManyToOne <-> OneToMany relationship.
One side should be the owning side of the relationship. Here the #JoinColumn should be stated. The receiving end should have a MappedBy Property.
See this guide for more information: https://thorben-janssen.com/hibernate-tips-map-bidirectional-many-one-association/
It should solve the issue, since only the data retrieval for connected tables does not seem to work, hence fixing the references should fix the issue.
Your billing.getAmount() does refer to data written in the billing object/table, and is not from another table like billing.getAccountId().getAccountName() which gets data from the account table connected to the billings table.
Last, but not least:
Think about your cascading strategy. The way it currently works, deleting a billing will delete the account of that billing, which deletes all references made there and so on since you currently use Cascade.All for ALL entries. This is bad.
Here is a guide for cascading: https://howtodoinjava.com/hibernate/hibernate-jpa-cascade-types/
Are you sure the field names in the Billing class exactly match the database column names? I see you set the column name to "billing_id" explicitly for the id field, but not for any other fields. My guess is that the fields in that class are all null since there are no corresponding database columns (debug to confirm).

Data insertion in database using jpa issueing error

I am new to the JPA world. Here I have tried to make a simple POS. The problem is that when there is no predefined value in tables although the PK is auto-incremented, data is not being inserted into DB. But if I set a predefined row into the tables then there are no issues and data is being inserted successfully. please help me.
The following are my Java classes, and I am using Mysql for DB.
#Entity
#Table(name = "card_payment")
public class Card_payment {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
int id;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "order_id")
private Orders order;
#Column(name = "issuing_bank")
String issuing_bank;
#Column(name = "card_type")
String card_type;
#Column(name = "card_expiry_date")
String card_expiry_date;
#Column(name = "amount")
int amount;
public Card_payment() {
super();
}
public Orders getOrder() {
return order;
}
public void setOrder(Orders order) {
this.order = order;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getIssuing_bank() {
return issuing_bank;
}
public void setIssuing_bank(String issuing_bank) {
this.issuing_bank = issuing_bank;
}
public String getCard_type() {
return card_type;
}
public void setCard_type(String card_type) {
this.card_type = card_type;
}
public String getCard_expiry_date() {
return card_expiry_date;
}
public void setCard_expiry_date(String card_expiry_date) {
this.card_expiry_date = card_expiry_date;
}
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
}
#Entity
#Table(name = "customer")
public class Customer {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
int id;
#Column(name = "name")
String name;
#Column(name = "mobile_no")
long mobile_no;
#Column(name = "address")
String address;
#OneToMany(mappedBy = "customer", cascade = CascadeType.ALL,
fetch=FetchType.LAZY)
private List<Orders> orders;;
public Customer() {
super();
}
public List<Orders> getOrders() {
return orders;
}
public void setOrders(List<Orders> orders) {
this.orders = orders;
}
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 long getMobile_no() {
return mobile_no;
}
public void setMobile_no(long mobile_no) {
this.mobile_no = mobile_no;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
#Entity
#Table(name = "Item")
public class Item {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
int id;
#Column(name = "name")
String name;
#Column(name = "unit")
String unit;
#Column(name = "stock_quantity")
int stock_quantity;
#Column(name = "reorder_level")
int reorder_level;
#Column(name = "unit_price")
int unit_price;
#Column(name = "tax_percentage")
float tax_percentage;
#OneToMany(mappedBy = "item", cascade = CascadeType.ALL,
fetch=FetchType.LAZY)
private List<Orderline> orderLines;
public Item() {
super();
}
public List<Orderline> getOrderLines() {
return orderLines;
}
public void setOrderLines(List<Orderline> orderLines) {
this.orderLines = orderLines;
}
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 String getUnit() {
return unit;
}
public void setUnit(String unit) {
this.unit = unit;
}
public int getStock_quantity() {
return stock_quantity;
}
public void setStock_quantity(int stock_quantity) {
this.stock_quantity = stock_quantity;
}
public int getReorder_level() {
return reorder_level;
}
public void setReorder_level(int reorder_level) {
this.reorder_level = reorder_level;
}
public int getUnit_price() {
return unit_price;
}
public void setUnit_price(int unit_price) {
this.unit_price = unit_price;
}
public float getTax_percentage() {
return tax_percentage;
}
public void setTax_percentage(float tax_percentage) {
this.tax_percentage = tax_percentage;
}
}
#Entity
#Table(name = "OrderLine")
public class Orderline {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
int id;
#ManyToOne
#JoinColumn(name = "itemId")
private Item item;
#ManyToOne
#JoinColumn(name = "orderId")
private Orders orders;
#Column(name = "unit_cost")
float unit_cost;
#Column(name = "unit")
int unit;
#Column(name = "tax_percentage")
float tax_percentage;
#Column(name = "quantity")
int quantity;
#Column(name = "amount")
int amount;
#Column(name = "tax_amount")
float tax_amount;
#Column(name = "line_total")
int line_total;
public Orderline() {
super();
}
public Item getItem() {
return item;
}
public void setItem(Item item) {
this.item = item;
}
public Orders getOrders() {
return orders;
}
public void setOrders(Orders orders) {
this.orders = orders;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public float getUnit_cost() {
return unit_cost;
}
public void setUnit_cost(float unit_cost) {
this.unit_cost = unit_cost;
}
public int getUnit() {
return unit;
}
public void setUnit(int unit) {
this.unit = unit;
}
public float getTax_percentage() {
return tax_percentage;
}
public void setTax_percentage(float tax_percentage) {
this.tax_percentage = tax_percentage;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
public float getTax_amount() {
return tax_amount;
}
public void setTax_amount(float tax_amount) {
this.tax_amount = tax_amount;
}
public int getLine_total() {
return line_total;
}
public void setLine_total(int line_total) {
this.line_total = line_total;
}
#Entity
#Table(name = "orders")
public class Orders {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
int id;
#ManyToOne
#JoinColumn(name = "customerId")
private Customer customer;
#Column(name = "order_date")
String order_date;
#Column(name = "delivery_address")
String delivery_address;
#Column(name = "total")
long total;
#OneToMany(mappedBy = "orders", cascade = CascadeType.ALL,
fetch=FetchType.LAZY)
private List<Orderline> orderlines;
#OneToOne(mappedBy = "order")
private Cash_payment cash_payment;
#OneToOne(mappedBy = "order")
private Card_payment card_payment;
#OneToOne(mappedBy = "order")
private Cheque_payment cheque_payment;
public Orders() {
super();
}
public Cash_payment getCash_payment() {
return cash_payment;
}
public void setCash_payment(Cash_payment cash_payment) {
this.cash_payment = cash_payment;
}
public Card_payment getCard_payment() {
return card_payment;
}
public void setCard_payment(Card_payment card_payment) {
this.card_payment = card_payment;
}
public Cheque_payment getCheque_payment() {
return cheque_payment;
}
public void setCheque_payment(Cheque_payment cheque_payment) {
this.cheque_payment = cheque_payment;
}
public List<Orderline> getOrderlines() {
return orderlines;
}
public void setOrderlines(List<Orderline> orderlines) {
this.orderlines = orderlines;
}
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getOrder_date() {
return order_date;
}
public void setOrder_date(String order_date) {
this.order_date = order_date;
}
public String getDelivery_address() {
return delivery_address;
}
public void setDelivery_address(String delivery_address) {
this.delivery_address = delivery_address;
}
public long getTotal() {
return total;
}
public void setTotal(long total) {
this.total = total;
}
}
public class JPAExample {
private static EntityManager entityManager = EntityManagerUtil.getEntityManager();
public static void main(String[] args) {
JPAExample example = new JPAExample();
entityManager.getTransaction().begin();
Orders order = new Orders();
order.setOrder_date("2019/05/05");
order.setTotal(1000);
order.setDelivery_address("kolkata");
Item item = new Item();
item.setName("cream");
item.setReorder_level(10);
item.setUnit_price(10);
item.setUnit("kg");
item.setTax_percentage((float) 12.5);
item.setStock_quantity(20);
item.setReorder_level(5);
Orderline orderline = new Orderline();
orderline.setAmount(1);
orderline.setItem(item);
orderline.setLine_total(200);
orderline.setQuantity(1);
List<Orderline> orderlns = new ArrayList<>();
orderlns.add(orderline);
item.setOrderLines(orderlns);
Customer customer = new Customer();
customer.setId(1234);
customer.setName("Tanusha");
customer.setMobile_no(Long.valueOf("9609"));
customer.setAddress("u-86, garia");
orderline.setOrders(order);
List<Orderline> orderLinesList = new ArrayList<>();
orderLinesList.add(orderline);
order.setOrderlines(orderLinesList);
order.setCustomer(customer);
List<Orders> orderList = new ArrayList<>();
orderList.add(order);
customer.setOrders(orderList);
Card_payment cp = new Card_payment();
cp.setAmount(200);
cp.setCard_expiry_date("2019/05/05");
cp.setCard_type("visa");
cp.setIssuing_bank("SBI");
cp.setOrder(order);
order.setCard_payment(cp);
entityManager.merge(order);
try {
entityManager.getTransaction().commit();
} catch (Exception e) {
entityManager.getTransaction().rollback();
}
}
}

MySQLIntegrityConstraintViolationException: column "question_id" cannot be null error

i have two entity classes named Qa.java and Answeres.java
my Qa entity consists of lists of answers.
Qa.Java
#Entity
#Table(name = "qa")
public class Qa {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
private String question;
private String type;
private String description;
private String param;
private int maxlength;
#OneToMany(mappedBy = "qa", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private List<Answers> answersList = new ArrayList<>();
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getQuestion() {
return question;
}
public void setQuestion(String question) {
this.question = question;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getParam() {
return param;
}
public void setParam(String param) {
this.param = param;
}
public int getMaxlength() {
return maxlength;
}
public void setMaxlength(int maxlength) {
this.maxlength = maxlength;
}
public List<Answers> getAnswersList() {
return answersList;
}
public void setAnswersList(List<Answers> answersList) {
this.answersList = answersList;
}
}
Answers.java
#Entity
#Table(name = "answers")
public class Answers {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String ans_label;
private int ans_value;
private int ans_weightage;
private int is_default;
#ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinColumn(name = "question_id", referencedColumnName = "id",nullable = false)
private Qa qa;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getAns_label() {
return ans_label;
}
public void setAns_label(String ans_label) {
this.ans_label = ans_label;
}
public int getAns_value() {
return ans_value;
}
public void setAns_value(int ans_value) {
this.ans_value = ans_value;
}
public int getAns_weightage() {
return ans_weightage;
}
public void setAns_weightage(int ans_weightage) {
this.ans_weightage = ans_weightage;
}
public int getIs_default() {
return is_default;
}
public void setIs_default(int is_default) {
this.is_default = is_default;
}
public Qa getQa() {
return qa;
}
public void setQa(Qa qa) {
this.qa = qa;
}
}
My controller from where i am trying to insert data.
TableDataController.java
#Controller
public class TabletDataController {
#Autowired
QaRepository qaRepository;
#RequestMapping(value = "/saveApiData", method = RequestMethod.GET)
public void saveApiData(){
Qa qa = new Qa();
qa.setParam("");
qa.setType("input_spinner");
qa.setDescription("");
qa.setQuestion("व्यक्तिको पहिलो नाम ?");
ArrayList<Answers> answersArrayList = new ArrayList<>();
Answers answers = new Answers();
answers.setAns_label("नेपाली");
answers.setAns_value(1);
answers.setAns_weightage(0);
answers.setIs_default(0);
answersArrayList.add(answers);
qa.setAnswersList(answersArrayList);
qaRepository.save(qa);
}
}
my qaRepository extends JpaRepository. so whenever i call this api i get an error of com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'question_id' cannot be null
what am i doing wrong?
You have a bidirectional OneToMany relationship, so you need to manually maintain both sides of the relationship. Here you are only setting the Qa side with qa.setAnswersList(answersArrayList);
You need to set the other side of your relationship manually. add:
answers.setQa(qa);
before you save your list
code as follow
public void saveApiData(){
Qa qa = new Qa();
qa.setParam("");
qa.setType("input_spinner");
qa.setDescription("");
qa.setQuestion("व्यक्तिको पहिलो नाम ?");
ArrayList<Answers> answersArrayList = new ArrayList<>();
Answers answers = new Answers();
answers.setAns_label("नेपाली");
answers.setAns_value(1);
answers.setAns_weightage(0);
answers.setIs_default(0);
answers.setQa(qa);
answersArrayList.add(answers);
qa.setAnswersList(answersArrayList);
qaRepository.save(qa);
}
when you save.you should Cascade save.Your annotations configure the relationship of the associated tables but also to associate them when they are saved

EclipseLink ADD CONSTRAINT Exception

I would like to use create-or-extend-tables but eclipselink gives below error after tables were created. I am using Eclipselink 2.5.2 and db is MS Sql 2014
Exception [EclipseLink-4002] (Eclipse Persistence Services -
2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.DatabaseException Internal
Exception: com.microsoft.sqlserver.jdbc.SQLServerException:
'announcementCOMPANY_ID' object already exists. Error Code: 2714 Call:
ALTER TABLE announcement ADD CONSTRAINT announcementCOMPANY_ID FOREIGN
KEY (COMPANY_ID) REFERENCES company (ID) Query:
DataModifyQuery(sql="ALTER TABLE announcement ADD CONSTRAINT
announcementCOMPANY_ID FOREIGN KEY (COMPANY_ID) REFERENCES company
(ID)")
Persistance.java
persistenceMap.put("javax.persistence.jdbc.driver", ConfigParams
.getInstance().getValue(ConfigConstants.JDBC_DRIVER));
persistenceMap.put("javax.persistence.jdbc.user", ConfigParams
.getInstance().getValue(ConfigConstants.JDBC_USER));
persistenceMap.put("javax.persistence.jdbc.password", ConfigParams
.getInstance().getValue(ConfigConstants.JDBC_PASSWORD));
persistenceMap.put("javax.persistence.jdbc.url", ConfigParams
.getInstance().getValue(ConfigConstants.JDBC_URL));
persistenceMap.put("eclipselink.logging.logger",
Log4jSessionLog.class.getName());
// persistenceMap.put("eclipselink.logging.file",
// Log4jSessionLog.class.getName());
persistenceMap
.put("eclipselink.ddl-generation.output-mode", "database");
persistenceMap.put("eclipselink.weaving.internal", "false");
persistenceMap.put("eclipselink.logging.level", ConfigParams
.getInstance().getValue(ConfigConstants.JDBC_LOGGING_LEVEL));
persistenceMap.put("eclipselink.ddl-generation",
"create-or-extend-tables");
Announcement.java
#Entity
#Table(name="announcement")
public class Announcement {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "annId")
private int id;
#Column(nullable =false, length = 250, name="annName")
private String name;
#Column(length = 250)
private String mainTitle;
#Column(nullable=false, length = 250)
private String subTitle;
#Lob
private String content;
#Column(nullable = false)
private Date startDate;
#Transient
private java.util.Date startDateUtil;
#Column(nullable = false)
private Date endDate;
#Transient
private java.util.Date endDateUtil;
#Lob
private String imgUrl;
#Column(nullable = false)
private boolean isActive;
#Column(nullable = false)
private boolean isDeleted;
#Transient
private BtcResponse status;
private Type type;
#ManyToMany
#JoinTable(name="announcementLogs")
private List<Log> logAList = new ArrayList<Log>();
private Company company;
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 String getMainTitle() {
return mainTitle;
}
public void setMainTitle(String mainTitle) {
this.mainTitle = mainTitle;
}
public String getSubTitle() {
return subTitle;
}
public void setSubTitle(String subTitle) {
this.subTitle = subTitle;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Date getStartDate() {
return startDate;
}
public void setStartDate(Date startDate) {
this.startDate = startDate;
}
public java.util.Date getStartDateUtil() {
return startDateUtil;
}
public void setStartDateUtil(java.util.Date startDateUtil) {
this.startDateUtil = startDateUtil;
}
public Date getEndDate() {
return endDate;
}
public void setEndDate(Date endDate) {
this.endDate = endDate;
}
public java.util.Date getEndDateUtil() {
return endDateUtil;
}
public void setEndDateUtil(java.util.Date endDateUtil) {
this.endDateUtil = endDateUtil;
}
public String getImgUrl() {
return imgUrl;
}
public void setImgUrl(String imgUrl) {
this.imgUrl = imgUrl;
}
public boolean isActive() {
return isActive;
}
public void setActive(boolean isActive) {
this.isActive = isActive;
}
public boolean isDeleted() {
return isDeleted;
}
public void setDeleted(boolean isDeleted) {
this.isDeleted = isDeleted;
}
public BtcResponse getStatus() {
return status;
}
public void setStatus(BtcResponse status) {
this.status = status;
}
public List<Log> getLogAList() {
return logAList;
}
public void setLogAList(List<Log> logAList) {
this.logAList = logAList;
}
#ManyToOne
public Type getType() {
return type;
}
public void setType(Type type) {
this.type = type;
}
public Announcement() {
super();
}
public Announcement(BtcResponse status) {
super();
this.status = status;
}
public Announcement(java.util.Date startDateUtil,
java.util.Date endDateUtil, String imgUrl, boolean isActive) {
super();
this.startDateUtil = startDateUtil;
this.endDateUtil = endDateUtil;
this.imgUrl = imgUrl;
this.isActive = isActive;
}
#ManyToOne
#JoinColumn(name = "id")
public Company getCompany() {
return company;
}
public void setCompany(Company company) {
this.company = company;
}
}
Company.java
#Entity
#Table(name="company")
public class Company {
#Id
#Column(nullable = false)
private int id;
#Column(length = 100, nullable = false, name="companyName")
private String name;
private List<Banner> bannerList = new ArrayList<Banner>();
private List<Announcement> announcementList = new ArrayList<Announcement>();
private List<PriceList> priceList = new ArrayList<PriceList>();
#OneToMany(mappedBy="company")
public List<Announcement> getAnnouncementList() {
return announcementList;
}
public void setAnnouncementList(List<Announcement> announcementList) {
this.announcementList = announcementList;
}
#Transient
private BtcResponse status;
public int getId() {
return id;
}
public Company(int id, String name) {
super();
this.id = id;
this.name = name;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#OneToMany(mappedBy="company")
public List<Banner> getBannerList() {
return bannerList;
}
public void setBannerList(List<Banner> bannerList) {
this.bannerList = bannerList;
}
public BtcResponse getStatus() {
return status;
}
public void setStatus(BtcResponse status) {
this.status = status;
}
public Company() {
super();
}
public Company(BtcResponse status) {
super();
this.status = status;
}
#OneToMany(mappedBy="company")
public List<PriceList> getPriceList() {
return priceList;
}
public void setPriceList(List<PriceList> priceList) {
this.priceList = priceList;
}
}

Why I don't see the data of the oneToOne?

I am new in JPA
I created two entities Questionnaire and Patient
I want that Questionnaire will have data of Patient.
Before I created the Questionnaire with only patientId but now I want to add new structure to get all the patientData.
I added new field of patientData and added new join( I hope I did it ok ).
The problem when I call to query AllQuestionnaires I didn't get data of patientData.
Could you please advise me ?
#Entity
#NamedQueries({
#NamedQuery(name = "AllQuestionnaires", query = "select q from Questionnaire q order by q.patientId") })
public class Questionnaire implements Serializable {
private static final long serialVersionUID = 1L;
public Questionnaire() {
}
#Id
#GeneratedValue
private long id;
private long patientId;
private Timestamp created;
#OneToOne
#JoinColumn(name = "patientId" ,referencedColumnName = "id" , insertable = false, updatable = false)
private Patient patientData;
public Patient getPatient() {
return patientData;
}
public void setPatient(Patient patient) {
this.patientData = patient;
}
#OneToMany(cascade = CascadeType.ALL)
private List<QuestionnaireAnswer> answers;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public long getPatientId() {
return patientId;
}
public void setPatientId(long patientId) {
this.patientId = patientId;
}
public Timestamp getCreated() {
return created;
}
public void setCreated(Timestamp created) {
this.created = created;
}
public void setCreated(long created) {
this.created = new Timestamp(created);
}
public List<QuestionnaireAnswer> getAnswers() {
return answers;
}
public void setAnswers(List<QuestionnaireAnswer> answers) {
this.answers = answers;
}
}
class Patient
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.ArrayList;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Transient;
#Entity
#NamedQueries({
#NamedQuery(name = "AllPatients", query = "select p from Patient p"),
#NamedQuery(name = "PatientsByUserType", query = "select p from Patient p where p.userType = :userType"),
#NamedQuery(name = "PatientByEmail", query = "select p from Patient p where p.email = :email"),
#NamedQuery(name = "PatientById", query = "select p from Patient p where p.id = :id") })
public class Patient implements Serializable {
public enum UserType {
PATIENT,
CONTROL
}
private static final long serialVersionUID = 1L;
public Patient() {
}
#Id
#GeneratedValue
private long id;
private String firstName;
private String lastName;
private String email;
private String password;
private int gender;
private Timestamp birthday;
private Timestamp diagnoseDate;
private Timestamp created;
private UserType userType;
#Transient
private ArrayList<Task> lastSubmittedTasks;
public UserType getUserType() {
return userType;
}
public void setUserType(UserType userType) {
this.userType = userType;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public int getGender() {
return gender;
}
public void setGender(int gender) {
this.gender = gender;
}
public Timestamp getBirthday() {
return birthday;
}
public void setBirthday(Timestamp birthday) {
this.birthday = birthday;
}
public void setBirthday(long birthday) {
this.birthday = new Timestamp(birthday);
}
public Timestamp getDiagnoseDate() {
return diagnoseDate;
}
public void setDiagnoseDate(Timestamp diagnoseDate) {
this.diagnoseDate = diagnoseDate;
}
public void setDiagnoseDate(long diagnoseDate) {
this.diagnoseDate = new Timestamp(diagnoseDate);
}
public Timestamp getCreated() {
return created;
}
public void setCreated(Timestamp created) {
this.created = created;
}
public void setCreated(long created) {
this.created = new Timestamp(created);
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public ArrayList<Task> getLastSubmittedTask() {
return lastSubmittedTasks;
}
public void setLastSubmittedTasks(ArrayList<Task> lastSubmittedTasks) {
this.lastSubmittedTasks = lastSubmittedTasks;
}
}
#RequestMapping(value = "/questionnaires", method = RequestMethod.POST)
#ResponseBody
public String createQuestionnaires(#RequestBody String body, HttpSession session) {
EntityManager em = emf.createEntityManager();
long patientId = (long) session.getAttribute("patientId");
try {
Questionnaire questionnaire = gson.fromJson(body, Questionnaire.class);
questionnaire.setPatientId(patientId);
questionnaire.setCreated(new Timestamp(System.currentTimeMillis()));
em.getTransaction().begin();
em.persist(questionnaire);
em.getTransaction().commit();
return "{\"status\": \"OK\", \"id\": " + questionnaire.getId() + "}";
} finally {
em.close();
}
}

Categories