SpringData JPA hibernate collection for IN keyword - spring-data-jpa

I am trying to fetch records using custome query in SpringData repository. I want to use IN keyword to fetch objects according to ids of a nested object. Following is my repo class.
public interface BusinessRepository extends JpaRepository<Business, Long> {
#Query("SELECT t from Business t where t.address.addressid IN ? AND (t.businessType.text like ? or t.businessname like ?)")
ArrayList<Business> findAllByAddressAddressidInAndBusinessTypeTextLikeOrBusinessnameLike(ArrayList<Long> ids, String businessType, String businessName);
My console shows following text.
Hibernate: select business0_.businessid as businessid0_, business0_.address_addressid as address9_0_, business0_.begdate as begdate0_, business0_.businessType_id as busines10_0_, business0_.businessname as business3_0_, business0_.contracttypeid as contract4_0_, business0_.multiuser as multiuser0_, business0_.statusid as statusid0_, business0_.urlreservos as urlreser7_0_, business0_.website as website0_, business0_1_.homePhone as homePhone2_, business0_1_.mobilePhone as mobilePh2_2_, business0_1_.primaryPhone as primaryP3_2_, business0_2_.businessdesc as business1_1_, business0_2_.pagetitle as pagetitle1_, business0_2_.tag as tag1_, business0_3_.userid as userid3_ from tbu1200 business0_ left outer join tbu1208 business0_1_ on business0_.businessid=business0_1_.id left outer join tbu1207 business0_2_ on business0_.businessid=business0_2_.id left outer join tbu1204 business0_3_ on business0_.businessid=business0_3_.businessid cross join vt1001 businessty1_ where business0_.businessType_id=businessty1_.id and (business0_.address_addressid in (?)) and (businessty1_.text like ? or business0_.businessname like ?)
TRACE: org.hibernate.type.descriptor.sql.BasicBinder - binding parameter [1] as [BIGINT] - [1, 2]
It seems correct to me. I am getting following exception.
java.lang.ClassCastException: java.util.ArrayList cannot be cast to java.lang.Long
at org.hibernate.type.descriptor.java.LongTypeDescriptor.unwrap(LongTypeDescriptor.java:36)
at org.hibernate.type.descriptor.sql.BigIntTypeDescriptor$1.doBind(BigIntTypeDescriptor.java:57)
at org.hibernate.type.descriptor.sql.BasicBinder.bind(BasicBinder.java:92)
My question is that why it is expecting Long while I have used IN statement. It should expect a Collection. If this is something not supported then what should I do?

Why are you adding #Query annotation here?
Without specifing query manually it should works as expected.
List<Company> findDistinctByUsers_loginIn(List<String> users)
I've checked and such code finishes without exception. The only problem is that SpringData is creating cartesian, and you need to add distinct to make it working properly.

Related

EF Core completely ignores my selected properties in select

As I understand it, the following code should generate a query containing only the RouteId, RouteNo, and ShipId
var tow = (from t in _context.AllTowData
where t.RouteId == id
orderby t.RouteNo descending
select new TowDefaults {
Id = t.RouteId,
TowNo = t.RouteNo,
ShipId = t.ShipId,
LastTow = t.RouteNo
})
.FirstOrDefault();
However, I get:
SELECT v.route_id, v.route_no, v.tow_id, v.analysis_complete, v.checks_complete, v.cpr_id, v.date_created, v.date_last_modified, v.factor, v.fromportname, v.instrument_data_file, v.instrument_id, v.internal_number, v.mastername, v.message, v.miles_per_division, v.month, v.number_of_samples, v.number_of_samples_analysed_fully, v.prop_setting, v.route_status, v.sampled_mileage, v.serial_no_per_calendar_month, v.ship_speed, v.silk_reading_end, v.silk_reading_start, v.toportname, v.tow_mileage, v.validity, v.year
FROM view_all_tow_data AS v
WHERE v.route_id = '#__id_0'
ORDER BY v.route_no DESC
LIMIT 1
That's every column except the explicitly requested ShipId! What am I doing wrong?
This happens using both a SQL Server and a PostGres database
The property ShipIdis not mapped, either by a [NotMapped] annotation or a mapping instruction. As far as EF is concerned, the property doesn't exist. This has two effects:
EF "notices" that there's an unknown part the final Select and it switches to client-side evaluation (because it's a final Select). Which means: it translates the query before the Select into SQL which doesn't contain the ShipId column, executes it, and materializes full AllTowData entities.
It evaluates the Select client-side and returns the requested TowDefaults objects in which ShipId has its default value, or any value you initialize in C# code, but nothing from the database.
You can verify this by checking _context.AllTowData.Local after the query: it will contain all AllTowData entities that pass the filter.
From your question it's impossible to tell what you should do. Maybe you can map the property to a column in the view. If not, you should remove it from the LINQ query. Using it in LINQ anywhere but in a final Select will cause a runtime exception.

According to the list to receive a string RID class MARKS

