Error getting BeanDescriptor for path - java

I tried to fetch some data from a db using Ebean ORM. I have 3 tables named deal and deal_company_branch and company_branch. deal_company_branchis the associate entity. I wrote a query to fetch data,
select d.* from deal d, deal_company_branch dcb where d.deal_id=dcb.dealId and dcb.branchId=3
And then I tried to do the same thing using Ebean ORM like following,
DealDAO.find.fetch("deal").fetch("deal_company_branch").where()
.and(Expr.eq("deal.deal_id", "deal_company_branch.dealId")
, Expr.eq("deal_company_branch.branchId", branchId)).findList();
When I'm executing this I'm getting,
ERROR:Error while retrieving categories:Error getting BeanDescriptor for path deal from com.de.models.Deal
How may I fix this?

So:
fetch("deal_company_branch") ... that looks like a table name when it should instead be a property name and it is optional so you are probably best to leave it out unless you truely want to fetch that data.
.and(Expr.eq("deal.deal_id", "deal_company_branch.dealId") ... you should leave this out entirely
Expr.eq("deal_company_branch.branchId", branchId)).findList(); ... again that looks like a table.column reference rather than the logical property path.
This almost looks like a ManyToMany relationship but you don't include you model. In most cases for ORM queries you should include your model objects so that people can understand better what you are trying to do.
It looks like you should just do:
DealDAO.find.where().eq("companies.branch.id", branchId).findList();
This assumes the Deal entity has a #ManyToMany to "companies" which has a #ManyToOne to "branch" which has an #Id id property.
Ebean will understand from the property paths ("companies.branch.id") what joins it needs to make to support the where clause (and order by clause and fetching).

Related

Hibernate is making extra SQL statement with #ManyToOne and #Lazy fetching object

I would like someone to explain me why Hibernate is making one extra SQL statement in my straight forward case. Basically i have this object:
#Entity
class ConfigurationTechLog (
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Long?,
val configurationId: Long,
val type: String,
val value: String?
) {
#JsonIgnore
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "configurationId", insertable = false, updatable = false)
val configuration: Configuration? = null
}
So as you can see, nothing special there. And when i execute this query :
#Query(value = "SELECT c FROM ConfigurationTechLog c where c.id = 10")
fun findById10() : Set<ConfigurationTechLog>
In my console i see this:
Hibernate:
/* SELECT
c
FROM
ConfigurationTechLog c
where
c.id = 10 */ select
configurat0_.id as id1_2_,
configurat0_.configuration_id as configur2_2_,
configurat0_.type as type3_2_,
configurat0_.value as value4_2_
from
configuration_tech_log configurat0_
where
configurat0_.id=10
Hibernate:
select
configurat0_.id as id1_0_0_,
configurat0_.branch_code as branch_c2_0_0_,
configurat0_.country as country3_0_0_,
configurat0_.merchant_name as merchant4_0_0_,
configurat0_.merchant_number as merchant5_0_0_,
configurat0_.org as org6_0_0_,
configurat0_.outlet_id as outlet_i7_0_0_,
configurat0_.platform_merchant_account_name as platform8_0_0_,
configurat0_.store_type as store_ty9_0_0_,
configurat0_.terminal_count as termina10_0_0_
from
configuration configurat0_
where
configurat0_.id=?
Can someone please explain me, what is happening here ? From where this second query is coming from ?
I assume you are using Kotlin data class. The kotlin data class would generate toString, hashCode and equals methods utilizing all the member fields. So if you are using the returned values in your code in a way that results in calling of any of these method may cause this issue.
BTW, using Kotlin data claases is against the basic requirements for JPA Entity as data classes are final classes having final members.
In order to make an association lazy, Hibernate has to create a proxy instance instead of using the real object, i.e. it needs to create an instance of dynamically generated subclass of the association class.
Since in Kotlin all classes are final by default, Hibernate cannot subclass it so it has to create the real object and initialize the association right away. In order to verify this, try declaring the Configuration class as open.
To solve this without the need to explicitly declare all entities open, it is easier to do it via the kotlin-allopen compiler plugin.
This Link can be useful for understand what kind (common) problem is that N + 1 Problem
Let me give you an example:
I have three Courses and each of them have Students related.
I would like to perform a "SELECT * FROM Courses". This is the first query that i want (+ 1) but Hibernate in background, in order to get details about Students for each Course that select * given to us, will execute three more queries, one for each course (N, there are three Course coming from select *). In the end i will see 4 queries into Hibernate Logs
Considering the example before, probably this is what happen in your case: You execute the first query that you want, getting Configuration Id = 10 but after, Hibernate, will take the entity related to this Configuration, then a new query is executed to get this related entity.
This problem should be related in specific to Relationships (of course) and LAZY Fetch. This is not a problem that you have caused but is an Hibernate Performance Issue with LAZY Fetch, consider it a sort of bug or a default behaviour
To solve this kind of problem, i don't know if will be in your case but ... i know three ways:
EAGER Fetch Type (but not the most good option)
Query with JOIN FETCH between Courses and Students
Creating EntityGraph Object that rappresent the Course and SubGraph that rappresent Students and is added to EntityGraph
Looking at your question, it seems like an expected behavior.
Since you've set up configuration to fetch lazily with #ManyToOne(fetch = FetchType.LAZY), the first sql just queries the other variables. When you try to access the configuration object, hibernate queries the db again. That's what lazy fetching is. If you'd like Hibernate to use joins and fetch all values at once, try setting #ManyToOne(fetch = FetchType.EAGER).

