Grails one-to-many using natural ID and referenced column name - grails

I have the following entities:
class ProductVariant {
int id
long sku
static hasMany = [prices: ProductPrice]
}
class ProductPrice {
int id
int priceBandId
long sku
BigDecimal price
}
I am trying to achieve a one-to-many relationship between ProductVariant and ProductPrice where the join is on the sku as opposed to the id column.
I have seen an example of how this works in Hibernate using a #NaturalId annotation on the sku column and a referencedColumnName property in the #JoinColumn annotation.
Is is possible to achieve the same thing using Grails/GORM?
The key thing here is that each store has its own set of variants with their own IDs, but the prices are set at a SKU level and would apply across all stores stocking the same SKU.

It turns out that, whilst this is fine at the database level, it's not really something you do. Grails won't let you have a hasMany association on just one part of the primary key.
Instead I am just retrieving all prices by adding a getter to my ProductVariant domain object as follows:
List<ProductPrice> getPrices() {
return ProductPrice.findAll { it.sku == this.sku }
}
and then I can just use productVariant.prices when needed.

Related

Entity framework6 one to one navigation property

How do I map a navigation property when there is no key of its parent in it?
I mean
There is a class Contract.
This is a contract of sale of a product and needs a product to exists. TB_Contract contains ProductId.
The Product exists without a contract and there isn't a ContractId on TB_product.
In some cases the product can be in more than one contract, that's why it has been modeled as a many to one in bd. But in our classes it must be one-to-one
public class Contract
{
...
public Product Product { get; set; }
...
}
public class Product
{
...
public Contract Contract { get; set; }
...
}
table tb_Contract
(
idContract,
idProduct
)
table tb_Product
(
idProduct,
description,
)
I want my class Product have the contract which it's linked to, if there is one.
I'm using code first. How to I map it on EF6?
There's no way to map this as a one-to-one association. It's a one-to-many association by design. So if anything, the design should change to make it one-to-one.
Entity Framework models one-to-one associations by a foreign key that's also a primary key. Any other way to have one-to-one associations is by enforcing them through business logic.
In code, this means that Product has a collection of Orders and a validation rule that checks the number of items in this collection.

Grails Inventory Desgin

I have these domain class:
class Product {
Manufacture manufacture
Model model
Category category
int price
String productCondition
String productDescription
}
class Manufacture {
String manufactureName
static hasMany = [products:Product, models:Model]
}
class Model {
Manufacture manufacture
String modelName
static hasMany = [products:Product]
}
class Category {
String categoryName
static hasMany = [products:Product];
}
I am wondering if I need a Manufacture class, Model class, and Category class or if I can just use a String manufacture, etc.. Is there any advantage to having those additional domain classes than just having String manufacture, etc when it comes to searching? Say I want all products that are manufactured by Ford, or all products that are category car. I am confused on when I should make a domain class vs just using a field.
Thanks
The choice between one solution or the other one depends on how you plan to query the application and adapt it to future changes.
You could use only a Product domain class and with the appropriate database indexes on manufacture, model and category String fields the queries would go fast. But with this approach you can not evolve easily your domain to add new fields to manufacture, model and category.
I always prefer the domain class solution because I don't know how the application is going to evolve.
And intermediate solution can be use embedded domain classes.

single entity for different tables

