I'm trying to make a todo application on Spring. It's almost finished but I got a problem. I need to filter todos by user id and select them which is in the between given dates. I've created a method for this in my TodoRepository. But when I send the request to the url, it gives me empty array.
Here's the repository class:
All methods work fine except the one I mentioned btw.
#Repository
public interface TodoRepository extends JpaRepository<Todo, Long> {
List<Todo> findTodosByUserId(Long id);
List<Todo> findTodosByUserIdOrderByDateAsc(String id);
List<Todo> findAllByDateBetween(Date date, Date date2);
List<Todo> findTodosByDateBetweenAndUserId(Date date, Date date2, Long id);
}
That's the method i use in the TodoService class:
#Service
public class TodosService {
#Autowired
TodoRepository todoRepository;
//other methods..
public List<Todo> filterTodosByUserId(FilterTodoByUserDto dto){
Date date1 = dto.getDate1();
Date date2 = dto.getDate2();
Long id = dto.getId();
return todoRepository.findTodosByDateBetweenAndUserId(date1, date2, id);
}
}
FilterTodoByUserDto class:
public class FilterTodoByUserDto {
private Long id;
private Date date1;
private Date date2;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Date getDate1() {
return date1;
}
public void setDate1(Date date1) {
this.date1 = date1;
}
public Date getDate2() {
return date2;
}
public void setDate2(Date date2) {
this.date2 = date2;
}
#Override
public String toString() {
return "FilterTodoByUserDto{" +
"id=" + id +
", date1=" + date1 +
", date2=" + date2 +
'}';
}
}
And lastly, controller class:
#RestController
#RequestMapping("/api")
public class TodoController {
#Autowired
private TodosService todosService;
//other methods..
#GetMapping("user/todos/filter")
public List<Todo> filterTodosById(#RequestBody FilterTodoByUserDto dto){
List<Todo> todos = todosService.filterTodosByUserId(dto);
return todos;
}
//other methods..
}
Request body that i sent with postman:
{"userId":"1", "date1":"2021-01-01", "date2":"2000-01-01"}
Database output:
mysql> select * from todos;
+----+----------------------------+-------------+-------------+---------+
| id | date | description | todo_status | user_id |
+----+----------------------------+-------------+-------------+---------+
| 1 | 2012-12-12 00:00:00.000000 | deneme | TODO | 2 |
| 2 | 2010-10-10 00:00:00.000000 | deneme2 | TODO | 2 |
| 3 | 2010-01-01 00:00:00.000000 | deneme5 | DONE | 1 |
| 4 | 2010-01-01 00:00:00.000000 | deneme | DONE | 1 |
| 5 | 2010-01-01 00:00:00.000000 | deneme | DONE | 1 |
| 6 | 2010-01-01 00:00:00.000000 | deneme | DONE | 1 |
| 7 | 2010-01-01 00:00:00.000000 | deneme | DONE | 1 |
| 8 | 2010-01-01 00:00:00.000000 | deneme | DONE | 1 |
| 9 | 2010-01-01 00:00:00.000000 | deneme | DONE | 2 |
+----+----------------------------+-------------+-------------+---------+
9 rows in set (0,01 sec)
Change your request json like this:
{
"id": "1",
"date1": "2000-01-01",
"date2": "2021-01-01"
}
Your fields in your DTO model should match your json fields. (userId -> id)
BETWEEN returns true if the value of date is greater than or equal to the value of begin_expression and less than or equal to the value of end_expression. (.. date BETWEEN date1 AND date2)
You are getting empty array due to your postman request is logically wrong. When BETWEEN use date1 must be the minimum value and date2 must be the maximum value.
ex: The following date example uses the BETWEEN condition to retrieve values within a date range.
SELECT *
FROM todos
where user_id=1
and date between '2000-01-01' and '2021-01-01';
Above BETWEEN SQL would be equivalent to the following SELECT statement:
SELECT *
FROM todos
where user_id=1
and date >= '2000-01-01' and date<= '2021-01-01';
I have a list with type MyClass, and MyClass has several attributes.
How can i retrieve data using CsvHelper, if .csv file looks like this? (Yes, attributes of type Data1 are numbered.)
Date | Data1 | Unit | Data2 | Unit | Data3 | Unit | ... | DataN | Unit
-----------|----------|-------|----------|-------|----------|-------|-----|----------|----------
2020.01.02 | 1 | kW | 3 | kW | 1.5 | kW | ... | 0 | kW
2020.01.03 | 0 | kW | 4 | kW | 1 | kW | ... | 3 | kW
2020.01.04 | 4 | kW | 2 | kW | 1 | kW | ... | 2 | kW
This is what i want to see. The objects are stored in a list that can store MyClass type.
List(MyClass) = [Object-1, Object-1, Object-3, ..., Object-N]
Object-1: [(2020.01.02.,1, kW),(2020.01.03.,0, kW),,(2020.01.04.,4, kW)]
Object-2: [(2020.01.02.,3, kW),(2020.01.03.,4, kW),,(2020.01.04.,2, kW)]
Object-3: [(2020.01.02.,1.5, kW),(2020.01.03.,1, kW),,(2020.01.04.,1, kW)]
...
Object-N: [(2020.01.02.,0, kW),(2020.01.03.,3, kW),,(2020.01.04.,2, kW)]
MappedClass{
private DateTime Date;
private List List;
}
MyClass{
private DateTime Date;
private string A1; //Attribute1
private int A2; //Attribute2
}
If the properties of only one object are listed, then i can do the task, but not with multiple objects and this layout.
I thought of reading the file row by row and then somehow pairing its related data.
How to do this task effectively?
This would be one way to do it.
public class Program
{
public static void Main(string[] args)
{
using (MemoryStream stream = new MemoryStream())
using (StreamWriter writer = new StreamWriter(stream))
using (StreamReader reader = new StreamReader(stream))
using (CsvReader csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
writer.WriteLine("Date,Data1,Unit,Data2,Unit,Data3,Unit");
writer.WriteLine("2020.01.02,1,kw,3,kw,1.5,kw");
writer.WriteLine("2020.01.03,0,kw,4,kw,1,kw");
writer.Flush();
stream.Position = 0;
var records = new List<MappedClass>();
csv.Read();
csv.ReadHeader();
while (csv.Read())
{
var record = new MappedClass
{
Date = record.Date,
Date = csv.GetField<DateTime>(0),
List = new List<MyClass>()
};
for (int i = 1; i < csv.Context.HeaderRecord.Length; i += 2)
{
var item = new MyClass
{
Data = csv.GetField<decimal>(i),
Unit = csv.GetField<string>(i + 1)
};
record.List.Add(item);
}
records.Add(record);
}
}
}
}
public class MappedClass
{
public DateTime Date { get; set; }
public List<MyClass> List { get; set; }
}
public class MyClass {
public DateTime Date;
public string Unit; //Attribute1
public decimal Data; //Attribute2
}
I am developing a ASP.NET Core frontend to connect to my Google Cloud SQL MySQL database.
I have the following model:
namespace shipping.Models
{
public class ShippingAppContext : DbContext
{
public ShippingAppContext(DbContextOptions<ShippingAppContext> options) : base(options) { }
public DbSet<Ship> ships { get; set; }
public DbSet<Company> companies { get; set; }
}
public class Ship
{
public int Id { get; set; }
public string Name { get; set; }
public virtual Company Company { get; set; }
}
public class Company
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Ship> Ships { get; set; }
}
}
and I iterate over _context.ships.ToListAsync() in a razor page which shows ship.Name and ship.Company.Name.
and my database is as follows:
MySQL [shipping]> show tables;
+--------------------+
| Tables_in_shipping |
+--------------------+
| companies |
| ships |
+--------------------+
MySQL [shipping]> select * from ships;
+------+-----------------+---------+
| Id | Name | Company |
+------+-----------------+---------+
| 1 | Eugen Maersk | 1 |
| 2 | Madrid Maersk | 1 |
| 3 | COSCO Vancouver | 4 |
| 4 | COSCO Rotterdam | 4 |
+------+-----------------+---------+
MySQL [shipping]> select * from companies;
+------+----------------------------------------------+
| Id | Name |
+------+----------------------------------------------+
| 1 | A.P. Moller–Maersk Group |
| 2 | Mediterranean Shipping Company S.A. (MSC) |
| 3 | CMA CGM Group |
| 4 | China Ocean Shipping (Group) Company (COSCO) |
+------+----------------------------------------------+
This works fine with just show ship.Name but as soon as I try to show ship.Company.Name I get: MySqlException: Unknown column 's.CompanyId' in 'field list'.
I have done a search and CompanyId is not referenced anywhere in the project. The ships table does not contain a CompanyId column.
I guess this is probably because I have created the tables and data directly in the sql instance rather than using dotnet ef to create the database and upload it. But I don't think this is possible on Google Cloud SQL?
How can I make efcore do INNER JOIN from my model?
If you are manually create the database , you can manually add the table schema with FOREIGN KEY constraints relationship(FK_ships_companies_CompanyId) ,so that you could query the related data like :
var result = _context.ships.Include(a=> a.Company).ToList();
Items Table
| id | item_id | item_title |
|-------|---------|------------|
| 1 | 1002 | A |
| 2 | 1003 | B |
| 3 | 1004 | C |
Sells Table
| id | item_id |
|----|-----------|
| 1 | 1002 1003 |
| 2 | 1003 1004 |
| 3 | 1004 1002 |
I want result : Sells Table 1. item title is A B
I want to combine the sells table with the item table and then match the item_id of the sells table to the item_title of the item table.
The table definitions look incorrect, you should have a pivot table linking items with sells, so a sell_item table:
item_id | sell_id
-----------------
1 | 1
1 | 3
2 | 1
2 | 2
3 | 2
3 | 3
Then using eloquent, you'd create models to represent your tables and define the relationships using BelongsToMany:
class Item extends Model {
public function sells() {
return $this->belongsToMany(Sell::class);
}
}
class Sell extends Model {
public function items() {
return $this->belongsToMany(Item::class);
}
}
Each instance of either model will then have access to it's related models via $item->sells and $sell->items.
The query builder can perform a join if not going the Eloquent route:
DB::table('sells')->join('items', 'sells.item_id', '=', 'items.item_id')
->select('sells.*', 'items.title')
->get();
The table definitions look incorrect, If you corrected already then your model replationship should be like
class Item extends Model {
public function sells() {
return $this->belongsToMany(Sell::class);
}
}
class Sell extends Model {
public function items() {
return $this->belongsToMany(Item::class);
}
}
Each instance of either model will then have access to it's related models via $item->sells and $sell->items.
The query builder can perform a join if not going the Eloquent route:
DB::table('sells')->join('items', 'sells.item_id', '=', 'items.item_id')
->select('sells.*', 'items.title')
->get();
Or if your model name is Sell then
$response=Sell::with('items')->get();
Here are some entities:
public class Zone : AbstractGuidKeyedEntity
{
public virtual string Name { get; set; }
public virtual string Description { get; set; }
}
public class ZoneGroup : AbstractGuidKeyedEntity
{
public virtual string Name { get; set; }
public virtual ICollection<Zone> Zones { get; set; }
}
public class Contract: AbstractGuidKeyedEntity
{
public virtual string Name { get; set; }
public virtual ICollection<Zone> Zones { get; set; }
}
Here are the rules:
A Zone can belong to a ZoneGroup or a Contract.
A Zone cannot belong to both a ZoneGroup and a Contract.
Here is what I want:
One join table that has a unique id on zone.
What I will settle for:
Something that works.
How do I fluently map this with Entity Framework 4.1?
Thank you for your brain power.
-- EDIT --
Here are the tables I would like.
Zone
--------------------------
| ZoneId | Name |
==========================
| lkj-lakjd | Front |
| asd-jkllk | Rear |
--------------------------
ZoneGroup
--------------------------
| ZoneId | Name |
==========================
| uio-asdfd | Z71 Boat |
--------------------------
Contract
--------------------------
| ZoneId | Name |
==========================
| zxc-qwert | Hugo Taylor|
--------------------------
ZoneGroupContractZone
--------------------------------------
| ZoneId | ZonableId | Type |
======================================
| lkj-lakjd | uio-asdfd | ZoneGroup |
| asd-jkllk | zxc-qwert | Contract |
--------------------------------------