I am trying to implement the below example for #MapKeyColumn. There is a OnetoMany relationship between the Company and Persons. However I am getting the below error when I try to persist the Person instance since that is the owner of the relationship:
Caused by: java.sql.SQLException: Field 'name_emp' doesn't have a default value
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:129)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:975)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1114)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1062)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeLargeUpdate(ClientPreparedStatement.java:1383)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdate(ClientPreparedStatement.java:1047)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:208)
... 20 more
Person Entity
#Entity
public class Person {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
int id;
String name;
#ManyToOne(cascade=CascadeType.PERSIST)
//#JoinColumn(name="company_id")
Company company;
public Person()
{}
public Person(String name) {
super();
this.name = name;
}
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 Company getcompany() {
return company;
}
public void setcompany(Company c) {
this.company = c;
}
}
Company Entity
#Entity
public class Company {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
int id;
String name;
#OneToMany(cascade=CascadeType.PERSIST,mappedBy="company")
#MapKeyColumn(name="name_emp")
Map<String,Person> persons= new HashMap<>();
public Company()
{}
public Company(String name) {
super();
this.name = name;
}
public Map<String,Person> getPersons() {
return persons;
}
public void setPersons(Map<String,Person> persons) {
this.persons = persons;
}
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;
}
}
MainTest
Person p1 = new Person("jack");
Company c= new Company("ABCORP");
p1.setcompany(c);
session.persist(p1);
The problem might occur because the relationship is not set in the company instance.
Could you try to add the person to the company ether by calling c.getPersons().add(p1.getName(), p1) or by changing the setcompany(...) method to
public void setcompany(Company c) {
c.getPersons().add(this.getName(), this)
this.company = c;
}
Related
I Have a rest controller that is not de-serializing the array type in json..
#PostMapping()
#ResponseBody
public ResponseEntity<Team> createteam(#RequestBody Team team) throws JsonProcessingException {
Team savedTeam = teamService.createTeam(team);
return new ResponseEntity<Team>(savedTeam, HttpStatus.CREATED);
}
below is my entity class.
#Entity
#JsonIdentityInfo(generator = IntSequenceGenerator.class)
public class Team {
#Id
#GeneratedValue
private Long id;
private String name;
#OneToMany(mappedBy = "team", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private List<Developer> developers;
public Team(String name, List<Developer> developer) {
super();
this.name = name;
this.developers = developer;
}
public Team() {
super();
}
public List<Developer> getDeveloper() {
return developers;
}
public void setDeveloper(List<Developer> developer) {
this.developers = developer;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
and my other entity..
package com.demo.springbootdemo.entity;
#Entity
#JsonIdentityInfo(generator = IntSequenceGenerator.class)
public class Developer {
#Id
#GeneratedValue
private Long id;
#ManyToOne
private Team team;
private Long phone;
private String name;
public Developer() {
super();
}
public Developer(Team team, Long phone, String name) {
super();
this.team = team;
this.phone = phone;
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Team getTeam() {
return team;
}
public void setTeam(Team team) {
this.team = team;
}
public Long getPhone() {
return phone;
}
public void setPhone(Long phone) {
this.phone = phone;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
below is my JSON payload, which returns null "developers" when i call the post method.i have tried changing the number of properties in json payload but, still i am not able to figure out why my json is not de-serilaized to List of developers..
{
"id": 1004,
"name": "claim",
"developers": [
{
"id" :1,
"phone": 9092123,
"name": "raina"
}
]
}
I am not sure what Deserializer are you using, but with the Jackson ObjectMapper I solved it changing the method names of the getter and setter for the developers properties: they should be called setDevelopers and getDevelopers. In your code they are called setDeveloper and getDeveloper, without the final S.
To avoid problem like these, I just add Lombok as a dependency and it takes care of creating setters and getters.
With Lombok your Team class would look like this:
// ... more imports here...
import lombok.Data;
#Data
#JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class)
public class Team {
#Id
#GeneratedValue
private Long id;
private String name;
#OneToMany(mappedBy = "team", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private List<Developer> developers;
}
You may need to add more Lombok annotations for generating constructor methods according to your needs.
I want a Bi-Directional mapping on my 2 Entities(PersonDetail,
PassportDetail) but it seems that it doesn't work fine. I want that
PersonDetail has a PassportId and PassportDetail has a PersonId as well.
My PersonDetail java Code
#Entity
#Table(name="persondetail")
public class PersonDetail {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="person_id")
private int id;
#Column(name="person_name")
private String name;
#Column(name="person_phone")
private long phone;
#OneToOne(mappedBy="person",cascade=CascadeType.ALL)
#JoinColumn(name="passport_id")
private PassportDetail passport;
public PassportDetail getPassport() {
return passport;
}
public void setPassport(PassportDetail passport) {
this.passport = passport;
}
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 getPhone() {
return phone;
}
public void setPhone(long phone) {
this.phone = phone;
}
#Column(name="passport_id")
private int passort_id;
public int getPassort_id() {
return passort_id;
}
public void setPassort_id(int passort_id) {
this.passort_id = passort_id;
}
}
Here is my PassportDetail Java Code
#Entity
#Table(name="PassportDetail")
public class PassportDetail {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="passport_id")
private int id;
#Column(name="passport_number")
private String passportNumber;
#Column(name="country_name")
private String country;
#Column(name="issue_date")
#Temporal(TemporalType.DATE)
private Date date;
#OneToOne
#JoinColumn(name="person_id")
private PersonDetail person;
public String getPassportNumber() {
return passportNumber;
}
public void setPassportNumber(String passportNumber) {
this.passportNumber = passportNumber;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public PersonDetail getPerson() {
return person;
}
public void setPerson(PersonDetail person) {
this.person = person;
}
}
Here is the Output in MySql
Here is the Output of Both table as you can clearly see the problem i.e PersonDetail has a column named passport_id but it dosesn't have any value
Here is the insertion code
public class MappingMain {
public static void main(String[] args) {
PersonDetail person=new PersonDetail();
PassportDetail passport = new PassportDetail();
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-mm-dd");
person.setName("Ankit");
person.setPhone(790148565);
passport.setCountry("india");
try {
passport.setDate(sdf.parse("2018-04-15"));
}
catch(Exception e)
{
}
passport.setPassportNumber("QUJMZ123");
passport.setPerson(person);
person.setPassport(passport);
PersonDao dao=new PersonDao();
dao.save(person);
}
Here is the DAO class
public class MappingDao {
SessionFactory sf=Util.getSessionFactory();
public void save(UserDemo user)
{
Session session=sf.openSession();
session.beginTransaction();
session.save(user);
session.getTransaction().commit();
session.close();
}
}
Problem: it works till i try to add Student obejcts to Database, but the tables are being created correctly .
I can't simplify the post any further. But it's mainly code that doesn't require a lot of reading, it's a simple spring data repository service model. I posted it all due to the fact idk what am i doing wrong. Problem is in the JPA mapping.
I got the example from over here http://www.java2s.com/Tutorial/Java/0355__JPA/OneToManyBidirectional.htm
MDOELS
#Entity
public class Department {
#Id #GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
private String name;
#OneToMany(mappedBy="department")
private Collection<Student> students;
public Department() {
}
public Department(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String deptName) {
this.name = deptName;
}
public Collection<Student> getStudents() {
return students;
}
public void setStudent(Collection<Student> students) {
this.students = students;
}
public String toString() {
return "Department id: " + getId() +
", name: " + getName();
}
}
#Entity
public class Student {
#Id #GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
private String name;
#ManyToOne (cascade=CascadeType.ALL)
private Department department;
public Student() {
}
public Student(String name, Department department) {
this.name = name;
this.department = department;
}
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 Department getDepartment() {
return department;
}
public void setDepartment(Department department) {
this.department = department;
}
public String toString() {
return "\n\nID:" + id + "\nName:" + name + "\n\n" + department;
}
}
REPOSITORIES
#Repository
public interface DepartmentRepository extends JpaRepository<Department, Integer> {
Department findByName(String name);
}
#Repository
public interface StudentRepository extends JpaRepository<Student, Integer> {
Student findByName(String name);
}
SERVICES
#Service
public class StudentService {
private final StudentRepository studentRepository;
#Autowired
public StudentService(StudentRepository studentRepository) {
this.studentRepository = studentRepository;
}
public void addToDatabase(Student student) {
this.studentRepository.saveAndFlush(student);
}
public Student getStudentByName(String name) {
return studentRepository.findByName(name);
}
}
#Service
public class DepartmentService {
private final DepartmentRepository departmentRepository;
#Autowired
public DepartmentService(DepartmentRepository departmentRepository) {
this.departmentRepository = departmentRepository;
}
public void addToDataBase(List<Department> department) {
this.departmentRepository.save(department);
department.forEach(this.departmentRepository::saveAndFlush);
}
public Department getDepartmentByName(String name){
return this.departmentRepository.findByName(name);
}
}
My main method
#Component
public class Terminal implements CommandLineRunner {
private final StudentService studentService;
private final DepartmentService departmentService;
#Autowired
public Terminal(StudentService studentService, DepartmentService departmentService) {
this.studentService = studentService;
this.departmentService = departmentService;
}
#Override
public void run(String... strings) throws Exception {
Department department = new Department("dep1");
Department department1 = new Department("dep2");
Department department2 = new Department("dep3");
Department department3 = new Department("dep4");
List<Department> departments = new ArrayList<>(Arrays.asList(department, department1, department2, department3));
this.departmentService.addToDataBase(departments);
//
Student student = new Student("pesho", department);
Student student11 = new Student("gosho", department1);
this.studentService.addToDatabase(student11);
this.studentService.addToDatabase(student);
student = new Student("sasho", department2);
this.studentService.addToDatabase(student);
// System.out.println(this.studentService.getStudentByName("gosho").getDepartment1());
// System.out.println("CHECKING ONE TO ONE BIDIRECTIONAL: " + this.departmentService.getDepartmentByName("dep1").getStudent());
}
}
So here when i try to add students in the students table it gives an error
The error is the fallowing
Caused by: org.hibernate.PersistentObjectException: detached entity passed to persist: app.models.Department
you added cascade= CascadeType.ALL for Department in Student class and save departments separete. this.departmentService.addToDataBase(departments);
fix : dont call
departmentService.addToDataBase(departments);
or remove CascadeType.ALL from Student
Well I can't understand you problem completely but here's what I would like to add. Cascading for add operation is not implemented or it's incomplete. Hope it helps.
My document entity class is
#Entity
#Table(name="Document_Directory")
public class DocumentDirectoryEntity{
private int id;
private String name;
private DocumentDirectoryEntity parentDirectory;
private List<DocumentDirectoryEntity> childDirectoryList;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
#Column(name="name", length=250, nullable= false)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="parent_dir_id")
public DocumentDirectoryEntity getParentDirectory() {
return parentDirectory;
}
public void setParentDirectory(DocumentDirectoryEntity parentDirectory) {
this.parentDirectory = parentDirectory;
}
#OneToMany(mappedBy="parentDirectory", cascade=CascadeType.ALL, fetch=FetchType.LAZY, orphanRemoval=true)
public List<DocumentDirectoryEntity> getChildDirectoryList() {
return childDirectoryList;
}
public void setChildDirectoryList(List<DocumentDirectoryEntity> childDirectoryList) {
this.childDirectoryList = childDirectoryList;
}
}
I want delete a document but before delete, i want to change its child's parent. But I am not able to do it. code is:-
DocumentDirectoryEntity documentDirectoryEntity = documentDirectoryDao.findById(1);
DocumentDirectoryEntity documentDirectoryEntity1 = documentDirectoryDao.findById(2);
List<DocumentDirectoryEntity> childDirectoryList = documentDirectoryEntity.getChildDirectoryList();
DocumentDirectoryEntity childDirectory = childDirectoryList.get(0);
childDirectory.setParentDirectory(documentDirectoryEntity1);
documentDirectoryDao.update(childDirectory);
documentDirectoryDao.delete(documentDirectoryEntity);
when i delete object documentDirectoryEntity then childDirectory row is also removed.
I have the following code that is not working properly.
testprovincia exist on data base and the partidos variable is a list that I am sure is not empty but is never persisted too.
mgr = getPersistenceManager();
Query query = mgr.newQuery(Provincia.class);
query.setFilter("name == nameParam");
query.declareParameters("String nameParam");
List<Provincia> results = (List<Provincia>) query.execute("testprovincia");
Provincia prov = results.get(0);
insertPartidos(partidos);
prov.setPartidos(partidos);
mgr.makePersistent(prov);
query.closeAll();
mgr.close();
InsertPartidos method:
private void insertPartidos(List<Partido> partidos){
for (Partido partido : partidos) {
log.info(partido.getName());
mgr.makePersistent(partido);
}
}
The question is why I never see the list I added to prov variable on the database? Is allways empty.
Here are my classes:
#PersistenceCapable(identityType = IdentityType.APPLICATION)
public class Provincia {
public Provincia(String name) {
super();
this.name = name;
}
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key id;
#Persistent
private String name;
#Persistent(mappedBy = "provincia")
#Order(extensions = #Extension(vendorName="datanucleus",key="list-ordering", value="name asc"))
private List<Partido> partidos;
public Key getId() {
return id;
}
public void setId(Key id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Partido> getPartidos() {
return partidos;
}
public void setPartidos(List<Partido> partidos) {
this.partidos = partidos;
}
}
#PersistenceCapable(identityType = IdentityType.APPLICATION)
public class Partido {
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key id;
#Persistent
private String name;
#Persistent
private Provincia provincia;
public Partido(){
}
public Partido(Key id) {
super();
this.id = id;
}
public Partido(Key id, String name, Provincia prov) {
super();
this.id = id;
this.name = name;
this.provincia = prov;
}
public Partido(String name, Provincia prov) {
super();
this.name = name;
this.provincia = prov;
}
public Key getId() {
return id;
}
public void setId(Key id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Provincia getProvincia() {
return provincia;
}
public void setProvincia(Provincia provincia) {
this.provincia = provincia;
}
}
Maybe using the other way of updating. If testprovincia already exists, using the method described here might do the trick for you. Instead of using makepersistent, grab your data with the persistence manager and straight update it.
That or use standard datastore's db (or ndb) puts, as explained here? Do you REALLY need the JDO?