How to associate multiple tables on Exposed - api

Now I'm creating an API using Kotlin with Exposed, Ktor and Postgres.
When I need to do some select on a table which is associated with another table I have to "parse" the ResultRow to an entity object. If this table have more associations I do have to repeat the association every time, what is weird.
Is there an easy way to do it?
Cuz I think to write a lot of code to create the objects it too much!
Now I'm doing like this.
fun ResultRow.toInterval() = Interval(
this[Intervals.idInterval],
Setting(
this[OfficeSettings.idOffice],
Office(
this[Offices.idOffice],
this[Offices.code],
this[Offices.name]
),
this[OfficeSettings.scheduleDaysRule],
this[OfficeSettings.serviceTimeRule],
this[OfficeSettings.countInterval],
this[OfficeSettings.restTimeRule]
),
this[Intervals.date],
this[Intervals.startTime],
this[Intervals.endTime]
)
Just to parse the result into an Interval, which is associated with a Setting, and Setting is associated with an Office.

Related

Tree-Structures & SQL - Looking for design recommendations

from what I've researched so far, this topic is both well documented and very broad. So I'm hoping you can safe me some time diving into the depths of how to store trees in a database by pointing me in the right direction.
I'm working with questionnaires, similarly to how HL7/FHIR approach them:There's two classes: Questionnaire and Item, with Questionnaire consisting of a Set of Items. However, Items can refer to any number of additional Items (i.e. children).So basically, I have a n-ary tree-like structure with - depending on how you want to look at it -a) a Questionnaire-Object as root and several Items as childrenb) several Items as a root each (i.e. a forest), again each with several Items as children
class Questionnaire {
items: Set<Item>
inner class Item {
children: Set<Item>
}
}
This part of the data structure unfortunately is non-negotiable (other than the use of inner classes, which I could change).
I'm now looking for a sensible way to store such a structure in my database (currently MySQL).
Luckily, I'm only ever storing and reading the whole questionnaire. I do not need to access individual nodes or branches, and the data will not be changed / updated (because any change to an existing Questionnaire will result in a new Questionnaire as per my projects definition). So I only need to work with SELECT and INSERT statements, each for one complete Questionnaire (with all its items).
My first approach was to reverse the Item-to-Item relationship, i.e. referring to one parent rather than several children. However, I fear that this might be hell to translate back into the already fixed object-structure. I'm hoping for a fairly easy solution.
Please note that I am aware that there's probably really nice solutions using ORM, but I've been having trouble wrapping my head around the whole setup progress lately, and am now too pressed for time to get into that. Right now, I need a solution in plain SQL to show results. ORM will have to wait a little, but I will get back to that!Also note that performance does not matter right now.
Thanks in advance for your efforts, your help will be much apreciated!
So here's what I ended up doing in case anyone else is looking for an answer:
Let's take as an example my QuestionnaireResponse class:
data class QuestionnaireResponse (
val qID: String,
val timeStamp: String,
val items: List<Item> = listOf<Item>()) {
inner class Item (val itemID: String, val itemType: String, var unit: String,
var answers: MutableList<String> = mutableListOf())
}
Where qID references the Questionnaire that has been answered here.
When a Questionnaire is answered, I'll receive the above object in JSON. I decided to parse the incoming JSON to my data structure, extract qID and timeStamp, and store those values in my database. That way I can select only those QuestionnaireResponses answering to a specific Questionnaire, and filter by timeStamp, while still circumventing to try and represent that (basically recursive) structure into my Db.
The SQL code to create the corresponding table looks like this:
CREATE TABLE `questionnaireresponses` (
`questionnaireID` int NOT NULL,
`timestamp` varchar(25) NOT NULL,
`questionnaireResonseObject` json DEFAULT NULL,
PRIMARY KEY (`questionnaireID`,`timestamp`),
CONSTRAINT `answeredQuestionnaire` FOREIGN KEY (`questionnaireID`) REFERENCES `questionnaires` (`id`))
From what I read, not all databases support the json data type. What it does in MySQL is making sure that the inserted data is formatted properly. I never mind additional checks, but since I've already been successfully parsing the JSON in my application before inserting it into the Db, that step can be omitted. Thus, if your Db doesn't support the json-type, any type that allows to store strings of variable length (e.g. text or blob) might work as well.

Reference an arbitrary row and field in another table

