I am reading about DDD and I have learned that Value Object is immutable, if you want to change it, you will have to create a new one.
I have just read the information on How are Value Objects stored in the database? , it works well for Address class and I also read https://cargotracker.java.net/ and https://gojko.net/2009/09/30/ddd-and-relational-databases-the-value-object-dilemma/. But I want to do something different .
I am working on a billing system , it has 4 tables/classes
TPerson - fields: id_person, name -> <<Entity>>
TMobile - fields: id_mobile, number -> <<Entity>>
TPeriod - fields: id_period, id_person, id_mobile, begin_date, end_date -> <<Value Object>> (I think, because the dates can be change)
TCall - field: id_call, id_period, etc... -> <<Value Object>>
The table TCall has many records, if I change the period record dates (Value Object, table TPeriod) it will create another Object Period then id_period will change(delete, insert a record) , but the foreign key in table TCall will be violated. How Could I implement the period class ? if i implement as a value object , it will be immutable and turns out I will not be able to change anything whatsoever.
Thanks,
Fernando
if it's a value object you don't have a period table/id.
A value object is just a grouping of certain fields. For example a call might have a start time, an end time, and then you could create a Duration Value object with starttime and end time from the call table. In your java code it would be then more convenient to talk about the call duration instead of the start/end time separately.
However, it certainly could make sense to make period an entity, but then period 201601 probally always have the same start/end time and you wouldn't need to make changes to it. And if you did you make changes to the entity directly and keeping the ids in tact.
Thank for your help,
I have this situation:
TPerson - fields: id_person = 1 , name = "John"
TMobile - fields: id_mobile = 100, number "555-0123"
TPeriod - fields: id_period = 1000, id_person = 1 , id_mobile = 1, begin_date = "2016-01-01", end_date = "2049-12-31"
TCall - field: id_call = 1, id_period = 1000
The period is a relation between TPerson and TPeriod, in this example John has a mobile between "2016-01-01" and "2049-12-31". On the table TCall there are John's calls record, but if i replace the period (TPeriod table) end_date to "2016-02-01", from my understanding the end_date will be inconsistent, it turns out i cann't replace because it's a value object, not a entity. I considered to implement like this.
// Create a class DatePeriod
public class DatePeriod {
private final begin_date;
private final end_date;
DatePeriod() {}
public static DatePeriod of(Date begin_date, Date end_date) {
this.begin_date = begin_date;
this.end_date = end_date;
}
// implement equals / hashcode...
}
// Period class
public class Period {
int id;
// others mappings id_person / id_mobile
DatePeriod datePeriod;
}
Still, i will have to update datePeriod attribute
Thank you for your attention to this matter
Related
I have 2 tables contractPoint and contractPointHistory
ContractPointHistory
ContractPoint
I would like to get contractPoint where point will be subtracted by pointChange. For example: ContractPoint -> id: 3, point: 5
ContractPointHistory has contractPointId: 3 and pointChange: -5. So after manipulating point in contractPoint should be 0
I wrote this code, but it works just for getRawMany(), not for getMany()
const contractPoints = await getRepository(ContractPoint).createQueryBuilder('contractPoint')
.addSelect('"contractPoint".point + COALESCE((SELECT SUM(cpHistory.point_change) FROM contract_point_history AS cpHistory WHERE cpHistory.contract_point_id = contractPoint.id), 0) AS points')
.andWhere('EXTRACT(YEAR FROM contractPoint.validFrom) = :year', { year })
.andWhere('contractPoint.contractId = :contractId', { contractId })
.orderBy('contractPoint.grantedAt', OrderByDirection.Desc)
.getMany();
The method getMany can be used to select all attributes of an entity. However, if one wants to select some specific attributes of an entity then one needs to use getRawMany.
As per the documentation -
There are two types of results you can get using select query builder:
entities or raw results. Most of the time, you need to select real
entities from your database, for example, users. For this purpose, you
use getOne and getMany. But sometimes you need to select some specific
data, let's say the sum of all user photos. This data is not an
entity, it's called raw data. To get raw data, you use getRawOne and
getRawMany
From this, we can conclude that the query which you want to generate can not be made using getMany method.
I have an endpoint lets say /order/ where i can send json object(my order), which contains some products etc, so my problem is i have to first save the order and wait for the order id back from the db and then save my products with this new order id( we are talking many to many relation thats why theres another table)
Consider this controller method
def postOrder = Action(parse.json[OrderRest]) { req => {
Created(Json.toJson(manageOrderService.insertOrder(req.body)))
}
}
this is how my repo methods look like
def addOrder(order: Order) = db.run {
(orders returning orders) += order
}
how can i chain db.runs to first insert order, get order id and then insert my products with this order id i just got?
im thinking about putting some service between my controller and repo, and managing those actions there, but i have no idea where to start
You can use for to chain database operations. Here is an example of adding a table to a db by adding a header row to represent the table and then adding the data rows. In this case it is a simple table containing (age, value).
/** Add a new table to the database */
def addTable(name: String, table: Seq[(Int, Int)]) = {
val action = for {
key <- (Headers returning Headers.map(_.tableId)) += HeadersRow(0, name)
_ <- Values ++= table.map { case (age, value) => ValuesRow(key, age, value) }
} yield key
db.run(action.transactionally)
}
This is cut down from the working code, but it should give the idea of how to do what you want. The first for statement would generate the order id and then the second statement would add the order with that order id.
This is done transactionally so that the new order will not be created unless the order data is valid (in database terms).
I have two models a parent and the son contains two float fields
one of the values this calculates according to the other but when I change the father how can be my calculating function.
Here is my example:
class A(models.model):
trv_ids = fields.One2many(classB,id_A)
class B(models.model):
id_A = fields.Many2one(classA)
qtite = fields.float(default=0)
qtite1 = fields.float(default=0,compute=?????)
qtite1 gets the value of qtite when I change parent
as the example of cumulated amount becomes previous quantity the next month.
Thanks
If i understood right i think what you need is something like this:
#api.depends('id_A')
def _compute_qtie1(self):
for record in self:
record.qtite1 = record.qtite
qtite1 = fields.float(compute=_compute_qtie1, store=True)
The depends is what triggers (any time you change the id_A field in the record) the compute method, if you dont store it in the DB it will re-calculate every time you open a view that contains the record.
I'm new to web development and rails, and I'm trying to construct a query object for my first time. I have a table Players, and a table DefensiveStats, which has a foriegn-key player_id, so each row in this table belongs to a player. Players have a field api_player_number, which is an id used by a 3rd party that I'm referencing. A DefensiveStats object has two fields that are relevant for this query - a season_number integer and a week_number integer. What I'd like to do is build a single query that takes 3 parameters: an api_player_number, season_number, and week_number, and it should return the DefensiveStats object with the corresponding season and week numbers, that belongs to the player with api_player_number = passed in api_player_number.
Here is what I have attempted:
class DefensiveStatsWeekInSeasonQuery
def initialize(season_number, week_number, api_player_number)
#season_number = season_number
#week_number = week_number
#api_player_number = api_player_number
end
# data method always returns an object or list of object, not a relation
def data
defensive_stats = Player.where(api_player_number: #api_player_number)
.joins(:defensive_stats)
.where(season_number:#season_number, week_number: #week_number)
if defensive_stats.nil?
defensive_stats = DefensiveStats.new
end
defensive_stats
end
end
However, this does not work, as it performs the second where clause on the Player class, and not the DefensiveStats class -> specifically, "SQLite3::SQLException: no such column: players.season_number"
How can I construct this query? Thank you!!!
Player.joins(:defensive_stats).where(players: {api_player_number: #api_player_number}, defensive_stats: {season_number: #season_number, week_number: #week_number})
OR
Player.joins(:defensive_stats).where("players.api_player_number = ? and defensive_stats.season_number = ? and defensive_stats.week_number = ?", #api_player_number, #season_number, #week_number)
I have two Tables.
Order - With Columns OrderID, OrderStatusID
OrderStatus - With Columns OrderStatusID, Description
I have an Order Object which calls to the database and fills its properties for use in my code. Right now I have access to Order.OrderStatusID, but in my application I really need access to the "Description" field.
How do you handle this elegantly with good OO design?
Usually I prefer to handle lookups as Value objects. I also use Null Object pattern.
public class Order {
private int statusID;
public OrderStatus Status {
get {
return OrderStatus.Resolve(statusID);
}
set {
statusID = value != null ? value.ID : null;
}
}
}
public class OrderStatus {
public static OrderStatus Resolve(int statusID)
{
OrderStatus status = null;
// read from cache or DB
...
// if not found return Null object
if (status == null)
status = new OrderStatus(null, string.Empty);
return status;
}
}
The system I'm currently working with creates an instance of the other business object and sets the Id. The other business object is then retrieved when it is used. e.g.
Order Properties
int OrderId = 5
int OrderStatusId = 3
OrderStatus OrderStatus_ref
{
get
{
if OrderStatus_ref == null
OrderStatus_ref = new OrderStatus(OrderStatusId)
return OrderStatus_ref
}
}
That's the general idea anyways.
You can use a SQL select statement with a Join to the OrderStatus table, and include the columns yo want from each table ...
Select O.OrderId, O.OrderStatusId, S.Descriptiuon
From Order O
Join OrderStatus S
On S.OrderStatusId = O.OrderStatusId
Where OrderId = 23 -- or whatever
Is it a one-to-one relationship between Order and OrderStatus? I guess it depends on the purpose to why you would have an OrderStatus table as I would argue that there isnt actually any need for a separate OrderStatus table?
Basically all that table gives you is the ability to change the description of the order status. From within code, you would then be writing code according to either a predefined OrderStatusID (from seed data?) or via the description. If this is the case then why not have the Order table contain an OrderStatus column which is an integer and that can map to an enum type?
My Order object would probably include the status description field (readonly [to non internal classes]), as well as any other similar fields.
Under the hood my getters (e.g. LoadByID, LoadAll, etc) would probably use a View (e.g. OrdersView) that contains all of those descriptive fields. Those description fields are readonly so that you don't accidentally set those fields thinking that you can save the changes to the database.