In my database IM_0609 OrientDB version 2.0.8 is a class MARKS:
CALIBRATION_DATE:date.
DEVICE_MARK:string
DEVICE_NAME:string
END_MARK_NUM:decimal
MARK_NUM:decimal
PERIOD:decimal
SERIAL_NUM:string
In the class MARKS I have created the index as follows: CREATE INDEX IDX_MARK_NUM on MARKS(MARK_NUM) NOTUNIQUE
I run the following query quickly:
select rid from index:IDX_MARK_NUM where key>=74118499 and key<=74118501
Results query:
#12:281829
#12:493194
#12:422739
#12:211374
#12:70464
#12:9
#12:352284
#12:140919
#12:329563
#12:259112
Question: How do I write a query to get the list RID fields class MARS?
select *
from MARKS
where #rid in [select rid
from index:IDX_MARK_NUM
where key>=74118499 and key<=74118501]
run for 51 sec.

TypedQuery<x> returns vector of Object[] instead of list of x-type object

I have a method:
public List<Timetable> getTimetableTableForRegion(String id) {
List<Timetable> timetables;
TypedQuery<Timetable> query = em_read.createQuery("SELECT ..stuff.. where R.id = :id", Timetable.class).setParameter("id", Long.parseLong(id));
timetables = query.getResultList();
return timetables;
}
which returns this:
so, what am I missing in order to return a list of Timetable's?
ok, so, ..stuff.. part of my JPQL contained an inner join to other table. Even through in SELECT there were selected fields just from one table, which was used as type - Timetable, Eclipslink was unable to determine if this fields are part of that entity and instead of returning list of defined entity returned list of Object[].
So in conclusion: Use #OneToMany/#ManyToOne mappings (or flat table design) and query just for ONE table in your JPQL to be able to typize returned entities.
Not sure it might be something is looking for, but I had similar problem and converted Vector to ArrayList like this:
final ArrayList<YourClazz> results = new ArrayList<YourClazz>();;
for ( YourClazzkey : (Vector<YourClazz>) query.getResultList() )
{
results.add(key);
}
i have faced the same problem. and my entity has no one to one or one to many relationship. then also jpql was giving me queryresult as vector of objects. i changed my solution to query to criteria builder. and that worked for me.
code snippet is as below:
CriteriaBuilder builder = this.entityManager.getCriteriaBuilder();
CriteriaQuery<Timetable> criteria = builder.createQuery(Timetable.class);
Root<Enumeration> root = criteria.from(Timetable.class);
criteria.where(builder.equal(root.get("id"), id));
List<Timetable> topics = this.entityManager.createQuery(criteria) .getResultList();
return topics;

JPQL query with WHERE on nested fields

I have a java entity class UserBean with a list of events:
#OneToMany
private List<EventBean> events;
EventBean has Date variable:
#Temporal(javax.persistence.TemporalType.TIMESTAMP)
private Date eventDate;
Now in UserBean I want to create a NamedQuery that returns all dates that fall within a specific range:
#NamedQuery(name="User.findEventsWithinDates",
query="SELECT u.events FROM UserBean u WHERE u.name = :name AND u.events.eventDate > :startDate AND u.events.eventDate < :endDate")
The above query does not compile though. I get this error:
The state field path 'u.events.eventDate' cannot be resolved to a valid type.
By the way, I use EclipseLink version 2.5.0.v20130507-3faac2b.
What can I do to make this query work? Thanks.
Path u.events.eventDate is an illegal construct in JPQL, because it is not allowed to navigate via a collection valued path expression. In this case u.events is a collection valued path expression. In JPA 2.0 specification this is told with following words:
It is syntactically illegal to compose a path expression from a path
expression that evaluates to a collection. For example, if o
designates Order, the path expression o.lineItems.product is illegal
since navigation to lineItems results in a collection. This case
should produce an error when the query string is verified. To handle
such a navigation, an identification variable must be declared in the
FROM clause to range over the elements of the lineItems collection.
This problem can be solved by using JOIN:
SELECT distinct(u)
FROM UserBean u JOIN u.events e
WHERE u.name = :someName
AND e.eventDate > :startDate
AND e.eventDate < :endDate

Entity Framework: selecting from multiple tables

I have a statement:
var items = from e in db.Elements
join a in db.LookUp
on e.ID equals a.ElementID
where e.Something == something
select new Element
{
ID = e.ID,
LookUpID = a.ID
// some other data get populated here as well
};
As you can see, all I need is a collection of Element objects with data from both tables - Elements and LookUp. This works fine. But then I need to know the number of elements selected:
int count = items.Count();
... this call throws System.NotSupportedException:
"The entity or complex type 'Database.Element' cannot be constructed in a LINQ to Entities query."
How am I supposed to select values from multiple tables into one object in Entity Framework? Thanks for any help!
You are not allowed to create an Entity class in your projection, you have to either project to a new class or an anonymous type
select new
{
ID = e.ID,
LookUpID = a.ID
// some other data get populated here as well
};
Your code doesn't work at all. The part you think worked has never been executed. The first time you executed it was when you called Count.
As exception says you cannot construct mapped entity in projection. Projection can be made only to anonymous or non mapped types. Also it is not clear why you even need this. If your class is correctly mapped you should simply call:
var items = from e in db.Elements
where e.Something == something
select e;
If LookupID is mapped property of your Element class it will be filled. If it is not mapped property you will not be able to load it with single query to Element.