I have same type of tables
ProductCodeTable, CountrycodeTable etc
All have key, value as their fields
When I use entity frame work,
Can I have a single entity for all these tables such that I can formulate different queries to get data from different tables?
You can create a base class for all of them and create sub class for each entity
public abstract class LookUpEntity
{
[Key]
public int Key { get; set; }
[Required]
public string Value { get; set; }
}
[Table("ProductCodeTable")]
public class ProductCode : LookUpEntity
{
}
This way you can model the relationships also and later if you wanted to add specific properties to those look up entities with out affecting other entities.
You can create a view with a Union of all tables like this:
create view AllKeyTables as
SELECT 'Product' as table, Productkey as Key, nameProduct as name
FROM ProductCodeTable
UNION
SELECT 'Country' as table, CountryISO as key, CountryName as name
FROM CountrycodeTable
UNION
...
Then update EF model and check 'table' and 'key' fields as Entity Primary Key.
Next question you will do is: 'How can I make a relation between this Entity and existing Entities?' The answer is 'you can't because EF is not able to join Entities between other fields than primary key'. Then, before implement this solution, be sure that this is you are looking for.
EF supports this only if you model it as inheritance (#Eranga showed it in code-first approach). You will have single base entity and derived entity for each table so you will not avoid having different type for each table. Otherwise the answer is no.
Inheritance will put additional requirements on data in your tables. For example Ids will have to be unique among all tables. So if ProductTableCode will have record with Id 1, CountryCodeTable (and any other code table) mustn't have record with Id 1.
Also inheritance in EF can produce nasty and very poorly performing queries.

How do I create a composite primary key using GORM?

I have three domain classes: Beer, Review, and Reviewer.
I want the Review table to create a many to many relationship between Beer and Reviewer, so I want the primary key of Review to be a composite of the id fields from Beer and Reviewer. I'm following this Grails documentation.
http://grails.org/doc/latest/guide/5.%20Object%20Relational%20Mapping%20(GORM).html#5.5.2.5%20Composite%20Primary%20Keys
Here are my domain classes.
class Beer {
String name
String type
Brewery breweryId
static hasMany = [ reviews : Review ]
static constraints = {
}
}
class Reviewer {
String screenName
static hasMany = [ reviews : Review ]
static constraints = {
}
}
class Review implements Serializable {
int score
Beer beer
Reviewer reviewer
static constraints = {
}
static mapping = {
id composite:['beer', 'reviewer']
}
}
I was getting compilation errors, but another answer here on stackoverflow said I needed to add implements Serializable. That took care of the error, but when I look in the database, I'm still not getting a composite primary key.
Here is what I'm seeing when I look at the table definition. I'm using Postgres.
Table "public.review"
Column | Type | Modifiers
-------------+---------+-----------
id | bigint | not null
version | bigint | not null
beer_id | bigint | not null
reviewer_id | bigint | not null
score | integer | not null
Indexes:
"review_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
"fkc84ef75823f39326" FOREIGN KEY (beer_id) REFERENCES beer(id)
"fkc84ef7587c483106" FOREIGN KEY (reviewer_id) REFERENCES reviewer(id)
I'd be happy with just a composite index with a unique constraint, but I can't figure out how to do that, either. I've been able to make a non-unique composite index, but this has two problems. One, it's non-unique. Two, the columns are specified in alphabetical order in the index (beer_id, reviewer_id). I'd like to specify the order of the columns in the index.
I have implemented a similar situation, with some different conditions:
There's no hasMany relationship.
Query to the join class is done by HQL
Using a more detailed mapping
When implementing like this, the mysql database is ok. (beer_id,reviewer_id) is the primary key.
class Review implements Serializable {
Beer beer
Reviewer reviewer
static Review get(long beerId, long reviewerId) {
find 'from Review where beer.id=:beerId and reviewer.id=:reviewerId',
[beerId: beerId, reviewerId: reviewerId]
}
static boolean remove(Beer beer, Reviewer reviewer, boolean flush = false) {
Review instance = Review.findByBeerAndReviewer(beer, reviewer)
instance ? instance.delete(flush: flush) : false
}
...
static mapping = {
table "REVIEW"
id composite: ['beer', 'reviewer']
beer(column: "beer_ID")
reviewer(column: "reviewer_ID")
version false
}
}
I don't know what exactly causes your problem, but hope this gives you some hint about where the problem can be.
I took the Grails mandate that I shouldn't use Composite Primary keys as wise advice and am avoiding it. If so, I believe a viable alternative to solve your problem is the Composite Unique Constraint.
ref: http://grails.org/doc/1.1.x/ref/Constraints/unique.html
Jacco's answer seems to be not correct, although it looks visually very close to correct, here is how you'd write a composite unique constraint for this problem:
static constraints = {
beer(unique: 'reviewer')
}
whereas if the programmer wanted to link 3 db fields as unique, the correct formation is:
static constraints = {
beer(unique: ['anotherField','reviewer'])
}
which looks like Jacco's answer, but the class name is not used as the first string of the constraint, the first field name is used.
I've just used this code structure in my own project app, and it seems to be behaving correctly, see also this on how to unit test unique constraints:
http://www.ibm.com/developerworks/java/library/j-grails10209/index.html
(see listing 11)
Try this, In your domain Review domain class:
static constraints = {
review(unique: ['beer','reviewer'])
}
you might need to drop the table and let Gorm recreate it.
the above constraint means that a review must consist of a unique record of beer/reviewer combination. it is still many to many where a reviewer has multiple beers and visa versa but the reviews are unique.

Composite foreign key columns in GORM

I need to customize the column names for composite foreign keys in GORM, and I didn't find any document that shows how to do it. I know how to customize PK columns, and how to customize a single-column FK, but not multi-column FK. Is it possible at all?
Thanks.
A domain class with composite id must implement the Serializable interface.
class Person implements Serializable {
...
}
You need the "id: composite" construct in your object mapping closure.
I have to leave for work, so here it is in brief:
class Person {
String firstName
String lastName
static mapping = {
id composite:['firstName', 'lastName']
}
}
Grails: Object Relational Mapping

Resources