Spring data r2dbc and group by - spring-data

I am using the DatabaseClient to perform my sql queries and I don't see how I can do a group by:
databaseClient.select()
.from( myClass.class )
.matching( where( "row_1" ).is( "value_1" ) )
//group by row_2 ...
.orderBy( Sort.Order.desc( "row_3" ) )
.page( pageable )
.fetch()
.all();

A workaround solution using sql directly.
public Flux<Map<Object, Object>> countByStatus() {
return this.databaseClient
.sql("SELECT count(*) as cnt, status FROM posts group by status")
.map((row, rowMetadata) -> {
Long cnt = row.get("cnt", Long.class);
Post.Status s = row.get("status", Post.Status.class);
return Map.<Object, Object>of("cnt", cnt, "status", s);
})
.all();
}
Check the complete codes.

Related

How to convert sql query to query builder typeorm format

1: This is sql query
INSERT INTO allocation (
effort, "startDate", "endDate", "employeeId", "projectId"
)
SELECT Distinct
request_allocation_detail.effort,
request_allocation_detail."startDate",
request_allocation_detail."endDate",
request_allocation_detail."employeeId",
request_allocation."projectId"
From
public.request_allocation
inner join public.request_allocation_detail ON request_allocation_detail."requestAllocationId" = request_allocation.id
where
request_allocation_detail.id = '${currentRequestDetailId}'
2: this is query builder using typeorm but it not work:
=>Create query builder and try to insert into using select with typeorm
const db= this.allocationRepository
.createQueryBuilder('allocation')
.insert()
.into('allocation')
.values(['effort', 'startDate', 'endDate', 'employeeId', 'projectId'])
.select([
'request_allocation_detail.effort',
'request_allocation_detail."startDate"',
'request_allocation_detail."endDate"',
'request_allocation_detail."employeeId"',
'request_allocation."projectId"',
])
.distinct()
.from('request_allocation', 'request_allocation')
.innerJoinAndSelect(
'request_allocation_detail',
'request_allocation_detail',
'request_allocation_detail.id = request_allocation.id'
)
.where('request_allocation_detail.id = :id', {
id: currentRequestDetailId,
});
Please help me how to resolve it
First i separate sql query to 2 phase: select and insert:
Second: i write querybuilder with typeorm to command select:
const (*) [subQuery, params] = this.createQueryBuilder(
'request_allocation_detail'
)
.innerJoin(
'request_allocation',
'request_allocation',
'request_allocation_detail."requestAllocationId" = request_allocation.id'
)
.where('request_allocation_detail.id = :id', {
id: currentRequestDetailId,
})
.select([
'request_allocation_detail.effort',
'request_allocation_detail.startDate',
'request_allocation_detail.endDate',
'request_allocation_detail."employeeId"',
'request_allocation."projectId"',
])
.getQueryAndParameters();
Next i return with command insert into with command query in typeorm:
return this.query(
`
INSERT INTO allocation (here is column i need to add data from *)${subQuery}`,
params
);

Spring JPA Query getResultList returning data as application/json

I have a web application that uses Spring JPA and I have the following function that works fine in my integration test
public List<PermissionQueryDTO> findByCompanyAndEventType(int companyId, int eventTypeId) {
Query query = getEntityManager().createNativeQuery(FIND_BY_COMPANY_AND_EVENT_TYPE_QUERY, "PermissionQueryMapping");
query.setParameter("companyId", companyId);
query.setParameter("eventTypeId", eventTypeId);
return query.getResultList();
}
How ever when run in my Web App I get this error message:
Could not locate appropriate constructor on class : a.b.c.PermissionQueryDTO] as "application/json" using [org.springframework.http.converter.StringHttpMessageConverter#346a9eea]
Anyone know why I'm getting this error
The problem was that the Result Set Mapping didn't have a type specified. I had to change this:
#SqlResultSetMapping(
name="PermissionQueryMapping",
classes={
#ConstructorResult(
targetClass=PermissionQueryDTO.class,
columns={
#ColumnResult(name="prop_id"),
#ColumnResult(name="prop_description"s),
#ColumnResult(name="prop_code"),
#ColumnResult(name="prop_pt_id"),
#ColumnResult(name="permissionId"),
#ColumnResult(name="uplineStationPermissionLevel"),
#ColumnResult(name="previousStationPermissionLevel"),
#ColumnResult(name="eventStationPermissionLevel"),
#ColumnResult(name="nextStationPermissionLevel",
#ColumnResult(name="downlineStationPermissionLevel"),
}
)
}
)
To this:
#SqlResultSetMapping(
name="PermissionQueryMapping",
classes={
#ConstructorResult(
targetClass=PermissionQueryDTO.class,
columns={
#ColumnResult(name="prop_id", type=Integer.class),
#ColumnResult(name="prop_description", type=String.class),
#ColumnResult(name="prop_code", type=String.class),
#ColumnResult(name="prop_pt_id", type=Integer.class),
#ColumnResult(name="permissionId", type=Integer.class),
#ColumnResult(name="uplineStationPermissionLevel", type=Integer.class),
#ColumnResult(name="previousStationPermissionLevel", type=Integer.class),
#ColumnResult(name="eventStationPermissionLevel", type=Integer.class),
#ColumnResult(name="nextStationPermissionLevel", type=Integer.class),
#ColumnResult(name="downlineStationPermissionLevel", type=Integer.class),
}
)
}
)

