session.get() unable to resolve field,argument - java

I'm totally new to Spring MVC but still trying to understand its methods and its way of referencing things. There's a video tutorial course I'm following.
I'm trying to implement a Model through a class.
ProductDaoImpl.java
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import java.util.List;
#Repository
public class ProductDaoImpl implements ProductDao {
#Autowired
private SessionFactory sessionFactory;
#Override
public void addProduct(Product product) {
Session session = sessionFactory.getCurrentSession();
session.saveOrUpdate(product);
session.flush();
}
#Override
public Product getProductById(String id) {
Session session = sessionFactory.getCurrentSession();
Product product = (Product) session.get(Product.class.productId);
// unable to resolve the productId on get()
return product;
}
#Override
public List<Product> getAllProducts() {
return null;
}
#Override
public void deleteProduct(String id) {
}
}
ProductDao.java
import java.util.List;
public interface ProductDao {
void addProduct(Product product);
Product getProductById(String id);
List<Product> getAllProducts();
void deleteProduct(String id);
}
Product.java Model
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
#Entity
public class Product {
#Id
#GeneratedValue(strategy = GenerationType.AUTO) //tells the system that when an instance is put to database, it will be numbered automatically starting from 1
private String productName;
private String productCategory;
private String productDescription;
private double productPrice;
private String productDimension;
private String productStatus;
private int unitInStock;
private String productManufacturer;
private String productId;
}
However, it's unable to resolve the productId argument in
#Override
public Product getProductById(String id) {
Session session = sessionFactory.getCurrentSession();
Product product = (Product) session.get(Product.class.productId);
return product;
}
Is get() method able to access the fields of Product.class?
Is it asking for a field in Product.class.fieldHere?
I don't understand why it can't resolve the productId
I hope you can help.
Thanks.

The expression Product.class.productId doesn't make sense in Java. Product.class is a class literal, meaning that it's a constant value that represents the Product class, an instance of java.lang.Class. Class has no productId field.
Additionally, you should read the Javadoc for the method--it takes two parameters, a Class object (to tell it what sort of thing you're getting) and an ID. Your call should therefore be session.get(Product.class, id), and if you're using Hibernate 5, you don't need to cast to a Product.
All of this is rather moot, however--instead of hand-rolling a DAO targeting Hibernate, use JPA (which provides advantages such as a generic API, eliminating the need for casting) and Spring Data (which will autogenerate this entire DAO for you from nothing but an empty interface declaration). Additionally, you're dealing with topics that can get complicated, and you would do well to go through some exercises to learn core Java before tackling something like ORM.

session.get(Product.class.productId);
That's not valid Java code. get() expects two arguments: the entity class, and the ID of the entity to get. Arguments in Java are separated by a comma.
session.get(Product.class, productId);
But your variable isn't even named productId. It's named id. So the code should be
session.get(Product.class, id);
This is beginner Java stuff. I strongly suggest you practice with simpler Java exercises before using Spring and Hibernate, which are complex stuff.

session.get accepts two parameters, one is the class of your entity and the other one is the identifier
Product product = (Product) session.get(Product.class,id);

Related

spring boot modeling MySQL native query result with a class without creating a table entity

as the title indicate i have a native SQL query in my repository like that
#Repository
public interface BesoinRepository extends CrudRepository<Statistic, Long>{
#Query(value="SELECT etat_besoin AS 'state',COUNT(DISTINCT id) AS 'number' FROM besoin WHERE YEAR(date_creation)=:year GROUP BY etat_besoin ",nativeQuery=true)
List<Object> getStatistic(#Param("year") int year);
}
class statistic
package fr.solinum.management.model;
public class Statistic {
private String state;
private int number;
public String getState() {
return state;
}
public int getNumber() {
return number;
}
}
and this is working ok but i want the return type of getStatistic to be List<Statistic> and without creating the table Statistic in my database since i dont need it. in other word i want only to read from the database and return the result as a class. so what are the changes in the model and in the repository or in the controller or what is the optimal approach for my problem? note that i modified my model class as following to solve that but i dont think that this is the optimal or the good approach.
package fr.solinum.management.model;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "besoin")
public class Statistic {
#Id
private int id;
private String state;
private int number;
public String getState() {
return state;
}
public int getNumber() {
return number;
}
}
I can think of three approaches:
Use a Database View.
With this, you can have your entity as you want mapped as any other table to the View. You can use a Repository with no problems and you don't create a different table.
Map your List in a class and access this data from a service/DAO.
This is more labor intensive and might not "fit" with the rest of your code. Instead of using your repository directly, you would use another class. This class would do the querying of Objects and map them before delivering them to the controller or service where they are being requested. It's like doing JPA's work, really.
Take the following code as example:
#Component
public class StatisticDAO {
#Autowired
private BesoinRepository besoinRepository;
public List<Statistic> getStatistic(int year) {
List<Statistic> result = new ArrayList<>();
List<Object[]> temp = besoinRepository.getStatistic(year);
temp.stream().forEach(data -> result.add(build(data)));
return result;
}
private Statistic build(Object[] data) {
return new Statistic(String.valueOf(data[0]), (Integer)data[1]);
}
}
You'll need to change the type of the list to Object[] and check the order in which order JPA is returning the attributes.
Use interface-based projections.
I'd recommend approaches 1 and 3, but is up to you and whatever suits you better.

How to make entity class and controller for biography backend using Spring Boot?

How would you make an entity class for the backend portion of a biography page (on a site). I am unsure how to approach something like this since there aren't specific things that need to be sent from the server. I have attached some code that I used for my entity class.
Does my entity class seem like the correct way to approach creating a backend for a biography page on a site using Spring Boot?
Entity Class
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name="BIOGRAPHY")
public class Biography {
#Id
#GeneratedValue
private Long sectionId;
#Column(name = "section_title")
private String titleSection;
#Column(name = "section_text")
private String textSection;
public Long getSectionId() {
return sectionId;
}
public String getTitleSection() {
return titleSection;
}
public String getTextSection() {
return textSection;
}
#Override
public String toString() {
return "EmployeeEntity [sectionId=" + sectionId + ", titleSection=" + titleSection +
", textSection=" + textSection + "]";
}
}
Here is what you could do to implement a Spring controller that takes care of requests to the Biography entity.
Your Biography entity appears to be good
To work with it, you could take advantage of org.springframework.data.repository.CrudRepository;
Namely:
public interface BiographyRepository extends CrudRepository <Biography, Long> {
}
Spring is pretty flexible and you can organize your code the way you like it. Here is just an example of how you could organize controller code:
#RestController
#RequestMapping
public class BiographyController {
#Autowired
private BiographyRepository biographyRepository;
#RequestMapping(value = "/biography, method = RequestMethod.POST)
public #ResponseBody
Response create (HttpServletRequest request) {
//read biography object from the request
biographyRepository.save(biography);
}
//other methods...
}
Depending on what you need, a better practice could be working with the repository through a #Service in the Controller.
Hope that helps.

