I'll appreciate if anyone can point me to a solution as to why I could be getting the error below in an attempt to execute the following query which caused no problem whatsoever with Hibernate:
The Entity (Step.java):
#Entity
#Table(name = "IAS_STEP")
public class Step implements Serializable {
#Id
private Long id;
#Temporal(TemporalType.DATE)
private Date tarih;
private long formId;
private Byte faz;
// getters, setters, etc.
}
The method in the controller class:
public byte getMaxPhase(String sid, long form_id) {
EntityManager em = getEntityManager();
try {
Query q = em
.createQuery(
"select max(faz) as mf from Step s where s.id = :sid and s.formId = :formId")
.setParameter("sid", sid)
.setParameter("formId", form_id);
return ((Byte) q.getSingleResult()).byteValue();
} finally {
em.close();
}
}
This worked just fine in Hibernate, but causes an error in EclipseLink 2.0.
Anyone can suggest a workaround?
max(faz)
should be,
max(s.faz)
(an you are executing JPQL not a native SQL query)
Related
I am studying Spring MVC with Hibernate and came across the following situation.
I have a service-related rate card in which the last registered price is the current price of the service and developed the sql code to get the result like this:
My database looks like this:
SQL that I need in HQL Java method:
select s.*,
(select ps.price
from priceServices ps
where ps.idService = s.id
order by ps.dateRegister DESC limit 1) as currentPrice
from service s
Java Classes:
#Entity
#Table(name = "service")
public class Service {
/****/
#OneToMany(mappedBy="service",
cascade= CascadeType.ALL,
fetch = FetchType.LAZY)
private List<PriceServices> prices;
}
// ......
#Entity
#Table(name = "priceServices")
public class PriceServices {
/****/
#Id
#ManyToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE,
CascadeType.DETACH, CascadeType.REFRESH})
#JoinColumn(name = "idService")
private Service service;
}
// ......
#Repository
public class ServiceDaoImpl implements ServiceDao {
#Autowired
private SessionFactory sessionFactory;
protected Session getCurrentSession() {
return sessionFactory.getCurrentSession();
}
#Override
public List<Service> findAll() {
return this.getCurrentSession().createQuery("from Service", Service.class).getResultList();
}
}
I am currently displaying a table with services and an "info" button at the end, when the user clicks this button, I do an ajax searching for the price of the service.
However I would like to already display the current value of the service in the table and in the course the examples are basic.
Do I have to use Criteria or NamedQuery to be able to subselect inside findAll()???
I found an answer in another post here in the forum. I will leave the answer in case someone also needs help like I need.
HQL doesn't actually implement the MySQL Limit function as I needed it, so one solution is to work with pure SQL itself.
This is the link:
How to set a limit to inner query in Hibernate?
In my ServiceDaoImpl class I created the method:
public List<Service> findAllWithPrice() {
NativeQuery<Service> query = this.getCurrentSession().createSQLQuery("select s.*, (select ps.price from priceServices ps where ps.idService = s.id order by ps.dateRegister DESC limit 1) as currentPrice from service s");
query.addEntity( Service.class );
return query.getResultList();
}
And in the class Service that represents the entity create a field for the price:
#Entity
#Table(name = "service")
public class Service {
/****/
private float currentPrice;
// Getter and Setter of currentPrice
}
I'm trying to integrate Hibernate Search to my backend, but I can't make it work as I would like it to.
My intention is to retrieve all the following model.Course tuples only with the token "java":
Currently, I'm only getting the model.Course with id = 26. That means Lucene is working, but I don't know how to create the query needed to perform the operation I want.
This is my CourseService code:
private Session session;
private FullTextSession fts;
public CourseService(){
SessionFactory sf = SessionFactoryManager.getInstance(); // Singleton
this.session = sf.openSession();
this.fts = Search.getFullTextSession(this.session);
}
public List<Course> searchCourses(String token) {
try {
this.fts.createIndexer().startAndWait();
} catch (InterruptedException e) {
e.printStackTrace();
}
Transaction tx = this.fts.beginTransaction();
QueryBuilder queryBuilder = this.fts.getSearchFactory()
.buildQueryBuilder()
.forEntity(Course.class)
.get();
org.apache.lucene.search.Query query = queryBuilder.simpleQueryString()
.onField("description").andField("name")
.matching(token)
.createQuery();
org.hibernate.query.Query hibQuery = fts.createFullTextQuery(query, Course.class);
List result = hibQuery.getResultList();
tx.commit();
return result;
}
This is my model.Course code:
#Entity
#Indexed
#Inheritance(strategy = InheritanceType.JOINED)
public class Course implements Comparable<Course>{
#Id
#DocumentId
#GeneratedValue(strategy= GenerationType.AUTO)
private int id;
#Field (termVector = TermVector.YES)
private String name;
#Field
private String description;
/*...*/
protected Course(String name, String description, ...) {
/*...*/
}
IMPORTANT EDIT: I initially thought it was a problem with the query, but it's actually an indexing problem.
I don't know how to solve this type of problem. I'm hearing suggestions. Details:
I'm using a singleton for SessionFactory (I wasn't before the edit)
I'm using org.hibernate:hibernate-search-orm:5.8.2.Final
I'm using HSQLdb 2.4.0
The rest of hibernate is working perfectly (CRUD operations)
It looks like an analysis issue, e.g. the analyzer chosen not splitting the field in tokens.
What is a bit weird is that the default analyzer (the StandardAnalyzer) split the field in tokens so it should work out of the box.
Have you set a different default analyzer (the KeywordAnalyzer for instance)?
I am building a query in QueryDSL. I have entity and sub class entity having same column. I wanna use same query to both entity using only single JPAQuery.
here is my entity.
#Entity
public class Region {
#Id
private Integer id;
}
#Entity
public class RegionTemp extends Region {}
queryer
#Component
public class RegionQueryer {
#PersistenceContext
private EntityManager mysqlEntityManager;
QRegion qRegion = QRegion.region; // ???
public Integer loadLastId() {
return new JPAQueryFactory(mysqlEntityManager)
.select(qRegion.id)
.from(qRegion)
.orderBy(qRegion.id.desc()).fetchFirst();
}
}
My code. this sample. if you want to using single query. use simple Repository. it take easy find, delete, save. you search JPA Tutorial.
#Override
public List<CompanyInformaion> findCompanyInformationList(String language, Association association) {
QCompanyInformaion qCompanyInformaion = QCompanyInformaion.companyInformaion;
QCompany qCompany = QCompany.company;
EntityManager em = entityManagerFactory.createEntityManager();
JPAQuery jpaQuery = new JPAQuery(em);
List<CompanyInformaion> infos = jpaQuery.from(qCompanyInformaion)
.where(qCompanyInformaion.language.eq(language)
.and(qCompanyInformaion.company.in(new JPASubQuery().from(qCompany)
.where(qCompany.association.eq(association)).list(qCompany))))
.orderBy(qCompanyInformaion.companyName.asc()).list(qCompanyInformaion);
return infos;
}
I am attempting to retrieve a list of results from my database, by following an example in this answer. Howeverm, I keep getting the following error:
java.lang.AbstractMethodError: org.hibernate.ejb.EntityManagerImpl.createQuery(Ljava/lang/String;Ljava/lang/Class;)Ljavax/persistence/TypedQuery;
Here is my code, to denote how I am calling this:
#Entity
#Table(name = "MY_TABLE")
public class CoolsEntity implements Serializable {
#Id
#Column(name = "ID", columnDefinition = "Decimal(10,0)")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private String id;
#Column(name = "COOL_GUY_NAME")
private String name;
public String getId() {
return id;
}
public void setId(final String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(final String name) {
this.name= name;
}
}
This code below generates the error:
final String sql = "select c from CoolsEntity c";
final TypedQuery<CoolsEntity> query = em.createQuery(sql, CoolsEntity.class);
final List<CoolsEntity> results = query.getResultList();
return results;
However, if I do something like this, I can see the results:
final String sql = "select c from CoolsEntity c";
final Query query = em.createQuery(sql);
#SuppressWarnings("unchecked")
final List<CoolsEntity> results = query.getResultList();
return results;
All of the references to em are imported through this package:
import javax.persistence.EntityManager
Shouldn't the two queries above generate the same result? Am I missing a cast to the List interface to allow this to work in the typed query?
You have an AbstractMethodError exception which is thrown when an application tries to call an abstract method.
You have quite a mix of Hibernate and JPA versions.
TypedQuery was introduced in JPA 2.0 and Hibernate implements this specification since 3.5.X
Suggesstion : Use implementation from Hibernate version 3.6.3 (or higher).
you are probably using two differnet version of interface EntityManager and implementation EntityManagerImpl.
In my database table Attribute, I will have a list of data loaded first. Every time, when I want to persist a new record of MyAttribute, I will need to search through the table Attribute first and select the appropriate record from table Attribute before I insert to table MyAttribute.
#Entity
class MyAttribute{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#ManyToOne(targetEntity = Attribute.class)
#JoinColumn(name="attribute_id", referencedColumnName="id")
Attribute detail;
private String greet;
public MyAttribute(){
this.greet = "Hello World.";
this.detail = new MyDbLayer().selectAttributeDetail("first"); //Error is thrown here.
}
//getter & setter
}
#Entity
class Attribute{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Index(name = "name_index")
#Column(unique=true )
private String name;
//getter & setter
}
class MyDbLayer{
private EntityManagerFactory emf;
public MyDbLayer() {
emf = Persistence.createEntityManagerFactory("MyPu");
}
public Attribute selectAttributeDetail(String name) {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
Query queryGetAttribute = em.createQuery("select a from Attribute a where a.name = :attributeName");
List<AttributeDescription> attributeDescList = queryGetAttribute.setParameter("attributeName", name).getResultList();
AttributeDescription tempAttribute = null;
if (!attributeDescList.isEmpty()) {
tempAttribute = (AttributeDescription) attributeDescList.get(0);
}
em.clear();
em.close();
return tempAttribute;
}
}
I'm not sure why I keep on receiving error like:
javax.persistence.PersistenceException: [PersistenceUnit: MyPu] Unable
to build EntityManagerFactory
Caused by: org.hibernate.MappingException: Could not get constructor
for org.hibernate.persister.entity.SingleTableEntityPersister
Caused by: org.hibernate.InstantiationException: could not instantiate
test object
P.S. This is not the real code that I'm working on, but the structure is more or less the same.
What about making a second construtor for MyAttribute?
public MyAttribute(){
this.greet = "Hello World.";
// this.detail = new MyDbLayer().selectAttributeDetail("first"); //Error is thrown here.
}
public MyAttribute(Attribute detail){
this.greet = "Hello World.";
this.detail = detail;
}
The default constructor is also used by jpa to load persited objects. this can cause unexpected behaviour
It is not in the JPA model to be able to access an EntityManager from an Entity. It can be done, but it can have different behaviors depending on the implementation.
In your case accessing an EntityManager from the no args constructor is never a good idea. Because thats the constructor used by the EntityManager when it loads an Entity. So every time MyAttribute is loaded by an EntityManager you will try to create antoher EntityManager to initialise the detail relationship which will be overwritten by the first EntityManager using the value it loaded from the database.
Usually you should have a service layer which has access to an EntityManager that manages your JPA Entities.