pg8000.core.ProgrammingError: 'could not determine data type of parameter $2'

I'm using pg.8000 (Postgres) and trying to run the following SELECT query
cursor.execute(
"""
SELECT orders.name, orders.order_price, orders.selling_price, orders.earnings
FROM member, orders
WHERE member.id=orders.member_id
AND member.name = %s
""",
member_username
)
Where member.username is a String.
But I am getting the following error.
pg8000.core.ProgrammingError: ('ERROR', 'ERROR', '42P18', 'could not determine data type of parameter $2', 'postgres.c', '1350', 'exec_parse_message', '', '')
However, when I run same query using GUI tool, everything runs fine and I get the results. What is the problem?
You passed the parameter wrong, you should give a tuple, a list or a dictionary
Example with a tuple:
cursor.execute(
"""
SELECT orders.name, orders.order_price, orders.selling_price, orders.earnings
FROM member, orders
WHERE member.id=orders.member_id
AND member.name = %s
""",
(member_username,)
)
Example with a list:
cursor.execute(
"""
SELECT orders.name, orders.order_price, orders.selling_price, orders.earnings
FROM member, orders
WHERE member.id=orders.member_id
AND member.name = %s
""",
[member_username]
)
Example with a dictionary:
cursor.execute(
"""
SELECT orders.name, orders.order_price, orders.selling_price, orders.earnings
FROM member, orders
WHERE member.id=orders.member_id
AND member.name = %(mname)s
""",
{'mname' : member_username}
)
http://initd.org/psycopg/docs/usage.html#query-parameters

Twisted (Scrapy) and Postgres

Im using Scrapy (aka Twisted) and also Postgres as a database.
After I while my connections seem to fill up and then my script is been stuck. I checked this with this query SELECT * FROM pg_stat_activity; and read that its caused because Postgres has no connection pool.
I read about txpostgres and PGBouncer, Bouncer regrettably isn't an option, what else can I do to avoid this problem?
So far I use the following pipeline:
import psycopg2
from twisted.enterprise import adbapi
import logging
from datetime import datetime
import scrapy
from scrapy.exceptions import DropItem
class PostgreSQLPipeline(object):
""" PostgreSQL pipeline class """
def __init__(self, dbpool):
self.logger = logging.getLogger(__name__)
self.dbpool = dbpool
#classmethod
def from_settings(cls, settings):
dbargs = dict(
host=settings['POSTGRESQL_HOST'],
database=settings['POSTGRESQL_DATABASE'],
user=settings['POSTGRESQL_USER'],
password=settings['POSTGRESQL_PASSWORD'],
)
dbpool = adbapi.ConnectionPool('psycopg2', **dbargs)
return cls(dbpool)
def process_item(self, item, spider):
d = self.dbpool.runInteraction(self._insert_item, item, spider)
d.addErrback(self._handle_error, item, spider)
d.addBoth(lambda _: item)
return d
def _insert_item(self, txn, item, spider):
"""Perform an insert or update."""
now = datetime.utcnow().replace(microsecond=0).isoformat(' ')
txn.execute(
"""
SELECT EXISTS(
SELECT 1
FROM expose
WHERE expose_id = %s
)
""", (
item['expose_id'],
)
)
ret = txn.fetchone()[0]
if ret:
self.logger.info("Item already in db: %r" % (item))
txn.execute(
"""
UPDATE expose
SET last_seen=%s, offline=0
WHERE expose_id=%s
""", (
now,
item['expose_id']
)
)
else:
self.logger.info("Item stored in db: %r" % (item))
txn.execute("""
INSERT INTO expose (
expose_id,
title
) VALUES (%s, %s)
""", (
item['expose_id'],
item['title']
)
)
# Write image info (path, original url, ...) to db, CONSTRAIN to expose.expose_id
for image in item['images']:
txn.execute(
"""
INSERT INTO image (
expose_id,
name
) VALUES (%s, %s)
""", (
item['expose_id'],
image['path'].replace('full/', '')
)
)
def _handle_error(self, failure, item, spider):
"""Handle occurred on db interaction."""
# do nothing, just log
self.logger.error(failure, failure.printTraceback())

