package com.hibernatetest;
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.OneToOne;
import javax.persistence.Table;
import javax.persistence.Transient;
#Entity
#Table(name = "country")
public class Country {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name = "ctry_id")
private Integer id;
#Column(name = "ctry_name")
private String name;
#Transient
private int rank;
#ManyToOne
#JoinColumn(name="fk_cont_id")
private Continent continent;
#OneToOne(mappedBy="country")
private HeadOfState hos;
public HeadOfState getHos() {
return hos;
}
public void setHos(HeadOfState hos) {
this.hos = hos;
}
public Continent getContinent() {
return continent;
}
public Country() {
;
}
public Country(String name) {
this.name = name;
}
public void setContinent(Continent continent) {
this.continent = continent;
}
public Integer getId() {
return id;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setRank(int rank) {
this.rank = rank;
}
public int getRank() {
return rank;
}
public void addCountryToDb(Continent cont) {
continent = cont;
}
}
package com.hibernatetest;
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.OneToOne;
import javax.persistence.Table;
#Entity
#Table(name="hos")
public class HeadOfState {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name="hos_id")
private Integer id;
#Column(name="hos_name")
private String name;
#OneToOne
#JoinColumn(name="fk_ctry_id")
private Country country;
public HeadOfState() {
}
public HeadOfState(String name) {
this.name=name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Country getCountry() {
return country;
}
public void setCountry(Country country) {
this.country = country;
}
}
Session session = HibernateUtil.getSessionFactory().openSession();
try {
Transaction transaction = session.getTransaction();
Country countObj = (Country)session.get(Country.class, 62);
HeadOfState hos = new HeadOfState("ghanaKing");
hos.setCountry(countObj);
transaction.begin();
session.save(hos);
transaction.commit();
Country cont = (Country)session.get(Country.class, 62);
System.out.println("name of country is "+cont.getName());
System.out.println("name of continent is "+cont.getContinent().getName());
HeadOfState newhos = cont.getHos();
if (newhos == null) {
throw new Exception("hos obj is null even after storing it");
}
System.out.println("Name of HOS is "+cont.getHos().getName());
} catch (Exception ex) {
System.out.println("exception has happened: "+ex.getMessage());
throw ex;
} finally {
session.close();
HibernateUtil.shutdown();
}
}
Output of the SQL table even with the exception in the code
ysql> select * from hos;
host_id, hos_name, fk_ctry_id
2, ghanaKing,62
1 row in set (0.00 sec)
mysql> select * from country
ctry_id, ctry_name, fk_cont_id
60, England, 30
62, ghana, 30
Eclipse exception
name of country is ghana
name of continent is Asia
exception has happened hos obj is null even after storing it
Nov 24, 2014 2:54:29 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl stop
INFO: HHH000030: Cleaning up connection pool [jdbc:mysql://172.23.180.81:3306/test]
Exception in thread "main" java.lang.Exception: hos obj is null even after storing it
at com.hibernatetest.SqlTest.main(SqlTest.java:37)
try to set related objects on both sides of association.
When you save your instances :
hos.setCountry(countObj);
and add
countObj.setHos(hos);
You could add a convinient method to either of your instances like, therefore you would call one method insead of two.
Related
I have three entity classes Country, State, and City. Now I am trying to display the cities that come under a particular state and states that come under a particular country. but I am facing an error like
org.springframework.dao.DataAccessResourceFailureException:
Could not create JPA EntityManager;
nested exception is org.hibernate.AnnotationException:
#OneToOne or #ManyToOne on com.region.model.State.cities reference
an unknown entity: java.util.List.
Please help me out in one-to-many and many-to-one mapping for the three tables.
package com.region.model;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.SecondaryTable;
import javax.persistence.Table;
import javax.persistence.Transient;
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonManagedReference;
#Entity
#Table(name = "country")
public class Country {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column
private Integer country_id;
#Column
private String country_name;
// #Column
// private String status="active";
#Transient
private String statusCode;
#Transient
private String statusmessage;
#OneToMany(targetEntity=State.class, mappedBy="country",cascade=CascadeType.ALL, fetch = FetchType.LAZY)
#JsonBackReference
private List<State> states;
public Country() {
}
public Integer getCountry_id() {
return country_id;
}
public void setCountry_id(Integer country_id) {
this.country_id = country_id;
}
public String getCountry_name() {
return country_name;
}
public void setCountry_name(String country_name) {
this.country_name = country_name;
}
// public String getStatus() {
// return status;
// }
// public void setStatus(String status) {
// this.status = status;
// }
public String getStatusCode() {
return statusCode;
}
public void setStatusCode(String statusCode) {
this.statusCode = statusCode;
}
public String getStatusmessage() {
return statusmessage;
}
public void setStatusmessage(String statusmessage) {
this.statusmessage = statusmessage;
}
public List<State> getStates() {
return states;
}
public void setStates(List<State> states) {
this.states = states;
}
}
package com.region.model;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.Transient;
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonManagedReference;
#Entity
#Table(name = "state")
public class State {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column
private Integer sk_state_id;
#Column
private String state_name;
#Column
private String country_id;
// #Column
// private String status="active";
#Transient
private String statusCode;
#Transient String statusMessage;
#ManyToOne()
#JoinColumn(name="country_id", referencedColumnName = "country_id", insertable = false, updatable = false)
#JsonManagedReference
#OneToMany(targetEntity=City.class, mappedBy="state",cascade=CascadeType.ALL, fetch = FetchType.LAZY)
private List<City>cities;
private Country country;
public State() {
}
public Integer getSk_state_id() {
return sk_state_id;
}
public void setSk_state_id(Integer sk_state_id) {
this.sk_state_id = sk_state_id;
}
public String getState_name() {
return state_name;
}
public void setState_name(String state_name) {
this.state_name = state_name;
}
public String getCountry_id() {
return country_id;
}
public void setCountry_id(String country_id) {
this.country_id = country_id;
}
// public String getStatus() {
// return status;
// }
// public void setStatus(String status) {
// this.status = status;
// }
public String getStatusCode() {
return statusCode;
}
public void setStatusCode(String statusCode) {
this.statusCode = statusCode;
}
public String getStatusMessage() {
return statusMessage;
}
public void setStatusMessage(String statusMessage) {
this.statusMessage = statusMessage;
}
public Country getCountry() {
return country;
}
public void setCountry(Country country) {
this.country = country;
}
public List<City> getCities() {
return cities;
}
public void setCities(List<City> cities) {
this.cities = cities;
}
}
package com.region.model;
import java.lang.annotation.Repeatable;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.Transient;
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonManagedReference;
#Entity
#Table(name = "city")
public class City {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column
private Integer sk_city_id;
#Column
private String city_name;
#Column
private String state_id;
#Column
private String country_id;
#Transient
private String statusCode;
#Transient
String statusMessage;
#ManyToOne(targetEntity = State.class)
#JoinColumn(name="state_id", referencedColumnName ="sk_state_id", insertable = false, updatable = false)
private State state;
private Country country;
//private List<State>states;
public City() {
}
public Integer getSk_city_id() {
return sk_city_id;
}
public void setSk_city_id(Integer sk_city_id) {
this.sk_city_id = sk_city_id;
}
public String getCity_name() {
return city_name;
}
public void setCity_name(String city_name) {
this.city_name = city_name;
}
public String getState_id() {
return state_id;
}
public void setState_id(String state_id) {
this.state_id = state_id;
}
public String getCountry_id() {
return country_id;
}
public void setCountry_id(String country_id) {
this.country_id = country_id;
}
public String getStatusCode() {
return statusCode;
}
public void setStatusCode(String statusCode) {
this.statusCode = statusCode;
}
public String getStatusMessage() {
return statusMessage;
}
public void setStatusMessage(String statusMessage) {
this.statusMessage = statusMessage;
}
public Country getCountry() {
return country;
}
public void setCountry(Country country) {
this.country = country;
}
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
}
#Override
public String toString() {
return "City [sk_city_id=" + sk_city_id + ", city_name=" + city_name + ", state_id=" + state_id
+ ", country_id=" + country_id + ", statusCode=" + statusCode + ", statusMessage=" + statusMessage
+ "]";
}
// public List<State> getStates() {
// return states;
// }
// public void setStates(List<State> states) {
// this.states = states;
// }
}
mappedBy is only used once in a relationship between 2 classes, for the class that you want to define the relationship for both. So in the class Countries you probably don't need mappedBy at all, in the class Cities, you should put mappedBy="state", and in the class State it would make sense to put mappedBy="country"
I've been going on a hobby project of mine for a couple of weeks that is basically a quiz assistant. What it does is after a test, I'm going to check what questions and answers I got right by inputting part of the question text and retrieving the category (e.g.: Chemistry), the questions related to my search queue (e.g.: NaCl, DNA, pH) and the answers related to those questions.
All of them are stored in a MySQL database, in this manner: Database Scheme.
When I first started, I was using an EAGER way of fetching all the records (since there weren't as many as today). However, today I'm counting a large collection of questions and answers and can't seem to get the lazy loading to be working.
Considering the following simple code:
Main.java
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import org.mybizname.quizassistant.database.dao.impl.CategoryDaoImpl;
import org.mybizname.quizassistant.database.entity.impl.CategoryEntityImpl;
import org.mybizname.quizassistant.database.entity.impl.QuestionEntityImpl;
import org.mybizname.quizassistant.database.utilities.HibernateUtil;
public class Main {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
List<CategoryEntityImpl> categories = new CategoryDaoImpl().fetchAll();
categories.forEach((category) -> {
Set<QuestionEntityImpl> questions = category.getQuestions();
});
HibernateUtil.shutdown();
System.exit(0);
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
});
}
}
HibernateUtil.java
import java.util.HashMap;
import java.util.Map;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Environment;
import org.mybizname.quizassistant.database.entity.impl.AnswerEntityImpl;
import org.mybizname.quizassistant.database.entity.impl.CategoryEntityImpl;
import org.mybizname.quizassistant.database.entity.impl.QuestionEntityImpl;
public class HibernateUtil {
private static StandardServiceRegistry standardServiceRegistry;
private static SessionFactory sessionFactory;
static {
StandardServiceRegistryBuilder standardServiceRegistryBuilder = new StandardServiceRegistryBuilder();
Map<String, String> hibernateConfiguration = new HashMap<>();
hibernateConfiguration.put(Environment.DIALECT, "org.hibernate.dialect.MySQLDialect");
hibernateConfiguration.put(Environment.DRIVER, "com.mysql.jdbc.Driver");
hibernateConfiguration.put(Environment.URL, "jdbc:mysql://localhost:3306/quiz_assistant");
hibernateConfiguration.put(Environment.USER, "root");
hibernateConfiguration.put(Environment.PASS, "pwd");
hibernateConfiguration.put(Environment.QUERY_TRANSLATOR, "org.hibernate.hql.internal.classic.ClassicQueryTranslatorFactory");
hibernateConfiguration.put(Environment.CURRENT_SESSION_CONTEXT_CLASS, "org.hibernate.context.internal.ThreadLocalSessionContext");
hibernateConfiguration.put(Environment.SHOW_SQL, "true");
hibernateConfiguration.put(Environment.FORMAT_SQL, "true");
standardServiceRegistryBuilder.applySettings(hibernateConfiguration);
standardServiceRegistry = standardServiceRegistryBuilder.build();
MetadataSources metadataSources = new MetadataSources(standardServiceRegistry);
metadataSources.addAnnotatedClass(CategoryEntityImpl.class);
metadataSources.addAnnotatedClass(QuestionEntityImpl.class);
metadataSources.addAnnotatedClass(AnswerEntityImpl.class);
Metadata metadata = metadataSources.getMetadataBuilder().build();
sessionFactory = metadata.getSessionFactoryBuilder().build();
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
public static Session openSession() {
return sessionFactory.openSession();
}
public static Session getCurrentSession() {
return sessionFactory.getCurrentSession();
}
public static void shutdown() {
if (sessionFactory != null) {
StandardServiceRegistryBuilder.destroy(standardServiceRegistry);
}
}
}
GenericEntity.java
import java.io.Serializable;
import java.util.Date;
public interface GenericEntity extends Serializable {
public Long getId();
public void setId(Long id);
public Date getRegistrationTimestamp();
public void setRegistrationTimestamp(Date registrationTimestamp);
}
AbstractGenericEntity.java
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
public abstract class AbstractGenericEntity implements GenericEntity {
#Override
abstract public Long getId();
#Override
abstract public void setId(Long id);
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "registrationTimestamp", length = 19)
protected Date registrationTimestamp;
#Override
public Date getRegistrationTimestamp() {
return this.registrationTimestamp;
}
#Override
public void setRegistrationTimestamp(Date registrationTimestamp) {
this.registrationTimestamp = registrationTimestamp;
}
}
GenericDao.java
import java.util.List;
public interface GenericDao<T> {
public void persist(T entity);
public void update(T entity);
public void remove(T entity);
public void removeAll();
public List<T> fetchAll();
public List<T> fetchAllByExample(T entity);
public T findById(Long id);
public Class<T> getType();
}
AbstractGenericDao.java
import java.lang.reflect.ParameterizedType;
import java.util.List;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.mybizname.quizassistant.database.utilities.HibernateUtil;
public abstract class AbstractGenericDao<T> implements GenericDao<T> {
private final Class<T> type;
public AbstractGenericDao() {
type = (Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}
#Override
public void persist(T entity) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
#Override
public void update(T entity) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
#Override
public void remove(T entity) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
#Override
public void removeAll() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
#Override
public List<T> fetchAll() {
List<T> entities;
Session session = HibernateUtil.getCurrentSession();
Transaction transaction = session.beginTransaction();
CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
CriteriaQuery<T> criteriaQuery = criteriaBuilder.createQuery(getType());
criteriaQuery.from(getType());
entities = session.createQuery(criteriaQuery).getResultList();
transaction.commit();
return entities;
}
#Override
public List<T> fetchAllByExample(T entity) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
#Override
public T findById(Long id) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
#Override
public Class<T> getType() {
return type;
}
}
CategoryEntityImpl
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import org.mybizname.quizassistant.database.entity.AbstractGenericEntity;
#Entity
#Table(name = "category", catalog = "quiz_assistant", uniqueConstraints = #UniqueConstraint(columnNames = "name"))
public class CategoryEntityImpl extends AbstractGenericEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", unique = true, nullable = false)
private Long id;
#Column(name = "name", unique = true, nullable = false)
private String name;
#Column(name = "shortDescription")
private String shortDescription;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "category")
private Set<QuestionEntityImpl> questions = new HashSet<>();
#OneToMany(fetch = FetchType.LAZY, mappedBy = "category")
private Set<AnswerEntityImpl> answers = new HashSet<>();
public CategoryEntityImpl() {
}
public CategoryEntityImpl(String name, Date registrationTimestamp) {
this.name = name;
this.registrationTimestamp = registrationTimestamp;
}
public CategoryEntityImpl(String name, String shortDescription, Date registrationTimestamp, Set<QuestionEntityImpl> questions, Set<AnswerEntityImpl> answers) {
this.name = name;
this.shortDescription = shortDescription;
this.registrationTimestamp = registrationTimestamp;
this.questions = questions;
this.answers = answers;
}
#Override
public Long getId() {
return this.id;
}
#Override
public void setId(Long id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String getShortDescription() {
return this.shortDescription;
}
public void setShortDescription(String shortDescription) {
this.shortDescription = shortDescription;
}
public Set<QuestionEntityImpl> getQuestions() {
return this.questions;
}
public void setQuestions(Set<QuestionEntityImpl> questions) {
this.questions = questions;
}
public Set<AnswerEntityImpl> getAnswers() {
return this.answers;
}
public void setAnswers(Set<AnswerEntityImpl> answers) {
this.answers = answers;
}
}
QuestionEntityImpl
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.mybizname.quizassistant.database.entity.AbstractGenericEntity;
#Entity
#Table(name = "question", catalog = "quiz_assistant")
public class QuestionEntityImpl extends AbstractGenericEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", unique = true, nullable = false)
private Long id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "categoryId", nullable = false)
private CategoryEntityImpl category;
#Column(name = "identifier", nullable = false)
private String identifier;
#Column(name = "text", nullable = false)
private String text;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "question")
private Set<AnswerEntityImpl> answers = new HashSet<>();
public QuestionEntityImpl() {
}
public QuestionEntityImpl(CategoryEntityImpl category, String identifier, String text, Date registrationTimestamp) {
this.category = category;
this.identifier = identifier;
this.text = text;
this.registrationTimestamp = registrationTimestamp;
}
public QuestionEntityImpl(CategoryEntityImpl category, String identifier, String text, Date registrationTimestamp, Set<AnswerEntityImpl> answers) {
this.category = category;
this.identifier = identifier;
this.text = text;
this.registrationTimestamp = registrationTimestamp;
this.answers = answers;
}
#Override
public Long getId() {
return this.id;
}
#Override
public void setId(Long id) {
this.id = id;
}
public CategoryEntityImpl getCategory() {
return this.category;
}
public void setCategory(CategoryEntityImpl category) {
this.category = category;
}
public String getIdentifier() {
return this.identifier;
}
public void setIdentifier(String identifier) {
this.identifier = identifier;
}
public String getText() {
return this.text;
}
public void setText(String text) {
this.text = text;
}
public Set<AnswerEntityImpl> getAnswers() {
return this.answers;
}
public void setAnswers(Set<AnswerEntityImpl> answers) {
this.answers = answers;
}
}
AnswerEntityImpl
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.mybizname.quizassistant.database.entity.AbstractGenericEntity;
#Entity
#Table(name = "answer", catalog = "quiz_assistant")
public class AnswerEntityImpl extends AbstractGenericEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", unique = true, nullable = false)
private Long id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "categoryId", nullable = false)
private CategoryEntityImpl category;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "questionId", nullable = false)
private QuestionEntityImpl question;
#Column(name = "identifier", nullable = false)
private String identifier;
#Column(name = "text", nullable = false)
private String text;
public AnswerEntityImpl() {
}
public AnswerEntityImpl(CategoryEntityImpl category, QuestionEntityImpl question, String identifier, String text, Date registrationTimestamp) {
this.category = category;
this.question = question;
this.identifier = identifier;
this.text = text;
this.registrationTimestamp = registrationTimestamp;
}
#Override
public Long getId() {
return this.id;
}
#Override
public void setId(Long id) {
this.id = id;
}
public CategoryEntityImpl getCategory() {
return this.category;
}
public void setCategory(CategoryEntityImpl category) {
this.category = category;
}
public QuestionEntityImpl getQuestion() {
return this.question;
}
public void setQuestion(QuestionEntityImpl question) {
this.question = question;
}
public String getIdentifier() {
return this.identifier;
}
public void setIdentifier(String identifier) {
this.identifier = identifier;
}
public String getText() {
return this.text;
}
public void setText(String text) {
this.text = text;
}
}
POM Dependencies:
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.3.6.Final</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.12</version>
</dependency>
</dependencies>
There are still CategoryDaoImpl.java, QuestionDaoImpl.java and AnswerDaoImpl.java which are just empty and simply extend AbstractGenericDao.java.
Now, in Main.java, I retrieve the list of categories from the database:
List<CategoryEntityImpl> categories = new CategoryDaoImpl().fetchAll();
And then, when I am trying to loop thru them via:
categories.forEach((category) -> {
Set<QuestionEntityImpl> questions = category.getQuestions();
});
I get the following:
Exception in thread "AWT-EventQueue-0" org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: org.mybizname.quizassistant.database.entity.impl.CategoryEntityImpl.questions, could not initialize proxy - no Session
The only workaround I found so far is a long and not so clever looking hack. Instead of the loop from above, I have to do this:
categories.forEach((category) -> {
System.out.println(category.getName());
Session session = HibernateUtil.getCurrentSession();
Transaction tx = session.beginTransaction();
session.lock(category, LockMode.NONE);
Set<QuestionEntityImpl> questions = category.getQuestions();
questions.forEach((question) -> {
System.out.println("\t" + question.getText());
});
tx.commit();
});
I know this kind of questions go far, far back, but trust me that I have tried anything I could find on the web and the above example is the only solution I found that works. Maybe I am mistaken somewhere? I would do that, just that it doesn't seem right to have to rewrite the same piece of code over and over again for every view I have and every time I need to refresh some data.
Some help would be appreciated.
Thank you in advance.
I have 3 tables in my database: Professors, Disciplines and Courses.
From Professors and Disciplines to Courses it is many to one relationship.
I have tried to put foreign keys, but it does not work.
Course class:
package com.licenta.ascourses.model;
import java.io.Serializable;
import javax.persistence.AssociationOverride;
import javax.persistence.AssociationOverrides;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinColumns;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
#Entity
#Table(name="Courses")
#AssociationOverrides({
#AssociationOverride(name = "pk.discipline",
joinColumns = #JoinColumn(name = "IDDISCIPLINE")),
#AssociationOverride(name = "pk.professor",
joinColumns = #JoinColumn(name = "IDPROFESSOR")) })
public class Course implements Serializable {
private CourseId idCourse=new CourseId();
private int year;
private int semester;
public Course()
{
}
public Course(CourseId idCourse, int idDiscipline, int idProfessor,int year, int semester) {
super();
this.idCourse = idCourse;
this.year = year;
this.semester = semester;
}
#EmbeddedId
public CourseId getIdCourse() {
return idCourse;
}
public void setIdCourse(CourseId idCourse) {
this.idCourse = idCourse;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public int getSemester() {
return semester;
}
public void setSemester(int semester) {
this.semester = semester;
}
}
CourseId class for composite primary key:
package com.licenta.ascourses.model;
import java.io.Serializable;
import javax.persistence.Embeddable;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
#Embeddable
public class CourseId implements Serializable{
#ManyToOne
#JoinColumn(name="IDDISCIPLINE")
private int idDiscipline;
#ManyToOne
#JoinColumn(name="IDPROFESSOR")
private int idProfessor;
private String courseNo;
public int getIdDiscipline() {
return idDiscipline;
}
public void setIdDiscipline(int idDiscipline) {
this.idDiscipline = idDiscipline;
}
public int getIdProfessor() {
return idProfessor;
}
public void setIdProfessor(int idProfessor) {
this.idProfessor = idProfessor;
}
public String getCourseNo() {
return courseNo;
}
public void setCourseNo(String courseNo) {
this.courseNo = courseNo;
}
public boolean equals(Object o) {
return true;
}
public int hashCode() {
return 1;
}
}
Discipline class:
package com.licenta.ascourses.model;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
#Entity
#Table(name="Disciplines")
public class Discipline implements Serializable {
private int idDiscipline;
#Id
private String name;
private String description;
private int an;
private int semestru;
public Discipline()
{
}
public Discipline(int idDiscipline, String name, String description, int an, int semestru) {
super();
this.idDiscipline = idDiscipline;
this.name = name;
this.description = description;
this.an = an;
this.semestru = semestru;
}
public Discipline(int idDiscipline, String name, String description, int an, int semestru, Set<Course> courses) {
super();
this.idDiscipline = idDiscipline;
this.name = name;
this.description = description;
this.an = an;
this.semestru = semestru;
}
public int getIdDiscipline() {
return idDiscipline;
}
public void setIdDiscipline(int idDiscipline) {
this.idDiscipline = idDiscipline;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public int getAn() {
return an;
}
public void setAn(int an) {
this.an = an;
}
public int getSemestru() {
return semestru;
}
public void setSemestru(int semestru) {
this.semestru = semestru;
}
}
And this is how my Course table is made by Hibernate:
create table Courses (
courseNo varchar2(255 char) not null,
idDiscipline number(10,0) not null,
idProfessor number(10,0) not null,
semester number(10,0) not null,
year number(10,0) not null,
primary key (courseNo, idDiscipline, idProfessor)
)
So, the foreign keys does not appear. Please help me
Try to change this:
#ManyToOne
#JoinColumn(name="IDDISCIPLINE")
private int idDiscipline;
#ManyToOne
#JoinColumn(name="IDPROFESSOR")
private int idProfessor;
private String courseNo;
to this:
#ManyToOne
#JoinColumn(name="idDiscipline")
private Discipline discipline;
#ManyToOne
#JoinColumn(name="idProfessor")
private Professor professor;
private String courseNo;
I have 2 tables prod (goods) with
> id, catid(category), name, price
And cat
> with id, catname.
I wanna select like this in SQL
> select * from cat join prod on cat.id=prod.catid where
> cat.name='catname';
My query is;
Query query = session.createQuery("from prod pr join pr.cat ct with pr.catid=ct.id where ct.name=?");
I have
could not resolve property: cat of: goods.prod [from goods.prod pr
join pr.cat ct with pr.catid=ct.id where ct.name=?]
error
and in indexservice.java i have import goods.cat unused. But why? If i wrote function to use goods.prod that imports goods.cat.
Ok. that was with no mapping. I add this in cat.java
**cat.java**
package goods;
import java.io.Serializable;
import java.util.List;
import java.util.ArrayList;
import goods.prod;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.OneToMany;
import javax.persistence.Table;
#Entity
#Table(name="cat")
public class cat implements Serializable {
private Integer id;
#Id #GeneratedValue
#Column(name="id")
#OneToMany
#JoinColumn(name="catid", referencedColumnName="id")
private List<prod> prods;
private static final long serialVersionUID = -4147058093508047162L;
private String Name;
public cat() {
}
public cat(int id, String Name) {
this.id = id;
this.Name = Name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return Name;
}
public void setName(String Name) {
this.Name = Name;
}
}
prod.java
package goods;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinColumns;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import goods.cat;
import java.io.Serializable;
#Entity
#Table(name = "prod")
public class prod implements Serializable {
#Id #GeneratedValue
#Column(name = "catid")
private Long id;
private Integer catid;
private String name;
private Integer price;
public prod() {
}
public prod(Long id, Integer catid, String name, Integer price) {
this.id = id;
this.catid = catid;
this.name = name ;
this.price = price;
}
public Long getid() {
return id;
}
public void setid(Long id) {
this.id = id;
}
public Integer getcatid() {
return catid;
}
public void setcatid(Integer catid) {
this.catid = catid;
}
public String getname() {
return name;
}
public void setname(String name) {
this.name = name;
}
public Integer getprice() {
return price;
}
public void setprice(Integer price) {
this.price = price;
}
}
IndexService.java
import goods.prod;
import goods.cat;
#SuppressWarnings("unchecked")
public static ArrayList<prod> getListOfProds(String catname,String name,Integer pricel, Integer priceh){
ArrayList<prod> list = new ArrayList<prod>();
Session session = HibernateUtil.openSession();
Transaction tx = null;
try {
tx = session.getTransaction();
tx.begin();
Query query = session.createQuery("from prod pr join pr.cat ct with pr.catid=ct.id where ct.name=?");
//Query query = session.createQuery("from prod pr join pr.cat ct with pr.catid=ct.id where ct.name=?");
query.setString(0, catname);
//query.setInteger(1, pricel);
//query.setInteger(2, priceh);
list = (ArrayList<prod>) query.list();
tx.commit();
} catch (Exception e) {
if (tx != null) {
tx.rollback();
}
e.printStackTrace();
} finally {
session.close();
}
return list;
}
In your prod class (defined in prod.java) you have not mapped a field cat (as object type cat), you have mapped only catId as integer.
So you can't use a join like yours.
You can re-write your query like this:
FROM prod pr, cat ct
WHERE pr.catid = ct.id
AND ct.name = ?
manytoone
another variant
public class prod implements Serializable {
#Id #GeneratedValue
#Column(name = "catid")
#ManyToOne
#JoinColumn(name="cat", referencedColumnName="id")
// private Integer catid;
private Long id;
private cat cat;
private String name;
private Integer price;
#Column(s) not allowed on a #ManyToOne property: goods.prod.id
In Hibernate 4, inner join is used for child objects while accessing objects of "one table per subclass".
[Edit: This is a bug in Hibernate 4.3.5, and it is going to be fixed in 4.3.6. https://hibernate.atlassian.net/browse/HHH-8980 ]
I have the following classes.
Professor - Base Class
ContractProfessor - Derived Class from Professor
FulltimeProfessor - Derived Class from Professor
FulltimeProfessor contains a mandatory object of Department. [Not null at SQL]
Classroom contains an object of Professor, which can be null.
When I query Classroom, I am getting errors. When I saw the query, it is doing inner join with Department. If the classroom that it is retrieving is of ContractProfessor, then it won't have Department, and the inner join fails, and it is throwing exception.
Since, the Professor object can be null, it should always use left join for all the joins. But, it is doing inner join between FulltimeProfessor and Department. Because of that, I am getting exceptions when I try to retrieve Classroom objects.
This is working fine in Hibernate 3. But, when I use hibernate 4.3.5-Final, I am getting errors.
What should I do to fix this without changing the DB schema?
The following is the code and sql for the same.
Generated Query in Hibernate 4.3.5-Final
select
professor0_.id as id1_6_0_,
professor0_.name as name2_6_0_,
professor0_1_.hourlyRate as hourlyRa1_2_0_,
professor0_2_.DepartmentId as Departme3_4_0_,
professor0_2_.salary as salary1_4_0_,
case
when professor0_1_.id is not null then 1
when professor0_2_.id is not null then 2
when professor0_.id is not null then 0
end as clazz_0_,
department1_.id as id1_3_1_,
department1_.name as name2_3_1_
from
Professor professor0_
left outer join
ContractProfessor professor0_1_
on professor0_.id=professor0_1_.id
left outer join
FulltimeProfessor professor0_2_
on professor0_.id=professor0_2_.id
inner join
Department department1_
on professor0_2_.DepartmentId=department1_.id
where
professor0_.id=?
Generated Query in Hibernate 3.
select
professor0_.id as id2_1_,
professor0_.name as name2_1_,
professor0_1_.hourlyRate as hourlyRate3_1_,
professor0_2_.DepartmentId as Departme3_8_1_,
professor0_2_.salary as salary8_1_,
case
when professor0_1_.id is not null then 1
when professor0_2_.id is not null then 2
when professor0_.id is not null then 0
end as clazz_1_,
department1_.id as id1_0_,
department1_.name as name1_0_
from
Professor professor0_
left outer join
ContractProfessor professor0_1_
on professor0_.id=professor0_1_.id
left outer join
FulltimeProfessor professor0_2_
on professor0_.id=professor0_2_.id
left outer join
Department department1_
on professor0_2_.DepartmentId=department1_.id
where
professor0_.id=?
Professor.java
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Table;
#Entity
#Table(name = "Professor")
#Inheritance(strategy = InheritanceType.JOINED)
public abstract class Professor {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String 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 String toString() {
return "Professor id: " + getId() + " name: " + getName();
}
}
ContractProfessor.java
import javax.persistence.Entity;
import javax.persistence.Table;
#Entity
#Table(name="ContractProfessor")
public class ContractProfessor extends Professor {
private long hourlyRate = 1;
public long getHourlyRate() {
return hourlyRate;
}
public void setHourlyRate(long hourlyRate) {
this.hourlyRate = hourlyRate;
}
public String toString() {
return "ContractProfessor id: " + getId() + " name: " + getName();
}
}
FulltimeProfessor.java
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
#Entity
#Table(name="FulltimeProfessor")
public class FulltimeProfessor extends Professor {
private long salary = 1;
#ManyToOne(fetch = FetchType.EAGER)
#Fetch(FetchMode.JOIN)
#JoinColumn(name = "DepartmentId", nullable = false)
private Department department;
public Department getDepartment()
{
return department;
}
public void setDepartment(Department department)
{
this.department = department;
}
public long getSalary() {
return salary;
}
public void setSalary(long salary) {
this.salary = salary;
}
public String toString() {
return "FullTimeProfessor id: " + getId() + " name: " + getName();
}
}
Department.java
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "Department")
public class Department
{
private long id;
private String name;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
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;
}
public String toString() {
return "Department id: " + getId() + " name: " + getName();
}
}
Classroom.java
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
#Entity
#Table(name = "Classroom")
public class Classroom
{
private long id;
private String name;
private Professor professor;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
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;
}
public String toString() {
return "Classroom id: " + getId() + " name: " + getName();
}
#ManyToOne(fetch = FetchType.EAGER)
#Fetch(FetchMode.JOIN)
#JoinColumn(name = "ProfessorId", nullable = true)
public Professor getProfessor()
{
return professor;
}
public void setProfessor(Professor professor)
{
this.professor = professor;
}
}
InnerJoinMain.java
import java.util.Collection;
import java.util.Date;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
public class InnerJoinMain
{
public static void main(String[] args) throws Exception
{
EntityManagerFactory emf = Persistence.createEntityManagerFactory("ProfessorService");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
int time = (int)((new Date().getTime() / 1000) % 10000);
System.out.println(time);
ContractProfessor cprof = new ContractProfessor();
cprof.setName("CProf" + time);
cprof.setHourlyRate(time);
em.persist(cprof);
Department dept = new Department();
dept.setName("Dept" + time);
em.persist(dept);
FulltimeProfessor fprof = new FulltimeProfessor();
fprof.setName("Fprof" + time);
fprof.setDepartment(dept);
fprof.setSalary(time + 10);
em.persist(fprof);
Classroom cls = new Classroom();
cls.setName("Classroom" + time);
cls.setProfessor(cprof);
em.persist(cls);
cls = new Classroom();
cls.setName("Classroom" + (time+1));
cls.setProfessor(fprof);
em.persist(cls);
cls = new Classroom();
cls.setName("Classroom" + (time+2));
em.persist(cls);
em.getTransaction().commit();
em.getTransaction().begin();
Query query = em.createQuery("SELECT c FROM Classroom c");
for(Classroom c : (Collection<Classroom>) query.getResultList()) {
System.out.println(c);
}
em.getTransaction().commit();
em.close();
emf.close();
}
}