Using NHibernate with lookup tables - database

If you have a set of tables in the database that strictly consist of a string description and an ID, what is the best way to load these via NHibernate?
So suppose I have a Sandwich class, and a sandwich has a meat, a cheese, and a vegetable, where those three things are lookup tables in the DB. It seems to be the most conformant to NHibernate philosophy to have
public class Meat { string name; int id; }
public class Cheese { string name; int id; }
public class Vegetable { string name; int id; }
public class Sandwich { Meat meat; Cheese cheese; Vegetable vegetable; }
But with a few dozen tables like this in the database, classes seem to proliferate quickly. Suppose I set it up like this:
public class NameAndID { string name; int id; }
public class Sandwich { NameAndID meat; NameAndID cheese; NameAndID vegetable; }
Is this feasible? How would it be implemented in Fluent NHibernate?

You'd need another column to determine the type. You could use an enum for that. Then all your lookups need to include that restriction....
CreateCriteria<NameAndID>.Add(Restrictions.Eq("ntype", E.Meat)
However, I'd prefer separate tables so you can have better foreign keys. Otherwise there is nothing in database constraints to stop you from making a sandwich that is simply 3 pieces of cheese.

Related

Overlap in an inheritance

hello i am using spring boot, spring data jpa and postgres. I have the following scenario: I have 3 classes that make up a hierarchy person, student, and teacher, where student and teacher inherit from person.
#Entity
#Table(name = "person")
#Inheritance(strategy = InheritanceType.JOINED)
public class Person {
// Personal Data
#Id
#GeneratedValue(generator = "ID_GENERATOR_POOLED")
protected Long id;
#Column(length = 11, unique = true, nullable = false)
protected String idNumber;
}
#Entity
public class Student extends Person {}
#Entity
public class Teacher extends Person {}
the inheritance strategy is joined.
It is possible for a student to be a teacher. The problem is when inserting a teacher who is already a student or vice versa. Hibernate tries to save and it does so by inserting a new tuple in the person relation, generating repeated data and even an error because the idNumber is unique. How can i fix this? that is to say that if the person already exists, then only insert in the relationship student or teacher as the case may be

JPA, Hibernate : Database Schema

This is my first post, so hi everybody! :)
I have a question regarding a schema of my database. I'm writing RESTful application using Spring. The idea is to allow user to create his own diet based on products stored in DB.
So I came to creating entity Meal, which should consist of Products and amount of those products. It seems like natural way to have something like this is using Map. Problem is, that as I have read there is a problem with mapping such class to JSON Object, which I would like to send to clients browser. My other idea was to store List of objects like ProductWithQuantity instead of such map, but I'm a little worried that DB would be quickly flooded by entries like 1 glass of milk, 2 glasses of milk, 1.1243 glasses of milk and so on.
So my question is - do you have any better idea for the schema for such purpose? ;)
I would define an entity Meal which has a oneToMany relation to an entity Product, this product has properties like 'name', 'amount' and 'unit' and 'price' or something like that. Unit can be "gramm", "liter" and so on.
I might suggest a Meal with many servings, each serving being of a single product. Products like Milk or Hamburg are likely to have nutritional information, while a Meal will have many servings of different products. Serving would essentially be a relational table between Mean and Product, but with additional information like serving size.
#Entity
Class Meal {
#Id
Integer Id;
#OneToMany(mappedBy="meal")
List<Serving> servings;
}
#Entity
Class Serving {
#Id
Integer Id;
#OneToOne
Meal meal;
#OneToOne
Product product;
#Basic
Long servingCount;
}
#Entity
Class Product {
#Id
Integer Id;
#Basic
String simpleName;
#Basic
Integer caloriesPerServing;
..
}

Sales system datamodel (Logical)

I have tried to make a logical data model, but I am not totally sure if it is modeled right. It is a very cut-down and basic model, but overall I want to know if it is modeled the way is should be.
Furthermore, how do I convert this into a class model in object oriented programming?
I guess I need:
Class Customer: int id, string name
Class Order: int id, string date, Customer object
Class Item: int id, string itemName, string item Desc
Class OrderItem: ?
For your data model, you don't need the relationship line between Orders and Items. You're using the junction table Order_Items to represent that many to many relationship.
As for the class models, you won't need a class to model the junction table. You can simply model it with a collection of Item in your Order class. The relationship between the Order and Item class is a composition relationship. You can think of it as: An Order has-a Item or an Order has-s collection of Item.
Here is how you can model the Order class in java.
public class Order {
private int id;
private Date date;
private Customer customer;
private List<Item> items; // you could use other collection types as well.
...
}
Edit:
Also for your many side of the relationships, you may consider using "one through many" line (crows foot with a line)" as opposed to "zero through many" (crows foot with circle). A order generally has atleast 1 item and atleast 1 customer. An order isn't an order without a customer or items.

Database: item can have alternatives, how to link in database?