Is there any form (data type, inherence..) of implement in postgresql something like this:
CREATE TABLE log (
datareferenced table_row_column_reference,
logged boolean
);
The referenced data may be any row field from the database. My objective is implement something like this without use Procedural Language or implement it in a higher layer, using only a relational approach and without modify the rest of the tables. Another feature may be referencial integrity, example:
-- Table foo (id, field1, field2, fieldn)
-- ('bar', '2014-01-01', 4.33, Null)
-- Table log (datareferenced, logged)
-- ({table foo -> id:'bar' -> field2 } <=> 4.33, True)
DELETE FROM foo where id='bar';
-- as result, on cascade, deleted both rows.
I have an application build onto a MVC pattern. The logic is written in Python. The application is a management tool, very data intensive. My goal is implement a module that could store additional information per every data present in the DDBB. Per example, a client have a serie of attributes (name, address, phone, email ...) across multiple tables, and I want that the app could store metadata-like for every registry from all the DDBB. A metadata could be last modification, or a user flag, etc.
I have implemented the metadata model (in postgres), its mapping to objects and a parcial API. But the part left is the most important, the glue. My plan B is create that glue in the data mapping layer as a module. Something like this:
address= person.addresses[0]
address.saveMetadata('foo', 'bar')
-- in the superclass of Address
def saveMetadata(self, code, value):
self.mapper.metadata_adapter.save(self, code, value)
-- in the metadata adapter class:
def save(self, entity, code, value):
sql = """update value=%s from metadata_values
where code=%s and idmetadata=
(select id from metadata_rels mr
where mr.schema=%s and mr.table=%s and
mr.field=%s and mr.recordpk=%s)"""%
(value, code,
self.class2data[entity.__class__]["schema"],
self.class2data[entity.__class__]["table"],
self.class2data[entity.__class__]["field"],
entity.id)
self.mapper.execute(sql)
def read(self, entity , code):
sql = """select mv.value
from metadata_values mv
join metadata_rels mr on mv.idmetadata=mr.id
where mv.code=%s and mr.schema=%s and mr.table=%s and
mr.field=%s and mr.recordpk=%s"""%
(code,
self.class2data[entity.__class__]["schema"],
self.class2data[entity.__class__]["table"],
self.class2data[entity.__class__]["field"],
entity.id )
return self.mapper.execute(sql)
But it would add overhead between python and postgresql, complicate Python logic, and using PL and triggers may be very laborious and bug-prone. That is why i'm looking at doing the same at the DDBB level.
No, there's nothing like that in PostgreSQL.
You could build triggers yourself to do it, probably using a composite type. But you've said (for some reason) you don't want to use PL/PgSQL, so you've ruled that out. Getting RI triggers right is quite hard, though, and you must apply a trigger to the referencing and referenced ends.
Frankly, this seems like a square peg, round hole kind of problem. Are you sure PostgreSQL is the right choice for this application?
Describe your needs and goal in context. Why do you want this? What problem are you trying to solve? Maybe there's a better way to approach the same problem one step back...

Updating SQL from object with groovy