Underscores in MYSQL table column names for org.hibernate.criterion.Restrictions throws Exception

I'm definitely a noob with Hibernate and am struggling to Query my database when table column names have underscores.
From what I've read, the underscore is treated like a wildcard. So, the solution is to remove it and camelCase the column name. However, that isn't working for me either. I would really appreciate some help here.
Here is the SQL table creation:
Here is the function where I attempt to Query:
When I call this function though, I get the following stack trace:
Request processing failed; nested exception is
org.hibernate.QueryException: could not resolve property: userId of....
I've tried it with multiple variations of userId: user_id, userId, user_ID, userID, userid & nothing works. I would really appreciate some help here. Thanks in advance. One other weird thing is that the camelCasing works if I do it for just publishId. It just doesn't work for both of them...
Here is the Java class with it's annotations:
In JPQL (HQL) you have to use property names:
criteria.add(Restrictions.eq("userEmail", user));
This is one of the benefits of ORM frameworks like JPA (and of course its providers like Hibernate and others): you use object-oriented constructs in queries as well.
You should use userEmail in your criteria because the the user_id field is named userEmail.
criteria.add(Restrictions.eq("userEmail", user))

How to tell Hibernate annotation #Column to be case-sensitive?

I'm trying to do a simple SELECT query in a table named ECM (in uppercase) on a Sybase db with Hibernate. I've annotated my DBO this way :
#Entity
#Table(name="ECM")
public class RelationshipDbo {
...
}
However, I'm facing a "table not found" error : the generated SQL has the table name in lowercase. I cannot change the database configuration to tell it to be case-insensitive.
I've also tried putting quotes like this :
#Table(name="`ECM`")
and this :
#Table(name="'ECM'")
Result : the quotes are added in the query, but the table name is still converted from uppercase to lowercase.
Technical information :
Hibernate 4.3
JPA 1.2
org.hibernate.dialect.SybaseDialect
Have you guys any idea?
EDIT: Also tried this Hibernate changes #Table(name) to lowercase
Then my columns names and table name are automatically quoted, but the names still get lowercased.
I think I have your answer:
Basically, you need to change the naming strategy for you JPA provider. How you do this will depend on how you setup your project.
In my case, using spring boot data I set a property in my application.properties to
spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.EJB3NamingStrategy
Without more details from you I can't give more specifics on how to do this.
My goal is a little different since was trying to create tables upper case and hibernate created them in lower case. Also i was using MySQL not Sybase.
But for me quoting the names like this worked:
#Entity
#Table(name="\"ECM\"")
public class RelationshipDbo {
...
}
Then tables were created upper case. Maybe that helps also for the queries.
What is your Sybase db version ?
SybaseDialect has been deprecated in Hibernate 3.5 and then refactored since Hibernate 4.1 with a bunch of subclasses matching different versions of Sybase. Have you tried one of the subclasses to see if it makes any difference?
org.hibernate.dialect.Sybase11Dialect
org.hibernate.dialect.SybaseAnywhereDialect
org.hibernate.dialect.SybaseASE15Dialect
Try this:
Use backticks as in #Table(name="`ECM`")?
This must work from Hibernate point. If not then problem should be in DB (if i'm not wrong)

HIBERNATE: Auto append word into TABLE

hi I have an entity with this annotation
#Entity
#Table(name = "REPORT_WORK")
But for some reason hibernate keep saying Missing Table: REPORT_REPORT_WORK
I know that is the problem because of when I change the name to "REPORT_WORKX"
It will say Missing Table: REPORT_REPORT_WORKX
Has any encountered this issue before?
Update: when I change the name to JJJJ
It will say Missing Table: REPORT_JJJJ
so for some reason there it is auto appending REPORT_
Configuration:
hibernate.hbm2ddl.auto=validate
I suspect that the problem is your Hibernate configurations. Specifically, if you don't have an appropriate setting for hibernate.hbm2ddl.auto, Hibernate won't automatically update the database schema when you change your model.
(And if you don't want the updates to happen automatically, then you need to figure out what schema changes are needed, code them as SQL DDL, and run them manually.)
Can you post your persistence.xml (or equivalent)?
It sounds like you are implementing org.hibernate.cfg.NamingStrategy, get rid of this configuration.
Some additional info:
JPA (Hibernate) and custom table prefixes

How to bulk delete from element collection in jpa

I'm using jpa 2.0 and I have the following entity:
#Entity
public class Folder{
#ElementCollection
#CollectionTable(name="folder_files")
private Set<String> files;
// .....
}
Given a file name, I would like to delete all entries where files == theGivenFileName. In sql it would be something like this:
Delete from folder_files where files = XXX
Is there a way to perform this query using criteria-api?
If not, is there a way to perform this query using jpql?
UPDATE:
I think my question was not clear enough:
Since jpql uses entities (and not tables) I cannot just perform the sql written above plus since I'm using #ElementCollection I don't know how to address this variablr or even deal with it. I would like to delete all entries in that collection (in my case, the files set) which holds a given value, from all entities. Is that possible using jpql or (even better) criteria-api?
The Delete FROM clause requires an Entity, so there is no way to delete from an element collection from what I understand.
You can use a native SQL query, or you can map the element collection as a OneToMany to an Entity instead.
You can use the like query just the syntax is slightly changed.
query = em.createQuery("SELECT i FROM Item i WHERE UPPER(i.name) LIKE :keyword ");
query.setParameter("keyword", "%" + keyword.toUpperCase() + "%");
You can read more on following link,
https://forums.oracle.com/forums/thread.jspa?threadID=423742
Updated:
#Noam you can do it: Like in Criteria API
List cats = sess.createCriteria(Cat.class)
.add( Restrictions.like("name", "Fritz%") )
.add( Restrictions.between("weight", minWeight, maxWeight) )
.list();
Kindly read more on it at following link:
http://ctpconsulting.github.com/query/1.0.0.Alpha3/criteria.html
http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/querycriteria.html
This cannot be done. Via JPQL it does not work because DELETE statement can only be applied to entities. Excerpt from JPA 2.0 specification:
Bulk update and delete operations apply to entities of a single entity
class (together with its subclasses,if any).
...
delete_statement ::= delete_clause [where_clause]
delete_clause ::= DELETE FROM entity_name [[AS] identification_variable]
Also it doesn't work via Criteria API. CriteriaQuery supports only selecting - not updates or removals.
You have to go for native SQL.

Categories