JPA and Java SE - Table not created for Entity class, due to additional convenience methods

I am currently writing a Netbeans platform application for persistence I use JPA 2.1 and eclipse link as provider. I have the following entity class:
import java.util.UUID;
import javafx.beans.property.SimpleStringProperty;
import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Transient;
/**
*
* #author forell
*/
#Entity
#Access(AccessType.FIELD)
public class MaterialAbc {
#Id
private String id;
//... several additional fields, that all work fine
private String substanceInstances = "";
public MaterialAbc(){
id = UUID.randomUUID().toString();
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
//.. getters and setters for the omitted fields
public String getSubstanceInstances() {
return substanceInstances;
}
public void setSubstanceInstances(String substanceInstances) {
this.substanceInstances = substanceInstances;
}
/* IF I UNCOMMENT THESE LINES THE DATATABLE IS NOT CREATED ANYMORE
IS THERE A WAY TO SOLVE THIS?
public List<SubstanceInstance2> getSubs() {
List<SubstanceInstance2> subs = new ArrayList<>();
if (!"".equals(substanceInstances)){
List<String> values = Arrays.asList(substanceInstances.split("|"));
values.forEach(value->{
subs.add(SubstanceInstance2.unSerialize(value));
});
}
return subs;
}
public void setSubs(List<SubstanceInstance2> subs) {
substanceInstances = "";
subs.forEach(sub->{
substanceInstances =substanceInstances + sub.serialize() + "|";
});
substanceInstances = substanceInstances.substring(0, substanceInstances.length()-1);
}
*/
As is the class works fine, as soon as I uncomment the two methods at the bottom that "unserialize" an object that is nested in the string substanceInstances, eclipselink is not creating the datatables anymore. Is there a way to solve this, or do need to add an extra layer.
In the meantime I actually found a solution to the problem. It seems eclipselink does not convert the Entity-bean into a table, if there are lambda expressions used in the methods. In the end I converted
values.forEach(value->{
subs.add(SubstanceInstance2.unSerialize(value));
});
into
for (String value:values){
subs.add(SubstanceInstance2.unSerialize(value));
}
And everthing works nicely. As to the reason why, no idea!

Loading collection of String into model from persistent object with hibernate and spring

When try to place a list of stings taken from an object I've loading in from a database via hibernate I'm getting this exception.
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
The method I've used to load the list is within a transaction. But when I try to place the list in the model I get the above exception. I'm taking from this that hibernate is requiring me to have even this line of code within a transaction also. But given that it's not a database operation why is this so?
#RequestMapping(value="{id}", method=RequestMethod.POST)
public String addComment(#PathVariable String id, Model model, String comment) {
personService.addComment(Long.parseLong(id), comment);
Person person = personService.getPersonById(Long.parseLong(id));
model.addAttribute(person);
List<String> comments = personService.getComments(id);
model.addAttribute(comments);
return "/Review";
}
Service object.
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
public class PersonServiceImpl implements PersonService {
private Workaround personDAO;
public PersonServiceImpl() {
}
#Transactional(propagation=Propagation.REQUIRED, readOnly=false)
public void savePerson(Person person) {
personDAO.savePerson(person);
}
#Transactional(propagation=Propagation.REQUIRED, readOnly=false)
public Person getPersonById(long id) {
return personDAO.getPersonById(id);
}
#Autowired
public void setPersonDAO(Workaround personDAO) {
this.personDAO = personDAO;
}
#Transactional(propagation=Propagation.REQUIRED, readOnly=false)
public List<Person> getAllPeople() {
return personDAO.getAllPeople();
}
#Transactional(propagation=Propagation.REQUIRED, readOnly=false)
public void addComment(Long id, String comment) {
Person person = getPersonById(id);
person.addComment(comment);
savePerson(person);
}
#Transactional(propagation=Propagation.REQUIRED, readOnly=false)
public List<String> getComments(String id) {
return personDAO.getComments(Long.parseLong(id));
}
}
DAO
import java.util.List;
import javax.persistence.ElementCollection;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
#Repository
public class PersonDAO implements Workaround {
private SessionFactory sessionFactory;
#Autowired
public PersonDAO(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
private Session currentSession() {
return sessionFactory.getCurrentSession();
}
public void addPerson(Person person) {
currentSession().save(person);
}
public Person getPersonById(long id) {
return (Person) currentSession().get(Person.class, id);
}
public void savePerson(Person person) {
currentSession().save(person);
}
public List<Person> getAllPeople() {
List<Person> people = currentSession().createQuery("from Person").list();
return people;
}
public List<String> getComments(long id) {
return getPersonById(id).getComments();
}
}
I am relatively new to Hibernate but I'll take a guess at this from my understanding of it.
By default #OneToMany collections are lazily loaded. So when you load your Person object a proxy will be created in place of your actual comments list. This list won't be loaded until you call the getter for that list (ie getComments()) as you are, and even then I don't think the full list is loaded at once, more so one by one (yep multiple db calls) as you iterate through the list or the whole list at one if you call .size().
However, I think the catch here is that you must load the list within the same session that you load the parent (Person) object. When you are loading the Person object you have a reference to the current session and then once you call the getComments() on that Person object the session is closed.
I think to keep the whole process in one session you could manually open and close your session like so in your DAO class.
public List<String> getComments(long id) {
Session session = sessionFactory.openSession();
List<String> comments = getPersonById(id).getComments();
sessionFactory.getCurrentSession().flush();
sessionFactory.getCurrentSession.close();
return comments;
}
Setting the FetchType to EAGER would solve the problem, but from what I have read it is generally not recommended unless you always need the comments loaded with the Person object.
Change a fetch type to FetchType.EAGER.
I think the problem is that you're using
currentSession()
Try to replace it with
private Session currentSession() {
return sessionFactory.openSession();
}
bcause the exception says that there isn't any open session.
You should review the Person class mapping, maybe the Comments field is mapped with the LAZY attribute and so it's not loaded in the DAO. When you call the getComments method Hibernate tries to load the attribute from the database but at that time there is no session, hence the exception. To solve this issue change the mapping attribute to EAGER.

org.hibernate.exception.SQLGrammarException: could not execute query

I use play framework !! But when I run my project it give me this
org.hibernate.exception.SQLGrammarException: could not execute query
who can help me ?
this is my model:
package models;
import java.util.*;
import javax.persistence.*;
import play.db.jpa.*;
import play.db.jpa.Model;
#Entity
#Table(name="GxkAccount")
public class GxkAccount extends Model {
private String Account;
private String Psw;
public String getAccount() {
return Account;
}
public void setAccount(String account) {
Account = account;
}
public String getPsw() {
return Psw;
}
public void setPsw(String psw) {
Psw = psw;
}
public static List<GxkAccount> GetList()
{
List<GxkAccount> infoList=GxkAccount.findAll();
return infoList;
}
}
You are completely missing the mapping annotations for the properties of your class.
P.S. Please try to follow the Java naming conventions
Using mysql, we also faced this type of issue. We found in play framework application.conf:
jpa.dialect=org.hibernate.dialect.PostgreSQLDialect
we replaced this with
jpa.dialect=org.hibernate.dialect.MySqlDialect.
This solved the problem. If you are facing this issue you can try out this configuration setting.
We also faced the same issue. We were having create in the xml and #GeneratedValue on the id column. The resolution is remove the #GeneratedValue annotation and put the value of the id manually, also the jpa takes long by default so give long value e.g 1l.
To do the auto generation follow some another rule.
The issue around the JPA related auto generated Id is resolved as below:
Modify the Person.java model class to have the following annotations for the Id attribute:
#Id
#TableGenerator(name="TABLE_GEN",table="T_GENERATOR",pkColumnName="GEN_KEY",pkColumnValue="TEST",valueColumnName="GEN_VALUE",initialValue=1,allocationSize=1)
#GeneratedValue(strategy=GenerationType.TABLE, generator="TABLE_GEN")
public Long Id;
This will create a table in the mysql schema called T_GNERATOR which will have the tracking of the next value for Id and JPA over hibernate knows how to retrieve this value. The assumption is that the initial value for the Id is 1 and it is incremented by 1 on each new insertion into it as is obvious from the attributes of the annotation.

Categories

Resources