Everything was working well until I use the annotation #ManyToOne in the class 'Stock', it generates the error:
"Caused by: java.sql.SQLSyntaxErrorException: Table 'libraries.stock' doesn't exist"
the implementation of the class "Stock":
import java.util.List;
import javax.persistence.*;
import lombok.Data;
#Entity
#Table(name="stock")
#Data
public class Stock {
#EmbeddedId
private stockid id;
private int quantity;
public Stock(int qq) {
this.quantity = qq;
}
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "book_id")
private Book book ;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "library_id")
private Library library ;
}
Related
I have got two entity. Employee and Project
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import jakarta.persistence.*;
import lombok.*;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
#Entity
#Table(name = "EMPLOYEE_DB")
#Setter
#Getter
#AllArgsConstructor
#NoArgsConstructor
public class Employee {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int emp_id;
private String name;
private String email;
private String phone;
#ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinTable(name = "EMP_PRO_DB", joinColumns = {
#JoinColumn(name = "empId", referencedColumnName = "emp_id")
},
inverseJoinColumns = {
#JoinColumn(name = "proId", referencedColumnName = "pro_id")
}
)
// #JsonManagedReference
private Set<Project> projects;
}
and
import com.fasterxml.jackson.annotation.JsonBackReference;
import jakarta.persistence.*;
import lombok.*;
import java.util.Set;
#Entity
#Table(name = "PROJECT_DB")
#Setter
#Getter
#AllArgsConstructor
#NoArgsConstructor
public class Project {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int pro_id;
private String projectName;
private String projectType;
#ManyToMany(mappedBy = "projects", fetch = FetchType.LAZY)
#JsonBackReference
private Set<Employee> employees;
}
So there were three tables created:
employee_db
project_db
emp_pro_db
I have a EmployeeRepo and ProjectRepo. I can add data to both employee_db and project_db.
Now I would like to assignProject.
I have tried using workbench to insert: INSERT INTO emp_pro_db (emp_id, pro_id) VALUES (1, 6);
Which is working.
How do I use Jpa to do that?
The Item table has Many to One relationship with supplier table.
If i delete supplier table row data by Id, its not deleting the row.
The Item table has many rows with same supplier Id. If i delete in supplier table with id, the item table supplier column data /id should be deleted.
Thanks in advance
Item
package com.ingroinfo.ubm.entity;
import java.util.Date;
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.SequenceGenerator;
import javax.persistence.Table;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
#Entity
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#Table(name = "master_item")
#SequenceGenerator(name = "item_sequence", initialValue = 201, allocationSize = 10000)
public class Item {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "branch_sequence")
private Long itemId;
private String itemName;
private String itemImage;
private String itemStatus;
private String unitOfMeasure;
private String remarks;
private String units;
#ManyToOne
#JoinColumn(name = "category_id")
private Category category;
#ManyToOne
#JoinColumn(name = "supplier_id")
private Supplier supplier;
#ManyToOne
#JoinColumn(name = "brand_id")
private Brand brand;
#ManyToOne
#JoinColumn(name = "publisher_id")
private BrandPublisher publisher;
#ManyToOne
#JoinColumn(name = "hsn_id")
private HsnCode hsnCode;
#Column(name = "date_created")
#CreationTimestamp
private Date dateCreated;
#Column(name = "last_updated")
#UpdateTimestamp
private Date lastUpdated;
}
ItemRepository
package com.ingroinfo.ubm.dao;
import javax.transaction.Transactional;
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.Repository;
import com.ingroinfo.ubm.entity.Item;
#Repository
#Transactional
public interface ItemRepository extends JpaRepository<Item, Long> {
Item findByItemId(Long id);
#Modifying
#Query("UPDATE Item i SET i.supplier= :val WHERE i.supplier = :id")
void deleteSupplierId(#Param("val") String val, #Param("id") Long id);
}
MasterService
void deleteItemSupplierId(String val, Long id);
MasterServiceImpl
#Override
public void deleteItemSupplierId(String val, Long id) {
itemRepository.deleteSupplierId(val, id);
}
MasterController
#GetMapping("/supplier/delete")
public String deleteSupplier(#RequestParam Long supplierId) {
masterService.deleteItemSupplierId(null, supplierId);
masterService.deleteBySupplierId(supplierId);
return "redirect:/master/supplier/list?supplierDeleted";
}
You can do that by using cascade types, for example
#OneToMany(cascade = CascadeType.REMOVE)
I am doing a API Rest with Spring Boot and MySQL and I have the next relation:
To do this, the first thing I do is create a type #Embeddable.
import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.persistence.Entity;
import javax.persistence.ManyToOne;
import java.io.Serializable;
import java.util.Objects;
#Embeddable
public class UserInterestKey implements Serializable {
#Column(name = "interest_id",nullable = false)
private long interestId;
#Column(name = "user_id",nullable = false)
private long userId;
public UserInterestKey() {
}
public UserInterestKey(long interestId, long userId) {
this.interestId = interestId;
this.userId = userId;
}
//get and set for interestId and userId
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
UserInterestKey that = (UserInterestKey) o;
return Objects.equals(interestId, that.interestId) &&
Objects.equals(userId, that.userId);
}
#Override
public int hashCode() {
return Objects.hash(interestId, userId);
}
}
Then, I create the entity that uses the EmbeddedId type:
import javax.persistence.*;
import javax.validation.constraints.NotNull;
#Entity
#Table(name = "rel_user_interest")
public class RelUserInterest {
#EmbeddedId
private UserInterestKey id;
#ManyToOne(fetch = FetchType.LAZY)
#MapsId("userId")
#JoinColumn(name = "user_id", nullable = false)
User user;
#ManyToOne(fetch = FetchType.LAZY)
#MapsId("interestId")
#JoinColumn(name = "interest_id", nullable = false)
Interest interest;
int priority;
public RelUserInterest() {
}
//get and set for id, user, interest and priority
This is the User entity:
import com.fasterxml.jackson.annotation.JsonIgnore;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
import java.util.HashSet;
import java.util.Set;
#Entity
public class User {
#Id #GeneratedValue private long id;
#NotNull
#Column (unique = true) private String email;
#NotNull private int age;
#NotNull private String genre;
#NotNull private String userName;
#NotNull private String password;
#OneToMany(mappedBy = "user")
#NotNull
Set<RelUserInterest> priority = new HashSet<>();
public User (){
}
public User(#NotNull String email, #NotNull int age, #NotNull String genre, #NotNull String userName, #NotNull String password) {
this.email = email;
this.age = age;
this.genre = genre;
this.userName = userName;
this.password = password;
}
// set and get for id, email, age, genre, username, password and priority.
}
This is the interest entity:
import javax.persistence.*;
import javax.validation.constraints.NotNull;
import java.util.HashSet;
import java.util.Set;
#Entity
public class Interest {
#Id
#GeneratedValue
private long id;
#NotNull private String nameInterest;
#OneToMany(mappedBy = "interest")
#NotNull
Set<RelUserInterest> priority = new HashSet<>();
public Interest() {
}
public Interest(String nameInterest) {
this.nameInterest = nameInterest;
}
// get and set for id, nameInterest and priority
}
This is the part of the controller
#PostMapping("/signup")
public ResponseEntity<?> addUser(#Validated #RequestBody NewUserDTO userDTO, BindingResult result) {
//more code
User user = new User(userDTO.getEmail(), userDTO.getAge(), userDTO.getGenre(), userDTO.getUserName(),userDTO.getPassword());
Set<InterestDTO> interestStr = userDTO.getInterest();
RelUserInterest rel;
for(InterestDTO interest: interestStr){
rel = new RelUserInterest();
rel.setPriority(interest.getPriority());
Interest i = interestService.getInterestByName(interest.getNameInterest());
rel.setInterest(i);
rel.setUser(user);
user.getPriority().add(rel);
i.getPriority().add(rel);
}
usersService.addUser(user);
return new ResponseEntity(new Mensaje("Usuario aƱadido"), HttpStatus.CREATED);
}
PROBLEM: The database is well created as you can see in the first image. The problem is that the intermediate table (rel_user_interest) is empty, nothing is inserted. Does anyone find any problem in the code and can help me please?
UPDATE 17/11/2020
This is a JSON example that I want to send
{
"email": "sd#email.com",
"userName": "sd",
"password": "1234",
"passwordConfirm": "1234",
"age": 21,
"genre": "Women",
"roles": [
"user"
],
"interest": [
{
"nameInterest": "Museum",
"priority": 5
}
]
}
I followed this tutorial Many-to-Many Using a Composite Key
Spring Boot version: 2.3.5.RELEASE
Java version: 1.8
I'm trying to do a simple #OneToMany relationship between contract and asset. But when hibernate tries to save , it's comming as null. What am I doing wrong?
#Entity
#Data
#EqualsAndHashCode
#NoArgsConstructor
#Table(name = "contracts")
public class Contract {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Integer id;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "contractId")
private List<Asset> assets;
}
#Entity
#Data
#Table(name = "assets")
public class Asset {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Integer id;
#ManyToOne
#JoinColumn(name = "contractId", referencedColumnName = "id")
private Contract contractId;
}
#Repository
public interface ContractRepository extends CrudRepository<Contract, Integer> {
}
private void mapAndSave(ContractDTO contractDTO) {
Contract contractToSave = new Contract();
ModelMapper mapper = BiModelMapper.createModelMapperDtoToEntity();
mapper.map(contractDTO, contractToSave);
contractRepository.save(contractToSave);
}
Caused by: java.sql.SQLIntegrityConstraintViolationException: Column 'contractId' cannot be null
The solution I was able to do is change my column table Asset.contractId to NOT NULL. Because Hibernate tries to insert the row, and after that updates the contractId.
And I change to unidirectional relationship, using only #OneToMany on Contract side.
I have simple code like:
#Transactional(readOnly = true, timeout = 10)
public List<MyClass> findThem() {
Criteria criteria = getSession().createCriteria(MyClass.class);
#SuppressWarnings("unchecked")
List<MyClass> theList = criteria.list();
return theList;
}
When I use this for the query, I get back 942 items, with duplicated items in the list. I don't see the pattern about which ones are duplicated just yet.
If I query with DB directly, I get back 138 records. 138 is the correct number of results:
SELECT count(*) FROM theschema.MY_CLASS;
I tried using the class with and without Lombok's #EqualsAndHashCode(exclude="id") on MyClass and also just not including any equals() implementation, thinking this was the cause - but no luck.
I've recently upgraded from MySQL 5.6 to MySQL 5.7.17 but I'm still on Hibernate 4.3.8.Final and HikariCP 2.5.1. The query has no WHERE clauses or anything very complicated. It may not matter, but I'm on Spring 4.3.3.RELEASE with mysql-connector-java 5.1.39.
Any other suggestions where to look? I'm going to turn on more debug logging and take a closer look in the meantime.
Update:
I'm able to correct this with criteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY); but not sure why it's now necessary.
Update 2
Here's MyClass. It has more basic properties, but I excerpted them for brevity. Some of the names are renamed for privacy reasons.
import base.domain.model.Persistable;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.hibernate.validator.constraints.NotEmpty;
import javax.persistence.*;
import java.math.BigDecimal;
import java.util.*;
#NoArgsConstructor
#Entity
#Table(name = "MY_CLASS")
public class MyClass implements Persistable {
#Getter
#Setter
#Id
#Column(name = "MY_CLASS_ID")
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#Getter
#Setter
private ClassB classb;
#Getter
#Setter
#ManyToOne
#JoinColumn(name = "CLASS_C_ID")
private ClassC classC;
#Getter
#Setter
#Transient
private Integer daysOpen;
#Getter
#Setter
#OneToOne
#JoinColumn(name = "CLASS_D_ID")
private ClassD classD;
#Getter
#Setter
#NotEmpty
private String briefDescription;
#Getter
#Setter
#Column(length = 1000)
private String details;
#Getter
#Setter
#OneToOne
#JoinColumn(name = "COMPANY_ID")
private Company company;
#Getter
#Setter
#Transient
private BigDecimal cost;
#Getter
#Setter
#ManyToMany(cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})
#JoinTable(name = "MY_CLASS_TAG",
foreignKey = #ForeignKey(name = "FK_MY_CLASS_TAG_REQUEST"),
joinColumns = #JoinColumn(name = "MY_CLASS_ID"),
inverseJoinColumns = #JoinColumn(name = "TAG_ID"))
private Set<Tag> tags = new HashSet<>(10);
#Getter
#Setter
#ManyToMany(cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})
#JoinTable(name = "MY_CLASS_ASSIGNEE",
foreignKey = #ForeignKey(name = "FK_MY_CLASS_ASSIGNEE"),
joinColumns = #JoinColumn(name = "MY_CLASS_ID"),
inverseJoinColumns = #JoinColumn(name = "ASSIGNEE_ID"))
private Set<Account> assignees = new HashSet<>(0);
#Getter
#Setter
#OneToMany(cascade = CascadeType.ALL, mappedBy = "myClass")
private List<MyClassHistory> historyList = new ArrayList<>(1);
private static final long serialVersionUID = 1L;
}
Update 3:
I am also able to get the correct results using HQL (abridged) without the result transformer:
String hql = "from MyClass myClass";
Query q = getSession().createQuery(hql);
List<MyClass> myClasses = q.list();
return myClasses;
Going to compare the SQL output for each (there's a lot of output to try to understand).
there must be some join happening in the query, which increases resultset and hence your count,often I face similar issue, you can try to take data in Set instead of list, or observe the actual query fired in DB.