I have a database where I want to store multiple items, every item would be unique, but they can have alternatives from other makers. So items would have a potential M:M relationship with each other.
For example, item A could have 3 alternatives. If I add item B, the alternative, the link for the alternative item should also be reversed, so that when I search item B, I would find item A as an alternative. When I add item C, it should be added as an alternative for both item A and B, and C should have as it's alternatives item A and B.
How's the best/smartest way to make this relationship between a class of its own kind?
The way I'm thinking is making a table in between called alternatives with a unique ID for each new item, if an alternative is added, then it's linked to that parent ID (alternative ID) and thus no new ID would be made in the alternative table. If it's established only later that this is an alternative, then remove the alternative ID of one of the two and add the item to the other alternative ID.
public partial class Item : Entity
{
public Item()
{
Id = GuidComb.GenerateComb();
}
public Guid Id { get; set; }
public string ItemName { get; set; }
public string MakerRef { get; set; }
public string Description { get; set; }
public virtual Maker Maker { get; set; }
public virtual IList<Offer> Offers { get; set; }
//stuck here on the smart way to make the relationship with itself?
}
Any advice would be welcome!
Thanks in advance!
The suggestion I'm thinking about might be similar to what you proposed, but I'll try to formulate it in database terms.
As far as I understand your requirements, your alternatives relationship will be completely transitive. This means your item set is partitioned in equivalence classes of subsets containing mutually alternative items. (If an item has no alternative yet, the subset consists of this item alone.)
If that's true, then the most elegant and redundancy free way to represent this is to choose one of the items of such as subset as a representative of the entire subset. This is reflected by the following table design:
item(id, equivalence_id, other attributes, ...)
where equivalence_id is a foreign key to the representative. Each item gets born with an equivalence id of null. If it is made equivalent to another item,
if the item already present has an equivalence id of null, assign the id of this representative to the equivalence it of both items,
if the item already present has a non-null equivalence id, assign this to the equivalence id of the new item.
Note that this works, in case there are many items in the same equivalence class, no matter which of this items are used to link the new one.
Example:
id equivalence_id name
1 1 abc
2 def
3 1 ghi
4 4 jkl
5 4 mno
This means abc and ghi are equivalent, as well as jkl and mno, but def isn't yet equivalent to anything. Now if pqr comes along and should become equivalent to abc, it would get equivalence id 1. The effect is the same as making it equivalent to ghi.
To find all items equivalent to a specific one, query
select *
from item
where equivalence_id = :my_equivalence_id
If some information pertaining to the equivalence class as a whole should be stored, a separate table for the equivalence classes only should be created.

NHibernate on a table with two "primary" keys

I'm learning NHibernate in order to layer it over a rather peculiar legacy database. Other applications use the same live database, so I can't make changes that will affect them.
I've run into a problem because one table, which represents hardware devices, has two columns that are used as de facto primary keys. One is the real primary key, an auto-generated row id. The other is a unique and non-null hardware serial number.
Many other tables in the database have a foreign-key relationship with this table. However, some of them use the real primary key - the integer row id - as a foreign key, and some use the hardware id of the device instead.
Note that in practice a hardware ID and row ID, once paired, will remain paired.
Will I be able to create mappings to deal with this in NHibernate, or will I need to create some views to give me a more standardized schema, and use INSTEAD OF triggers to make them updatable?
The DB in use is MSSQL 2000, in case this makes a difference.
In your situation I would do the following:
public class HardwareDevice{
public virtual int Id {get; set;}
public virtual string SerialNumber {get; set;}
//Other stuff
}
public class DomainThingA {
public virtual int Id {get; set;}
public virtual HardwareDevice Device {get; set;}
//Other stuff
}
public class DomainThingB {
public virtual int Id {get; set;}
public virtual HardwareDevice Device {get; set;}
//Other stuff
}
Map out your HardwareDevice class using the AutoGenerated Id as the primary key.
My examples use FluentNhibernate for the class maps.
public class HardwareDeviceMap : ClassMap<HardwareDevice> {
public HardwareDeviceMap(){
Id(x=>x.Id).GeneratedBy.Native().Column("Id"); //Uses auto number
Map(x=>x.SerialNumber).Column("SerialNumber");
//Other mappings
}
}
Now for mapping out the other two classes:
public class DomainThingAMap : ClassMap<DomainThingA> {
public DomainThingAMap(){
Id(x=>x.Id).GeneratedBy.Native(); //Uses auto number
References(x=>x.Device)
.Column("DeviceId"); //Joins on Id in HardwareDevice Table by default
//Other mappings
}
}
public class DomainThingBMap : ClassMap<DomainThingB> {
public DomainThingBMap(){
Id(x=>x.Id).GeneratedBy.Native(); //Uses auto number
References(x=>x.Device)
.Column("SerialNumber") //Column in DomainThingB Table
.PropertyRef("SerialNumber"); //Joins using SerialNumber column (hardware device table)
//Other mappings
}
}
The Property-Ref feature of the class maps allows you to join on columns which are not the primary key for these types of legacy database purposes.

Resources