optional include with entity framework

I'm working on a manager. Depending on the conditions some include must be enforced in order to get eager loading. But sometime I don't want all the data so the includes should not be applied.
This is what I've got so far.
//INFO : public partial class Entities : DbContext
var Database = new Entities();
var result = Database.Department;
if (includeHospitalEmployee) { result.Include(a => a.HospitalEmployee); }
if (includeQuickScans) { result.Include(a => a.QuickScan); }
return result;
This doesn't work. The includes aren't loaded, although the includebooleans are set to true. Query results in;
SELECT
[Extent1].[Code] AS [Code],
[Extent1].[Discipline] AS [Discipline],
[Extent1].[FinancialCode] AS [FinancialCode],
[Extent1].[Name] AS [Name],
[Extent1].[DepartmentManagerId] AS [DepartmentManagerId],
[Extent1].[Show] AS [Show],
[Extent1].[Id] AS [Id]
FROM [dbo].[Department] AS [Extent1]
But strange enough if i do this, all include are working
//INFO : public partial class Entities : DbContext
var Database = new Entities();
var result = this.businessManagersFactory.Database.Department.Include(a => a.QuickScan);;
if (includeHospitalEmployee) { result.Include(a => a.HospitalEmployee); }
if (includeQuickScans) { result.Include(a => a.QuickScan); }
return result;
see the query
SELECT
[Project1].[C1] AS [C1],
[Project1].[Code] AS [Code],
[Project1].[Discipline] AS [Discipline],
[Project1].[FinancialCode] AS [FinancialCode],
[Project1].[Name] AS [Name],
[Project1].[DepartmentManagerId] AS [DepartmentManagerId],
[Project1].[Show] AS [Show],
[Project1].[Id] AS [Id],
[Project1].[C2] AS [C2],
[Project1].[Id1] AS [Id1],
[Project1].[StartDateTime] AS [StartDateTime],
[Project1].[EndDateTime] AS [EndDateTime],
[Project1].[Shared] AS [Shared],
[Project1].[ScanStatus] AS [ScanStatus],
[Project1].[Title] AS [Title],
[Project1].[Count] AS [Count],
[Project1].[Comment] AS [Comment],
[Project1].[HospitalEmployeeId] AS [HospitalEmployeeId],
[Project1].[DepartmentId] AS [DepartmentId]
FROM ( SELECT
[Extent1].[Code] AS [Code],
[Extent1].[Discipline] AS [Discipline],
[Extent1].[FinancialCode] AS [FinancialCode],
[Extent1].[Name] AS [Name],
[Extent1].[DepartmentManagerId] AS [DepartmentManagerId],
[Extent1].[Show] AS [Show],
[Extent1].[Id] AS [Id],
1 AS [C1],
[Extent2].[Id] AS [Id1],
[Extent2].[StartDateTime] AS [StartDateTime],
[Extent2].[EndDateTime] AS [EndDateTime],
[Extent2].[Shared] AS [Shared],
[Extent2].[ScanStatus] AS [ScanStatus],
[Extent2].[Title] AS [Title],
[Extent2].[Count] AS [Count],
[Extent2].[Comment] AS [Comment],
[Extent2].[HospitalEmployeeId] AS [HospitalEmployeeId],
[Extent2].[DepartmentId] AS [DepartmentId],
CASE WHEN ([Extent2].[Id] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C2]
FROM [dbo].[Department] AS [Extent1]
LEFT OUTER JOIN [dbo].[QuickScan] AS [Extent2] ON [Extent1].[Code] = [Extent2].[DepartmentId]
) AS [Project1]
ORDER BY [Project1].[Code] ASC, [Project1].[C2] ASC
Why is this behaviour and how to get it working properly?
regards
I don't have access to Visual Studio to confirm but you will probably find that assigning the return from the call to Include will sort it - it will be something like a QueryObject that implements IQueryable
var Database = new Entities();
IQueryable<Department> result = Database.Departments;
if (includeHospitalEmployee) { result = result.Include(a => a.HospitalEmployee); }
if (includeQuickScans) { result = result.Include(a => a.QuickScan); }
return result;