Hibernate Error SQLGrammarException (MySQL) - java

I try to get back a list of elements in an instance Criteria. In the execution I obtain this exception. What is the problem ?
The name of my database is "TransPlusBD".
The name of my table is a "gerant".
But the error indicates me that he(it) does not find the table "TransPlusDB.gerant_gerant", yet this table does not exist.
Normally we have to have his "TransPlusDB.gerant".
Code of the configuration
properties = new Properties();
properties.put("hibernate.dialect","org.hibernate.dialect.MySQLInnoDBDialect");
properties.put("hibernate.connection.driver_class","com.mysql.jdbc.Driver");
properties.put("hibernate.connection.url","jdbc:mysql://(cloud amazone aws).amazonaws.com:3306/TransPlusDB");
properties.put("hibernate.connection.username","xxx");
properties.put("hibernate.connection.password","xxxxxxxxxxxx");
properties.put("hibernate.connection.pool_size","4");
configuration = new Configuration();
configuration.setProperties(properties);
configuration.addAnnotatedClass(Administrator.class);
configuration.addAnnotatedClass(AutoGare.class);
configuration.addAnnotatedClass(Car.class);
configuration.addAnnotatedClass(City.class);
configuration.addAnnotatedClass(Company.class);
configuration.addAnnotatedClass(transplus.models.Configuration.class);
configuration.addAnnotatedClass(DateDeparture.class);
configuration.addAnnotatedClass(Departure.class);
configuration.addAnnotatedClass(HoursDeparture.class);
configuration.addAnnotatedClass(Luggage.class);
configuration.addAnnotatedClass(Manager.class);
configuration.addAnnotatedClass(Passenger.class);
configuration.addAnnotatedClass(PlanningVoyage.class);
configuration.addAnnotatedClass(Route.class);
configuration.addAnnotatedClass(Stopover.class);
configuration.addAnnotatedClass(SysAdmin.class);
configuration.addAnnotatedClass(Ticket.class);
configuration.addAnnotatedClass(TypeCar.class);
configuration.addAnnotatedClass(ModificationLuggage.class);
configuration.addAnnotatedClass(ModificationTicket.class);
configuration.addAnnotatedClass(PassageRoute.class);
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
.applySettings(configuration.getProperties()).build();
Code of my class
#Entity
#Table(name = "gerant")
public class Manager implements Serializable // Table Gerant
{
#Id
#GeneratedValue
#Column(name = "code_gerant")
private long code_manager;
#Column(name = "matricule_gérant",unique = true)
private String matricule_manager;
#Column(name = "nom_gerant")
private String lastName_manager;
#Column(name = "prenom_gerant")
private String firstName_manager;
#Column(name = "password_gerant",nullable = false)
private String password_manager;
#Column(name = "login_gerant",unique = true,nullable = false)
private String login_manager;
#Column(name = "poste_gerant")
private String function_manager;
#Column(name = "actif_gerant")
private boolean enabled_manager;
#Enumerated(EnumType.ORDINAL)
#Column(name = "privilege_gerant")
private Privilege privilege;
#ManyToOne
#JoinColumn(name = "code_manager", foreignKey = #ForeignKey(name = "fk_gerant_manager"))
private Administrator administrator;
#ManyToOne
#JoinColumn(name = "over_gerant", foreignKey = #ForeignKey(name = "fk_over_gerant"))
private Manager overManager;
#Expose // Annotation for Gson
#OneToMany(cascade = CascadeType.ALL,orphanRemoval = false)
private List<Manager> underManagers = new ArrayList<>();
Code for the recovery of the list.
public String getAllManager()
{
if(session.isOpen())
{
Transaction transaction = null;
try
{
transaction = session.beginTransaction();
transaction.begin();
Criteria criteria = session.createCriteria(Manager.class);
List list = criteria.list();
transaction.commit();
if(list != null)
{
if(!list.isEmpty())
return serializeTab(list);
}
return null;
}
catch (Exception e)
{
if(transaction != null)
transaction.rollback();
e.printStackTrace();
}
}
return null;
}
Here is the raised exception
this = {ServiceManager#3681}
transaction = {TransactionImpl#3683}
transactionCoordinator = {JdbcResourceLocalTransactionCoordinatorImpl#3979}
transactionDriverControl = {JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl#3980}
valid = false
e = {SQLGrammarException#3954} "org.hibernate.exception.SQLGrammarException: could not extract ResultSet"
sqlException = {MySQLSyntaxErrorException#3958} "com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'TransPlusDB.gerant_gerant' doesn't exist"
SQLState = "42S02"
vendorCode = 1146
next = null
detailMessage = "Table 'TransPlusDB.gerant_gerant' doesn't exist"
cause = {MySQLSyntaxErrorException#3958} "com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'TransPlusDB.gerant_gerant' doesn't exist"
stackTrace = {StackTraceElement[0]#3961}
suppressedExceptions = {Collections$UnmodifiableRandomAccessList#3962} size = 0
sql = "n/a"
Help I PLEASE

The table gerant_gerant is a join table for a self association for this
#OneToMany(cascade = CascadeType.ALL,orphanRemoval = false)
private List<Manager> underManagers = new ArrayList<>();
You need to let Hibernate to create this table using the hibernate.hbm2ddl.auto property or you can create it manually with constraints ( a foreign key, a unique key).
You can specify a join table name with the #JoinTable annotation.

I added this line of code at the level of the configuration
properties.put("hbm2ddl.auto","validate");
Then this code at the level of my class
#OneToMany(cascade = CascadeType.ALL,orphanRemoval = false,mappedBy = "overManager")
private List<Manager> underManager;
Thank

Related

Entity Manager not auto increasing ID

I'm trying to run a UT but is failing at the #Before method. This is the error:
Caused by: org.h2.jdbc.JdbcSQLException: Unique index or primary key violation: "UK_PBNJJ4MCIQ51S0SJV9U3J2WQ4_INDEX_5 ON PUBLIC.XACTIVITYCONTENTTYPE(CONTENTTYPE_ID) VALUES (19, 1)"; SQL statement:
insert into XACTIVITYCONTENTTYPE (ACTIVITY_ID, CONTENTTYPE_ID) values (?, ?) [23505-197]
I have an array of object(ActivityEntity) which I'm initializing and persisting in a H2 DB:
for (int i = 0; i < activities.length; i++) {
Date createdDate = new Date();
ActivityEntity activity = new ActivityEntity();
activity.setType(ActivityType.valueOf(properties.getType()));
activity.setLabel(ActivityLabel.valueOf(properties.getLabel()));
activity.setStatus(Status.valueOf(properties.getStatus()));
activity.setDeliveryType(DeliveryType.valueOf(properties.getDeliveryType()));
activity.setSubject(em.find(SubjectEntity.class, subjectId));
activity.setFontSize(FontSize.valueOf(properties.getFontSize()));
activity.setEstimatedTime(ESTIMATED_TIME);
activity.setPlannedTime(properties.getPlannedTime());
activity.setInteractivityType(InteractivityType.valueOf(properties.getInteractivityType()));
activity.setAudience(Audience.valueOf(properties.getAudience()));
activity.setPurpose(Purpose.valueOf(properties.getPurpose()));
activity.setAcademicLevel(AcademicLevel.valueOf(properties.getAcademicLevel()));
activity.setEnvironment(Environment.valueOf(properties.getEnvironment()));
activity.setInstructionMethod(InstructionMethod.valueOf(properties.getInstructionMethod()));
activity.setCreatedBy(CREATED_BY);
activity.setCreatedDate(createdDate);
activity.setModifiedBy(CREATED_BY);
activity.setModifiedDate(createdDate);
activity.setDeprecated(properties.isDeprecated());
activity.setTemplate(properties.isTemplate());
activity.setCurriculumProvider(CurriculumProvider.valueOf(properties.getCurriculumProvider()));
activity.setShowLessonNavigator(properties.isShowLessonNavigator());
activity.setShowHeader(properties.isShowHeader());
activity.setDisplayModuleType(properties.isDisplayModuleType());
activity.setDisplayLabelType(properties.isDisplayLabelType());
activity.setShowFooter(properties.isShowFooter());
activity.setShowPagination(properties.isShowPagination());
activity.setDisplayProgressBar(properties.isDisplayProgressBar());
activity.setDisplayResources(properties.isDisplayResources());
activity.setLanguage(language);
activity.setPrimaryStatus(PrimaryStatus.valueOf(properties.getPrimaryStatus()));
activity.setIntendedDeliveryType(IntendedDeliveryType.valueOf(properties.getIntendedDeliveryType()));
activity.setNextGen(properties.isNextGen());
activity.setExcludeFromSearch(properties.isExcludeFromSearch());
activity.setExcludeFromRecommender(properties.isExcludeFromRecommender());
activity.setTeacherCreated(properties.isTeacherCreated());
activity.setTitle(TITLE + (i + 1), language);
activity.getGrades().addAll(grades);
activity.getStudentGroupings().add(new StudentGroupingEntity(properties.getStudentGroupingId()));
activity.getPedagogicalIntents().add(new PedagogicalIntentEntity(properties.getPedagogicalIntentId()));
activity.getLearnerTypes().add(new LearnerTypeEntity(properties.getLearnerTypeId()));
activity.getContentTypes().add(new ContentTypeEntity(properties.getContentTypeId()));
activities[i] = em.persist(activity);
}
em.flush();
The last set it's the property related to the error. The properties have a value of 19 for the ContentTypeId. Now, this is part of the Activity entity class:
#Entity
#Table(name = "ACTIVITY")
public class ActivityEntity {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SQ_ACTIVITY_ACTIVITY_ID")
#SequenceGenerator(name = "SQ_ACTIVITY_ACTIVITY_ID", sequenceName = "SQ_ACTIVITY_ACTIVITY_ID", allocationSize = 1)
#Column(name = "ACTIVITY_ID")
private Integer id;
//MORE FIELDS LEFT OUT FOR CLARITY
#ManyToMany
#JoinTable(name = "XACTIVITYCONTENTTYPE", joinColumns = { #JoinColumn(name = "ACTIVITY_ID", referencedColumnName = "ACTIVITY_ID") }, inverseJoinColumns = { #JoinColumn(name = "CONTENTTYPE_ID", referencedColumnName="ID") } )
private List<ContentTypeEntity> contentTypes = new ArrayList<>();
}
And here's the ContentTypeEntity class:
#Entity
#Table(name = "CONTENTTYPE")
public class ContentTypeEntity {
#Id
#Column(name = "ID")
private int id;
#Column(name = "NAME")
private String name;
#Column(name = "SEQ_NUM")
private int seqNum;
public ContentTypeEntity() {
}
public ContentTypeEntity(int id) {
this.id = id;
}
public int getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSeqNum() {
return seqNum;
}
public void setSeqNum(int seqNum) {
this.seqNum = seqNum;
}
}
If I debug, the ids for ActivityEntity is being generated correctly for each of the 3 objects that i'm putting in the array (ids=[1,2,3]). So i don't understand why the second insert is using the id=1, which is what the exception is implying. If I put one ActivityEntity in the array, everything works correctly.
You haven't pasted in all the code and you cannot assign the return type of em.persist, but i think the issue is probably related to creating multiple instances of contenttype with id 19.
Assuming content type with id 19 is already persisted and you are attempting to just create references to it rather than persist it as you have no cascade in your ManyToMany you can do something like this as this sample test code shows. The transaction are there as I don't know your tx boundaries in your code and just for the purpose of saving the contenttype separately
#Test
public void saveActivities() {
// Tx1 - Persist content type
EntityTransaction tx1 = em.getTransaction();
tx1.begin();
ContentTypeEntity contentType = new ContentTypeEntity(19);
em.persist(new ContentTypeEntity(19));
tx1.commit();
em.detach(contentType);
// Tx2 - Persist activities using a reference to content type
EntityTransaction tx2 = em.getTransaction();
tx2.begin();
for (int i = 0; i < 3; i++) {
ActivityEntity activity = new ActivityEntity();
activity.getContentTypes().add(em.getReference(ContentTypeEntity.class, 19));
em.persist(activity);
}
tx2.commit();
// assertions
}

java.sql.SQLIntegrityConstraintViolationException: Column 'library_idlibrary' cannot be null

I'm making one to many relationship in hibernate, but when i try to insert a value
in the tables I get exception that my FK in photos entity can't be null.
My parent entity:
#Table(name = "library")
#Entity
public class Book {
#OneToMany(
fetch = FetchType.LAZY,
mappedBy = "book",
cascade = CascadeType.ALL,
orphanRemoval = true
)
// setters / getters and other columns
My child entity
#Entity
#Table(name = "photos")
public class photos{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "idphotos")
private int id;
#ManyToOne(cascade = CascadeType.ALL,fetch = FetchType.LAZY)
#JoinColumn(name = "library_idlibrary")
private Book book;
// other columns
Exception:
java.sql.SQLIntegrityConstraintViolationException: Column 'library_idlibrary' cannot be null
com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:115)
com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:95)
com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:960)
com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1116)
com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1066)
I have DAO object and controller which are inserting values :
Controller:
#PostMapping( value = "/newBook",consumes = {MediaType.MULTIPART_FORM_DATA_VALUE})
public String add(#ModelAttribute("book") #Valid Book book, HttpServletResponse response, HttpServletRequest request,#RequestParam(value = "photo", required = false) List<MultipartFile> photos, #RequestParam(value = "valute",required = false) String valute,BindingResult result) {
if (result.hasErrors()) {
return "addBook";}
List<entity.photos> list = new ArrayList<>();
for (MultipartFile photo : photos) {
File file =null;
if (!photo.isEmpty()) {
try {
validateImg(photo);
file = new File(context.getRealPath("/uploadFile/" + photo.getOriginalFilename()));
Logger.getAnonymousLogger().info("THE PATH IS " + file.getAbsolutePath());
FileUtils.copyInputStreamToFile(photo.getInputStream(), file);
file.createNewFile();
} catch (IOException ex) {
result.reject("uk_UA", "Поганий тип");
return "addBook";
}
}
if (file != null) {
photos ph = new photos(photo.getOriginalFilename());
StringBuilder builder = new StringBuilder();
builder.append(file.getAbsolutePath());
Logger.getAnonymousLogger().info("SOMETHING HAS BROKEN IN LOGGING FILE");
System.out.println("INSIDE ADD METHOD ");
list.add(ph);
} else list.add(new photos(""));
}
book.getPhotosList().addAll(list);
service.add(book);
return "redirect:/books";
}
DAO:
public void add(Book user) {
currentSession().save(user);
}
Most probably you have not set your backreference from the Photo to the Book and then you cascade the persist/merge operation from the Book through the photoes collection. When you add element to collection you need to maintain both sides of the relationship. For example:
Book book = new Book();
Photo photo = new Photo();
book.addPhoto(photo);
photo.setBook(book);
//notice on the line above we set the backreference of the photo to the book.
hibernateSession.persist(book);
// now it is cascading from book to photo and it will set the foreign keys correctly.

java.lang.ClassCastException using JPA Queries

I'm trying to create Java EE web aplication but I have problem getting single result from database. Getting list of results isn't a problem.
public UserCredentialsDTO findByUsernameAndPassword(String username, String password) {
EntityManager em = getEntityManager();
TypedQuery<UserCredentialsDTO> q = em.createNamedQuery("UserCredentialsDTO.findByUsernameAndPassword", UserCredentialsDTO.class);
//Query q = em.createNamedQuery("UserCredentialsDTO.findByUsernameAndPassword", UserCredentialsDTO.class);
q.setParameter("un", username);
q.setParameter("pw", password);
UserCredentialsDTO r = null;
try{
r = q.getSingleResult(); //This line is a problem
//r = (UserCredentialsDTO)q.getSingleResult();
} catch(javax.persistence.NoResultException e) {
}
return r;
}
Using both Query and TypedQuery throws java.lang.ClassCastException
java.lang.ClassCastException: wipb.jee.clientdemo.model.UserCredentialsDTO cannot be cast to wipb.jee.clientdemo.model.UserCredentialsDTO
EDIT
UserCredentialsDTO:
#NamedQueries(
{#NamedQuery(name = "UserCredentialsDTO.findByUsernameAndPassword", query = "select uc from UserCredentialsDTO uc where uc.username=:un and uc.password=:pw")}
)
#Entity
#Table(name="USERCREDENTIALS", schema="APP")
public class UserCredentialsDTO implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password;
#OneToMany(mappedBy = "userCredentials", cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
private List<UserGroupDTO> userGroups = new LinkedList<>();
//getters and setters
public void add(UserGroupDTO userGroup) {
userGroup.setUserCredentials(this);
this.userGroups.add(userGroup);
}
public List<UserGroupDTO> getUserGroups() {
return userGroups;
}
}
This looks like an environment issue, where different classloaders are being used for JPA and the rest of the application.
Refer to this thread

Why the join table is empty

I created two tables in Oracle SQL Developer editor whos realtion is Many-To-Many, and I also created their hibernate classes 'TestEmployee' and 'TestProject' as shown below in the code. As the relation between the two classes is
Many-To-Many, however a new table named 'Employee_Project2' was created in Oracle SQL Developer editor to hold te primary keys of the other two tables 'TestEmployee' and 'TestProject'.
Values to 'TestEmployee' and 'TestProject' were inserted through Hibernate as shown belwo in section 'records insertion'.
The problem i facing now is, when I run the follwoing command:
SELECT * from Employee_Project2;
from Oracle SQL Developer Editor, i get an empty table despite it is mentioned in the annotation of the Hibernate class 'TestProject' as follwos:
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name = "Employee_Project2", joinColumns = #JoinColumn(name = "proj_id"), inverseJoinColumns = #JoinColumn(name = "emp_id"))
private Set<TestEmployee> employeesList;
Please let me know why despite there are records inserted into both 'TestEmployee' and 'TestProject' tables, the table 'Employee_Project2' is empty??
note:
I have not explicitly inserted any records into 'Employee_Project2' neither through Hibernate nor Oracle SQL Developer editor, because I expect the records "primary key" to be inserted automatically through Hibernate as the table 'Employee_Project2' is mentioned in the annotation
TestEmployee:
#Entity #Table(schema = "afk_owner", name = "Test_Employee2")
public class TestEmployee {
#Id
#Column(name = "emp_id")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequencegen")
#SequenceGenerator(name = "sequencegen", sequenceName = "afk_owner.Test_Employee_seq", allocationSize = 1)
private Long mEmpId;
#Column(name = "emp_name")
private String mEmpName;
#Column(name = "emp_experience")
private int mEmpExperience;
#ManyToMany(cascade = CascadeType.ALL, mappedBy = "employeesList")
private Set<TestProject> mProjectsList;
public Long getmEmpId() {
return mEmpId;
}
public void setmEmpId(Long mEmpId) {
this.mEmpId = mEmpId;
}
public String getmEmpName() {
return mEmpName;
}
public void setmEmpName(String mEmpName) {
this.mEmpName = mEmpName;
}
public int getmEmpExperience() {
return mEmpExperience;
}
public void setmEmpExperience(int mEmpExperience) {
this.mEmpExperience = mEmpExperience;
}
public Set<TestProject> getmProjectsList() {
return mProjectsList;
}
public void setmProjectsList(Set<TestProject> mProjectsList) {
this.mProjectsList = mProjectsList;
}
public TestEmployee(String empName, int empExperience) {
this.mEmpName = empName;
this.mEmpExperience = empExperience;
}
public TestEmployee() {
// TODO Auto-generated constructor stub
}
}
TestProject:
#Entity #Table(schema = "afk_owner", name = "Test_Project2")
public class TestProject {
#Id
#Column(name = "proj_id")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequencegen")
#SequenceGenerator(name = "sequencegen", sequenceName = "afk_owner.Test_Project_seq", allocationSize = 1)
private Long mProjId;
#Column(name = "proj_name")
private String mProjName;
#Column(name = "proj_desc")
private String mProjDesc;
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name = "Employee_Project2", joinColumns = #JoinColumn(name = "proj_id"), inverseJoinColumns = #JoinColumn(name = "emp_id"))
private Set<TestEmployee> employeesList;
public Long getmProjId() {
return mProjId;
}
public void setmProjId(Long mProjId) {
this.mProjId = mProjId;
}
public String getmProjName() {
return mProjName;
}
public void setmProjName(String mProjName) {
this.mProjName = mProjName;
}
public String getmProjDesc() {
return mProjDesc;
}
public void setmProjDesc(String mProjDesc) {
this.mProjDesc = mProjDesc;
}
public Set<TestEmployee> getEmployeesList() {
return employeesList;
}
public void setEmployeesList(Set<TestEmployee> employeesList) {
this.employeesList = employeesList;
}
public TestProject(String projName, String projDesc) {
this.mProjName = projName;
this.mProjDesc = projDesc;
}
public TestProject() {
// TODO Auto-generated constructor stub
}
}
records insertion
Session session = HibernateUtil.getCurrentSession();
Transaction transaction = session.beginTransaction();
/*empAhmad*/
TestEmployee empAhmad = new TestEmployee();
TestProject projRoadSteepnessEstimation = new TestProject();
TestProject projObjectTrackingUsingLIDAR = new TestProject();
TestProject projSalientRegionDetector = new TestProject();
TestProject projAutonomousNavigationUsingGNSSSensors = new TestProject();
Set<TestProject> empAhmadProjLists = new HashSet<>();
empAhmad.setmEmpName("Ahmad");
empAhmad.setmEmpExperience(9);
projRoadSteepnessEstimation.setmProjName("Road Steepness Est");
projRoadSteepnessEstimation.setmProjDesc("Kalman Filter, Java");
empAhmadProjLists.add(projRoadSteepnessEstimation);
projObjectTrackingUsingLIDAR.setmProjName("Object Tracking LIDAR");
projObjectTrackingUsingLIDAR.setmProjDesc("C++, OpenCV");
empAhmadProjLists.add(projObjectTrackingUsingLIDAR);
projSalientRegionDetector.setmProjName("Salient Region Detector");
projSalientRegionDetector.setmProjDesc("Java, OpenCV");
empAhmadProjLists.add(projSalientRegionDetector);
projAutonomousNavigationUsingGNSSSensors.setmProjName("Autonomous Navigation GNSS");
projAutonomousNavigationUsingGNSSSensors.setmProjDesc("Android, Kalman Filter");
empAhmadProjLists.add(projAutonomousNavigationUsingGNSSSensors);
empAhmad.setmProjectsList(empAhmadProjLists);
/*empAmr*/
TestEmployee empAmr = new TestEmployee();
TestProject projKalmanForOnlineEstimation = new TestProject();
TestProject projNonLinearControlAndFiltering = new TestProject();
TestProject projAppForHydrolicProcess = new TestProject();
Set<TestProject> empAmrProjList = new HashSet<>();
empAmr.setmEmpName("Amr");
empAmr.setmEmpExperience(5);
projKalmanForOnlineEstimation.setmProjName("Kalman For Online Estimation");
projKalmanForOnlineEstimation.setmProjDesc("Kalman Filter, Java, C++");
empAmrProjList.add(projKalmanForOnlineEstimation);
projNonLinearControlAndFiltering.setmProjName("Non-Linear Control And Filtering");
projNonLinearControlAndFiltering.setmProjDesc("C++, wavelet analysis");
empAmrProjList.add(projNonLinearControlAndFiltering);
projAppForHydrolicProcess.setmProjName("App For Hydrolic Process");
projAppForHydrolicProcess.setmProjDesc("Android, OpenCV, C++");
empAmrProjList.add(projAppForHydrolicProcess);
empAmr.setmProjectsList(empAmrProjList);
/*empAli*/
TestEmployee empAli = new TestEmployee();
Set<TestProject> empAliProjList = new HashSet<>();
empAli.setmEmpName("Ali");
empAli.setmEmpExperience(7);
empAliProjList.add(projAutonomousNavigationUsingGNSSSensors);
empAliProjList.add(projObjectTrackingUsingLIDAR);
empAliProjList.add(projKalmanForOnlineEstimation);
empAliProjList.add(projAppForHydrolicProcess);
empAli.setmProjectsList(empAliProjList);
session.persist(empAhmad);
session.persist(empAmr);
session.persist(empAli);
transaction.commit();
Because you never inserted anything in the owning side tof the association: Project.employeesList. As simple as that.
You only populated the inverse side of the association: Employee.mProjectsList, but Hibernate only cares about the owning side.

Spring-MVC, Hibernate : Creating DTO objects from Domain objects

I am working on a Spring-MVC application in which I am trying to search for List of GroupNotes in database. The mapping in my project is GroupCanvas has one-to-many mapping with GroupSection and GroupSection has one-to-many mapping with GroupNotes. Because of these mappings, I was getting LazyInitializationException. As suggested on SO, I should be converting the objects to a DTO objects for transfer. I checked on net, but couldnt find a suitable way to translate those.
I have just created a new List to avoid the error, but one field is still giving me an error. I would appreciate if anyone tells me either how to fix this error or convert the objects to a DTO objects so they can be transferred.
Controller code :
#RequestMapping(value = "/findgroupnotes/{days}/{canvasid}")
public #ResponseBody List<GroupNotes> findGroupNotesByDays(#PathVariable("days")int days, #PathVariable("canvasid")int canvasid){
List<GroupNotes> groupNotesList = this.groupNotesService.findGroupNotesByDays(days,canvasid);
List<GroupNotes> toSendList = new ArrayList<>();
for(GroupNotes groupNotes : groupNotesList){
GroupNotes toSendNotes = new GroupNotes();
toSendNotes.setMnotecolor(groupNotes.getMnotecolor());
toSendNotes.setNoteCreationTime(groupNotes.getNoteCreationTime());
toSendNotes.setMnotetag(groupNotes.getMnotetag());
toSendNotes.setMnotetext(groupNotes.getMnotetext());
toSendNotes.setAttachCount(groupNotes.getAttachCount());
toSendNotes.setNoteDate(groupNotes.getNoteDate());
toSendList.add(toSendNotes);
}
return toSendList;
}
GroupNotesDAOImpl :
#Override
public List<GroupNotes> searchNotesByDays(int days, int mcanvasid) {
Session session = this.sessionFactory.getCurrentSession();
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DAY_OF_YEAR, -days);
long daysAgo = cal.getTimeInMillis();
Timestamp nowMinusDaysAsTimestamp = new Timestamp(daysAgo);
GroupCanvas groupCanvas = (GroupCanvas) session.get(GroupCanvas.class,mcanvasid);
Query query = session.createQuery("from GroupSection as n where n.currentcanvas.mcanvasid=:mcanvasid");
query.setParameter("mcanvasid", mcanvasid);
List<GroupSection> sectionList = query.list();
List<GroupNotes> notesList = new ArrayList<GroupNotes>();
for (GroupSection e : sectionList) {
System.out.println("Section name is "+e.getMsectionname());
GroupSection groupSection = (GroupSection) session.get(GroupSection.class,e.getMsectionid());
Query query1 = session.createQuery("from GroupNotes as gn where gn.ownednotes.msectionid=:msectionid and gn.noteCreationTime >:limit");
query1.setParameter("limit", nowMinusDaysAsTimestamp);
query1.setParameter("msectionid",e.getMsectionid());
notesList.addAll(query1.list());
}
// I am getting the data below, but I get JSON errors.
for(GroupNotes groupNotes : notesList){
System.out.println("Group notes found are "+groupNotes.getMnotetext());
}
return notesList;
}
GroupCanvas model :
#Entity
#Table(name = "membercanvas")
public class GroupCanvas{
#OneToMany(mappedBy = "currentcanvas",fetch=FetchType.LAZY, cascade = CascadeType.REMOVE)
#JsonIgnore
private Set<GroupSection> ownedsection = new HashSet<>();
#JsonIgnore
public Set<GroupSection> getOwnedsection() {
return this.ownedsection;
}
public void setOwnedsection(Set<GroupSection> ownedsection) {
this.ownedsection = ownedsection;
}
}
GroupSection model :
#Entity
#Table(name = "membersection")
public class GroupSection{
#OneToMany(mappedBy = "ownednotes", fetch = FetchType.EAGER,cascade = CascadeType.REMOVE)
#JsonIgnore
private Set<GroupNotes> sectionsnotes = new HashSet<>();
public Set<GroupNotes> getSectionsnotes(){
return this.sectionsnotes;
}
public void setSectionsnotes(Set<GroupNotes> sectionsnotes){
this.sectionsnotes=sectionsnotes;
}
}
GroupNotes model :
#Entity
#Table(name="groupnotes")
public class GroupNotes{
#Id
#Column(name="mnoteid")
#GeneratedValue(strategy = GenerationType.SEQUENCE,generator = "mnote_gen")
#SequenceGenerator(name = "mnote_gen",sequenceName = "mnote_seq")
#org.hibernate.annotations.Index(name = "mnoticesidindex")
private int mnoticesid;
#Column(name = "mnotetext")
private String mnotetext;
#Column(name = "mnoteheadline")
private String mnotetag;
#Column(name = "mnotecolor")
private String mnotecolor;
#Column(name = "mnoteorder")
private double mnoteorder;
#Column(name = "attachmentcount")
private int attachCount;
#Column(name = "notedate")
private String noteDate;
#Column(name = "uploader")
private String uploader;
#Column(name = "activeedit")
private boolean activeEdit;
#Column(name = "notedisabled")
private boolean noteDisabled;
#Column(name = "noteinactive")
private boolean noteInActive;
#Column(name = "notecreatoremail")
private String noteCreatorEmail;
#Column(name = "prefix")
private String prefix;
#Column(name = "timestamp")
private Timestamp noteCreationTime;
#Transient
private boolean notRead;
#Transient
private String tempNote;
#Transient
private String canvasUrl;
#ManyToOne
#JoinColumn(name = "msectionid")
#JsonIgnore
private GroupSection ownednotes;
#JsonIgnore
public GroupSection getOwnednotes(){return this.ownednotes;}
public void setOwnednotes(GroupSection ownednotes){this.ownednotes=ownednotes;}
#JsonIgnore
public int getOwnedSectionId(){
return this.ownednotes.getMsectionid();
}
#OneToMany(mappedBy = "mnotedata",fetch = FetchType.LAZY,cascade = CascadeType.REMOVE)
#JsonIgnore
private Set<GroupAttachments> mattachments = new HashSet<>();
public Set<GroupAttachments> getMattachments() {
return this.mattachments;
}
public void setMattachments(Set<GroupAttachments> mattachments) {
this.mattachments = mattachments;
}
#OneToMany(mappedBy = "mhistory",fetch = FetchType.LAZY,cascade = CascadeType.REMOVE)
#JsonIgnore
private Set<GroupNoteHistory> groupNoteHistorySet = new HashSet<>();
public Set<GroupNoteHistory> getGroupNoteHistorySet(){
return this.groupNoteHistorySet;
}
public void setGroupNoteHistorySet(Set<GroupNoteHistory> groupNoteHistorySet){
this.groupNoteHistorySet = groupNoteHistorySet;
}
#OneToMany(mappedBy = "unreadNotes",fetch = FetchType.LAZY,cascade = CascadeType.REMOVE)
#JsonIgnore
private Set<UnreadNotes> unreadNotesSet = new HashSet<>();
public Set<UnreadNotes> getUnreadNotesSet(){
return this.unreadNotesSet;
}
public void setUnreadNotesSet(Set<UnreadNotes> unreadNotesSet){
this.unreadNotesSet = unreadNotesSet;
}
//getters and setters ignored
}
Error log :
org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: (was java.lang.NullPointerException) (through reference chain: java.util.ArrayList[0]->com.journaldev.spring.model.GroupNotes["ownedSectionId"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: (was java.lang.NullPointerException) (through reference chain: java.util.ArrayList[0]->com.journaldev.spring.model.GroupNotes["ownedSectionId"])
Kindly let me know what to do, as I am stuck on that error since some time.
What I think that happens is Jackson tries to serialize all fields in the hierarchy based on getter methods. In some situation NullPointerException is thrown in the following method:
#JsonIgnore
public int getOwnedSectionId(){
return this.ownednotes.getMsectionid();
}
replace it with the following method:
#JsonIgnore
public int getOwnedSectionId(){
if(this.ownednotes != null)
return this.ownednotes.getMsectionid();
return 1;
}
I don't have an explanation why jackson tries to serialize it when is market with #JsonIgnore but you can give a try with my proposal
I would appreciate if anyone tells me either how to fix this error or convert the objects to a DTO objects so they can be transferred.
We use DozerMapper at work for this purpose.
Instead of doing that mapping manually you might want to take a look at Blaze-Persistence Entity Views which can be used to efficiently implement the DTO pattern with JPA. Here a quick code sample how your problem could be solved
First you define your DTO as entity view
#EntityView(GroupNotes.class)
public interface GroupNoteView {
#IdMapping("mnoticesid") int getId();
String getMnotecolor();
String getMnotetag();
String getMnotetext();
String getNoteDate();
Timestamp getNoteCreationTime();
int getAttachCount();
}
Next you adapt your DAO to make use of it
#Override
public List<GroupNoteView> searchNotesByDays(int days, int mcanvasid) {
EntityManager entityManager = // get the entity manager from somewhere
CriteriaBuilderFactory cbf = // factory for query building from Blaze-Persistence
EntityViewManager evm = // factory for applying entity views on query builders
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DAY_OF_YEAR, -days);
long daysAgo = cal.getTimeInMillis();
Timestamp nowMinusDaysAsTimestamp = new Timestamp(daysAgo);
CriteriaBuilder<GroupNotes> cb = cbf.create(entityManager, GroupNotes.class, "note")
.where("noteCreationTime").gt(nowMinusDaysAsTimestamp)
.where("ownednotes.ownedcanvas.mcanvasid").eq(mcanvasid);
return evm.applySetting(EntityViewSetting.create(GroupNoteView.class), cb)
.getResultList();
}
And finally the calling code
#RequestMapping(value = "/findgroupnotes/{days}/{canvasid}")
public #ResponseBody List<GroupNoteView> findGroupNotesByDays(#PathVariable("days")int days, #PathVariable("canvasid")int canvasid){
return this.groupNotesService.findGroupNotesByDays(days, canvasid);
}

Categories