I have classes that follow a composite pattern relationship for which I need to create the relational data model for Oracle database.
The (java) classes are as below -
class AbstractEmployee {
int employeeId;
}
class Employee extends AbstractEmployee {
Date joiningDate;
}
class Supervisor extends AbstractEmployee {
List<AbstractEmployee> directs;
int officeLocationId;
}
Clearly, there are attributes which are shared across all classes and there are other attributes which are specific to each class. What would be the best way to create sql tables for the above scenario?
I can see that there are different ways to handle hierarchy namely - TPC, TPH and TPT as provided on this post - inheritance in databases. However, composite patterns pose additional complexity in being intrinsically recursive structures, and as a result, the select/insert query performance can be drastically impacted by the schema.
If possible, please discuss the pros/cons of your solution in terms of scalability and performance.
Related
I am trying to build application by spring boot and Domain Driven Design. I have a problem about Domain model (match with fields of table DB) and View Model (response API).
Domain Model:
EX:
class Name
#Getter
#NoArgsConstructor
#AllArgsConstructor
class Name {
String value;
}
class Product
#Getter
#NoArgsConstructor
#AllArgsConstructor
class Product{
Name name;
}
ViewModel:
#Data
#NoArgsConstructor
#AllArgsConstructor
class ProductView {
//int prodId;
String prodName;
}
Select data DB by class Product, builder to Response API by class ProductView. When that convert from DomainModel to ViewModel or vice versa, I written static method in ProductView for that.
It will become:
#Data
#NoArgsConstructor
#AllArgsConstructor
class ProductView {
//int prodId;
String prodName;
public static ProductView of(Product prod) {
String productName = prod.getName().getValue();
return new ProductView(productName)
}
}
It works well, but when the data becomes more. I think need that as CommonConvert from DomainModel to ViewModel and vice versa.
I have a solution use Mapstruct library. But Mapstruct only support to convert field same type(String with String, ex). What is the best solution for writting CommonConvert?
My advice: do not query domain models and translate them to view models for reading.
Domain model classes (e.g. aggregates) are used to represent business data and behaviour with the to purpose to adhere to business invariants when creating or changing such business entities.
For building your view models from your persistent data you can - and in my opinion you should - bypass the domain model. You can safely read the data from your database as you need it without going through domain repositories.
This is okay because you can't violate business rules by just reading data. For writing data go through domain repositories and aggregates.
In your case you can of course use view model entities using JPA annotations by designing those classes to exactly fit your viewing requirements. Keep in mind that view models often don't correlate to domain models as they might only need a subset of the data or aggregate data from different aggregates.
Another catch is that if you need to query many objects for viewing can quickly cause performance issues if you query full domain aggregates via repositories. As such aggregates always load all data from it's child entities and value objects as well to allow for performing business logic with all invariants you would end up performing lots of expensive queries which are suited for loading a single aggregate but not many of them at once.
So by querying only what you need for viewing you also address such performance issues.
When following DDD you should usually create or change only one aggregate within a business transaction. So domain models are not suited for query optimization but for keeping the business invariants in tact when writing business data.
View models and corresponding queries are optimized for reading and collecting all data required.
Simply map like this (with mapstruct) :
#Mapping(source = "name.value", target = "prodName")
public abstract ProductView toProductView(Product model);
If i have several entites, lets say :
#Entity
class Book{
String name;
Author author;
}
#Entity
class Author{
String name;
City hometown;
}
#Entity
class City{
String cityName;
}
If i want to retrieve all the books, if i use classic JPA Repository and Spring Data and just do a findAll(), it will get me all the books with all the Authors with all their home towns. I know i can use #JsonIgnore, but i think that only prevents whats being returned, not whats being looked up in the database. And also i have methods that DO want to return both books and authors, so #JsonIgnore -ing does not work for me. Is there anything like this ? To tell Spring Data what to look up and what to return ? Any links or guides or methods i don't know of, would be appreciated.
Spring Data has the concept of 'projections' which allow you to return different representations of the same Entity.
Official Documentation:
Spring Data query methods usually return one or multiple instances of
the aggregate root managed by the repository. However, it might
sometimes be desirable to create projections based on certain
attributes of those types. Spring Data allows modeling dedicated
return types, to more selectively retrieve partial views of the
managed aggregates.
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections
Where a Projection is a 'closed' projection (a projection interface whose accessor methods all match properties of the target aggregate) then the documentation notes that additionally:
Spring Data can optimize the query execution [to select only the relevant fields], because we know about
all the attributes that are needed to back the projection proxy
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections.interfaces.closed
Spring Data also allows for Projections to be specified dynamically at runtime. See further:
https://github.com/spring-projects/spring-data-commons/blob/master/src/main/asciidoc/repository-projections.adoc#dynamic-projections
First mark your relations as LAZY
Then specify what data needs to be fetched on a per-query basis.
See for example:
https://vladmihalcea.com/eager-fetching-is-a-code-smell/
I've problem with aggregate which one will increase over time.
One day there will be thousands of records and optimalization gonna be bad.
#Entity
public class Serviceman ... {
#ManyToMany(mappedBy = "servicemanList")
private List<ServiceJob> services = new ArrayList<>();
...
public Optional<ServiceJob> firstServiceJobAfterDate(LocalDateTime dateTime) {
return services.stream().filter(i -> i.getStartDate().isAfter(dateTime))
.min(Comparator.comparing(ServiceJob::getStartDate));
}
}
Method just loading all ServiceJob to get just one of them.
Maybe I should delegate this method into service with native sql.
You have to design small aggregates instead of large ones.
This essay explains in detail how to do it: http://dddcommunity.org/library/vernon_2011/. It explains how to decompose your aggregates to smaller ones so you can manage the complexity.
In your case instead of having an Aggregate consisting of two entities: Serviceman and Servicejob with Serviceman being the aggregate root you can decompose it in two smaller aggregates with single entity. ServiceJob will reference Serviceman by ID and you can use ServicejobRpository to make queries.
In your example you will have ServicejobRpository.firstServiceJobAfterDate(guid servicemanID, DateTime date).
This way if you have a lot of entities and you need to scale, you can store Servicejob entities to another DB Server.
If for some reason Serviceman or Servicejob need references to each other to do their work you can use a Service that will use ServicemanRepository and ServicejobRepository to get both aggregates and pass them to one another so they can do their work.
Getting my feet wet with Grails, so please bear with me...
Just wondering if this is a good use of transient, or if there's a better way.
say I have
class Author {
String name
String favoriteBook
static transients = ["favoriteBook"]
etc.
"Favorite Book" is the title from the Book table of the a book published by the author. I have a database stored procedure (function) that I want to use to do this lookup. I don't want it persisted to the database, just evaluated on the fly when the Author list (and show) is executed. For the list, ideally it is sortable as well.
Note: using Oracle datbase
This obviously is not my real world example, I am actually working on extending a legacy database, and cannot touch that structure....I have a lot of stored procedures that can be utilized. So the question remains...I want my domain class to pull down a value from the database which is the result of a stored procedure.
I find examples on the web of using transients, but not in this way...am I misusing it? How do I utilize stored procedures within g&g and GORM?
I also find example of using stored procedures, like this one
http://www.craigburke.com/post/44771719252/oracle-stored-procs-in-grails
but missing how to implement this in the views...
tia...
K.
Instead of declaring it as a transient I would map it as a formula
class Author {
String name
String favoriteBook
static mapping = {
favoriteBook formula:'find_favorite_book(id)'
}
(or whatever the required SQL is to call your custom function).
Quoting from the linked documentation
Note that the formula expressed in the ORM DSL is SQL so references to other properties should relate to the persistence model not the object model.
i.e. if you need to refer to other properties in the formula then you have to use the database column names (some_property) rather than the property names (someProperty). If you don't want to have to guess the naming convention then you should consider making the property-to-column mapping explicit for any columns you want to use in the formula
static mapping = {
someProperty column:'my_unusual_column'
}
I'm looking at using LINQ to SQL for a new project I'm working on, but I do not want to expose the LINQ classes to my applications. For example, do an select in link returns a System.Linq.IQueryable<> collection. As well, all the classes generated to represent the database use Table, Column, EntityRef classes and attributes. It's fine if my data access layer has LINQ dependancies, but I don't want my application to.
So my thoughts are that I will have to use the LINQ to SQL generated classes as intermediate classes that are not exposed outside of my data access layer, and create my own classes which the application can use. What is the easiest/effecient way to get the data from the LINQ to SQL classes into my own classes?
I totally agree with your thinking - I would try to avoid exposing LINQ to SQL entities directly to the world.
I would definitely recommend using a "domain model" of your own, either a 1:1 mirror of the underlying LINQ to SQL entities, or a different one.
As long as you have a domain model that is quite similar to the underlying LINQ to SQL entities, you can use tools like AutoMapper to easily shuffle data between your LINQ to SQL entities and your domain model classes. It should be pretty easy and flexible to do it that way!
Rob Conery published a webcast series entitled the MVC-Storefront where he introduces a variation of the repository pattern that accomplishes what you want.
I've used ideas from the screencast on a reasonably large project and was quite pleased with the results.
There are, however, issues with the pattern, particularly around concurrency and detached scenarios that you will want to think about up front before fully committing to it.
I detailed some of my pain with concurrency in this pattern here.
I'll be interested in the responses you get because I'm considering the exact same thing. I want to use the L2S entities classes on our backend but use much lighter-weight entities for application consumption.
Randy
I would advise against using LINQ to SQL on a new project, since Microsoft will no longer be developing this project, except for maybe fine-tuning some issues. LINQ to SQL is perfectly usable and is acceptable, but I would not advise new projects to use it. If you like LINQ to SQL, you should definately look into using Entity Framework instead of LINQ to SQL.
This is my current incarnation of how I am going about doing this:
I have a DataContext class that I created by adding a LINQ to SQL class, and droping tables onto the designer. I called the class MyDataContext and put it in a namespace called Linq. My database has a table called Tag, which generated a class, also in the Linq namespace. I changed all the accessors to internal, so they would not be visible outside of the data access layer.
namespace Linq
{
[System.Data.Linq.Mapping.DatabaseAttribute(Name="MyDb")]
internal partial class MyDataContext : System.Data.Linq.DataContext
{
...
}
[Table(Name="dbo.vTag")]
internal partial class Tag
{
....
}
}
I then created a class called DataAccess which is what will be exposed to any application that references the assembly. I also created my own Tag class. The DataAccess class and my new Tag class are in a different namespace called Data to avoid collisions with the generated classes which are in the Linq namespace. I use Linq to Sql to query for an IList of Linq.Tag objects, then I use Linq to generate me a list of Data.Tag objects from the Linq.Tag objects.
I'd like to hear comments on this to see if there's a more performant way to do this, or one that requires less code. I also wasn't too happy with my use of duplicate class names (Tag) so I'm interested to hear any ideas on naming suggestions too.
namespace Data
{
public class DataAaccess
{
public IList<Tag> List_Tags()
{
using (Linq.MyDataContext dal = new Linq.MyDataContext ())
{
IList<Linq.Tag> lstTags = (from c in dal.Tags select c).ToList();
return (from tag in lstTags
select new Data.Tag()
{
ID = tag.ID,
Name = tag.Name,
Parent_ID = tag.Parent_ID
}).ToList();
}
}
}
}
What you are proposing is having two separate models. That means boilerplate code, which I've found is not necessary. I have more or less the same idea as you, but realized that this would be useless. I've suggested Entity Framework in another answer in this thread, and I want to make that point again here.
What you end up with is a model-soup, where you have to maintain two models instead of just the one. And that is definitely NOT desirable.
To go from the LINQ to SQL classes to your classes is a matter of some fairly straightfoward LINQ to Objects (or just initialisation for single objects).
More fun is going back from your model to the LINQ to SQL objects but this is fairly standard stuff (although something I'm still working out or I'd find you some specific references).