When you read in a result set in Groovy it comes in a collection of maps.
Seems like you should be able to update values inside those maps and write them back out, but I can't find anything built into groovy to allow me to do so.
I'm considering writing a routine that allows me to write a modified map by iterating over the fields of one of the result objects, taking each key/value pair and using them to create the appropriate update statement, but it could be annoying so I was wondering if anyone else had done this or if it'sa vailable already in groovy.
It seems like just a few lines of code so I'd rather not bring in hibernate for this. I'm just thinking a little "update" method that would allow:
def rows=sql.rows(query)
rows[0].name="newName"
update(sql, rows[0])
to update the first guy's name in the database. Anyone seen/created such a monster, or is something like this already built into Groovy Sql and I'm just missing it?
(I suppose you may have to point out to the update method which field is the key field, but that's doable...)
Using the rows method will actually read out all of the values into a List of GroovyRowResult so it's not really possible to update the data without creating an update method like the one you mention.
It's not really possible to do that in the generic case because your query can contain joins or a column reference that is an aggregate, etc.
If you're selecting from a single table use the Sql.eachRow method however and set the ResultSet to be an updatable one, you can use the underlying ResultSet interface to update as you iterate through:
sql.resultSetConcurrency = ResultSet.CONCUR_UPDATABLE
sql.resultSetType = ResultSet.TYPE_FORWARD_ONLY
sql.eachRow(query) { row ->
row.updateString('name', 'newName')
row.updateRow()
}
Depending on the database/driver you use, you may not be able to create an updatable ResultSet.

Loading a entity IDs CSV column as hydrated entities in NHibernate

I have a number of database table that looks like this:
EntityId int : 1
Countries1: "1,2,3,4,5"
Countries2: "7,9,10,22"
I would like to have NHibernate load the Country entities identifed as 1,2,3,4,5,7,9 etc. whenever my EntityId is loaded.
The reason for this is that we want to avoid a proliferation of joins, as there are scores of these collections.
Does fetching the countries have to happen as the entity is loaded - it is acceptable that you run a query to fetch these? (You could amend your DAO to run the query after fetching the entity.) The reason I ask is that simply running a query compared to having custom code invoked when entities are loaded requires less "plumbing" and framework innards.
After fecthing your entity, and you have the Country1,Country2 lists, You can run a query like:
select c from Country c where c.id in (:Country1)
passing :Country1 as a named parameter. You culd also retrieve all rows for both sets of countries
select Entity e where e.id in (:Country1, :Country2)
I'm hoping the country1 & country2 strings can be used as they are, but I have a feeling this won't work. If so, you should convert the Strings to a collection of Integers and pass the collection as the query parameter.
EDIT: The "plumbing" to make this more transparent comes in the form of the IInterceptor interface. This allows you to plug in to how entities are loaded, saved, updated, flushed etc. Your entity will look something like this
class MyEntity
{
IList<Country> Country1;
IList<Country> Country2;
// with public getter/setters
String Country1IDs;
String Country2IDs;
// protected getter and setter for NHibernate
}
Although the domain object has two representations of the list - the actual entities, and the list of IDs, this is the same intrusion that you have when declaring a regular ID field in an entity. The collections (country1 and Country2) are not persisted in the mapping file.
With this in place, you provide an IInterceptor implementation that hooks the loading and saving. On loading, you fetch the value of the countryXID property an use to load the list of countries (as I described above.) On saving, you turn the IList of countries into an ID list, and save this value.
I couldn't find the documentation for IInterceptor, but there are many projects on the net using it. The interface is described in this article.
No you cannot, at least not with default functionality.
Considering that there is no SPLIT string function in SQL it would be hard for any ORM to detect the discreet integer values delimited by commas in a varchar column. If you somehow (custom sql func) overcame that obstacle, your best shot would be to use some kind of component/custom user type that would still make a smorgasbond of joins on the 'Country' table to fetch, in the end, a collection of country entities...
...but I'm not sure it can be done, and it would also mean writing from scratch the persistence mechanism as well.
As a side note, I must say that i don't understand the design decision; you denormalized the db and, well, since when joins are bad?
Also, the other given answer will solve your problem without re-designing your database, and without writing a lot of experimental plumbing code. However, it will not answer your question for hydration of the country entities
UPDATE:
on a second thought, you can cheat, at least for the select part.
You could make a VIEW the would split the values and display them as separate rows:
Entity-Country1 View:
EntityId Country
1 1
1 2
1 3
etc
Entity-Country2 View:
EntityId Country
1 7
1 9
1 10
etc
Then you can map the view

nhibernate and DDD suggestion

I am fairly new to nHibernate and DDD, so please bear with me.
I have a requirement to create a new report from my SQL table. The report is read-only and will be bound to a GridView control in an ASP.NET application.
The report contains the following fields Style, Color, Size, LAQty, MTLQty, Status.
I have the entities for Style, Color and Size, which I use in other asp.net pages. I use them via repositories. I am not sure If should use the same entities for my report or not. If I use them, where I am supposed to map the Qty and Status fields?
If I should not use the same entities, should I create a new class for the report?
As said I am new to this and just trying to learn and code properly.
Thank you
For reports its usually easier to use plain values or special DTO's. Of course you can query for the entity that references all the information, but to put it into the list (eg. using databinding) it's handier to have a single class that contains all the values plain.
To get more specific solutions as the few bellow you need to tell us a little about your domain model. How does the class model look like?
generally, you have at least three options to get "plain" values form the database using NHibernate.
Write HQL that returns an array of values
For instance:
select e1.Style, e1.Color, e1.Size, e2.LAQty, e2.MTLQty
from entity1 inner join entity2
where (some condition)
the result will be a list of object[]. Every item in the list is a row, every item in the object[] is a column. This is quite like sql, but on a higher level (you describe the query on entity level) and is database independent.
Or you create a DTO (data transfer object) only to hold one row of the result:
select new ReportDto(e1.Style, e1.Color, e1.Size, e2.LAQty, e2.MTLQty)
from entity1 inner join entity2
where (some condition)
ReportDto need to implement a constructor that has all this arguments. The result is a list of ReportDto.
Or you use CriteriaAPI (recommended)
session.CreateCriteria(typeof(Entity1), "e1")
.CreateCriteria(typeof(Entity2), "e2")
.Add( /* some condition */ )
.Add(Projections.Property("e1.Style", "Style"))
.Add(Projections.Property("e1.Color", "Color"))
.Add(Projections.Property("e1.Size", "Size"))
.Add(Projections.Property("e2.LAQty", "LAQty"))
.Add(Projections.Property("e2.MTLQty", "MTLQty"))
.SetResultTransformer(AliasToBean(typeof(ReportDto)))
.List<ReportDto>();
The ReportDto needs to have a proeprty with the name of each alias "Style", "Color" etc. The output is a list of ReportDto.
I'm not schooled in DDD exactly, but I've always modeled my nouns as types and I'm surprised the report itself is an entity. DDD or not, I wouldn't do that, rather I'd have my reports reflect the results of a query, in which quantity is presumably count(*) or sum(lineItem.quantity) and status is also calculated (perhaps, in the page).
You haven't described your domain, but there is a clue on those column headings that you may be doing a pivot over the data to create LAQty, MTLQty which you'll find hard to do in nHibernate as its designed for OLTP and does not even do UNION last I checked. That said, there is nothing wrong with abusing HQL (Hibernate Query Language) for doing lightweight reporting, as long as you understand you are abusing it.
I see Stefan has done a grand job of describing the syntax for that, so I'll stop there :-)