What I want to do is to create a hierachy of roles a person can have. And do this with Doctrine and Symfony2.
The top of the hierachy would be person. From person there is one subclass called employee and two from this called it_user and telephony_user. Each one of these add a couple of attributes to the baseclass person.
If I understand correctly, with a Single Table Inheritance I would have different rows (one by rol/subclass) for the same person.
I want the same row for the same person, and manage a certain subset of attributes with every class/subclass.
Questions:
Is Single Table Inheritance a good way for doing this? Any tweak?
Or otherwise is better the classic way with a superclass called person with an aggregation of all the attributes of all roles?
It is better any other way?
Thank you in advance.
If you plan to set different attributes according to person type, then you should use Class Table Inheritance. This inheritance lets you make the following:
Superclass:
Person
- name
- gender
Subclass 1:
Employ extends Person
- manager
- projects
Subclass 2:
TelephonyUser extends Person
- schedule
- foo
- bar
By this way, every model (subclasses) is mapped to its table. See how each subclass have custom attributes from each other and sharing parent attributes at the same time.
Single Table Inheritance (STI) and Aggregation
Take a look at following db schema:
-- Uploads table
id | name | size | type | filename
------------------------------------------
1 | upload1 | 43423 | image | foo.gif
2 | upload2 | 64234 | file | hack.txt
3 | upload3 | 76646 | image | bar.gif
File and Image are two subclasses of Upload class according to type column. As you see, both of them have the same attributes with taking care of subclass type. Why? because this Inheritance is wise based in behavior model instead of structure. For example, you can manage the attribute data differently for each class:
// In file class the content as text should be showen
class File extends Uploads{
// show the file content
public function show(){
echo file_get_contents( $this->filename );
}
}
// In Image class the image should be showen
class File extends Uploads{
// show the file content
public function show(){
echo "<img src='{ $this->filename }' alt='' />";
}
}
See how every class having the same attributes they manage them different from each other. But the most relevant here is that all data will be stored in a unique table. So, what you need to do is to model your db squema in order to apply the appropiate Inheritance.
Related
Is there a way to partially insert an object using PetaPoco or NPoco?
For example, I have a table called Users:
UserId | UserName | UserMail | UserCreationDate
Each one of these columns are NON NULLABLE and have a default value when they are left empty.
In ASP.NET I have a User class, and I use the ORM to insert a new record with only the name:
Dim userData As New User()
userData.UserName = "Jimmy Hendrix"
db.Insert(userData)
I expect the database to look as follows:
UserId | UserName | UserMail | UserCreationDate
12 | Jimmy Hendrix | (DB default)| (DB default)
I want the insert command only insert the name, without inserting the other object properties with the object's default values.
Such as there is a partial update, I want a partial insert.
Is that possible in PetaPoco?
Is there another way to do it by myself without any ORM?
Edit:
Using SQL I can get the job done, but I need to use POCO objects, so I don't want to have to remember the database parameters. I want something like
user.UserName = "Michael"
user.Insert(user)
And it will insert only the UserName, ignoring the other variables. The SQL that I want to be generated in the background is:
"INSERT Users(UserName) VALUES(#UserName)"
(while the #UserName parameter holds the userData.FirstName value)
As you can see, it doesn't take in account the other variables in the class.
Today if I use the insert command, even if I give a value to a single property in the class, NPoco still tries to insert ALL the class variables into the db setting the variables I didn't want to set with the class's default values (which are different from the db default values)
Also, all of the properties are insertable/updateable, so there can't be any ResultColumn types in the class. I want to insert these values but only the ones I declare in that particular instance. All of the properties are available to update and insert but for each instance i insert only what i declare.
I would create a PartialUserForInsert class:
[TableName("Users")]
public class PartialUserForInsert
{
public string UserName { get; set; }
}
Your provided schema does not include a FirstName column.
Assuming the column is mapped to UserName, using the following should insert as expected.
dim sql = new Sql("INSERT Users(UserName) VALUES(#0)", userData.FirstName)
db.Execute(sql)
I have an ArrayCollection of objects used as the source for a HierarchicalData object. My object looks roughly like this:
ObjectName (String)
SubCollection (ArrayCollection)
I am using the HierarchicalData in an AdvancedDataGrid to display the data in a grouped format.
I am able to filter the data in the ArrayCollection using a filterFunction. What I want to do now is also filter the records in the SubCollection as well so that only the items that match the filter are displayed in the AdvancedDataGrid.
Can anyone tell me how I can filter the child rows in a HierarchicalData?
This answer isn't a direct answer to your question, but it should help with some of the background. Essentially I am in the same position as you, where I need to show a specific data set depending on what type of parent node I have.
In this case, starting with an override to HierarchicalData.getChildren(node:Object):Object this will give you access to filter the first level children, and will also give you the ability to call a filtered method for sub-children to any n-th level.
You then use your extended class as the source to the ADG.
A pseudo-code example:
Class MyCollection extends HierarchicalData
override public function getChildren(node:Object):Object
{
if (node is a TopLevelObject)
(node.children as ArrayCollection).filterFunction = filterSub;
node.children.refresh();
else if (node is a SubCollectionObject)
(node.children as ArrayCollection).filterFunction = filterGrandChildren;
node.children.refresh();
// - OR -
//a more complex process of allowing the sub-node to determine it's filter
return node.filterSubCollectionGrandChildren();
return node;
}
I have three tables for different payment types, and want to create a table that holds payments made using all three. I'm not sure if I'm going about this the right way, but I was going to create a foreign key column in the table for each of the three, and the write a constraint such that exactly one of those columns has to be not null.
Is this the right way to go about this?
How do you go about writing this constraint?
Is there any way to do this from within SQLAlchemy on sqlite? (code for declarative classes would be much appreciated)
Have a single foreign key column, and a separate type column so you know which table to look in.
Ok I've got it - Is this the best way to do it? - I created a generic id field table as such:
class PaymentDetails(Base):
__tablename__ = 'payment_details'
id = Column(Integer, primary_key=True)
type = Column(PaymentType.db_type(), nullable=False)
where PaymentType uses the declarative enum recipe and and then subclassed this for the various payment methods:
#concrete
#do_unique_index('paypal_unique_details', 'env', 'main_email', 'sub_email')
class Paypal(Base):
__tablename__ = 'paypal_details'
id = Column(ForeignKey('payment_details.id'), primary_key=True)
# The rest of the implementation
#
#concrete
#do_unique_index('credit_card_unique_details', 'env', 'card_number')
class CreditCard(Base):
__tablename__ = 'card_details'
id = Column(ForeignKey('payment_details.id'), primary_key=True)
# The rest of the implementation
#
#concrete
#do_unique_index('time_code_unique_details', 'env', 'code')
class TimeCodes(Base):
__tablename__ = 'code_details'
id = Column(ForeignKey('payment_details.id'), primary_key=True)
# The rest of the implementation
#
(Where concrete and do_unique_index set the relevant __mapper_args__ and __table_args__). I then set the description field of the PaymentType enum values to be each of these classes, so that to look up a payment I can query for a PaymentDetails object, then get an id and a type from that, say id and Paypal, to perform a second query for the Paypal with that id.
My code for adding sets of details is fairly simple in that in a single transaction, it adds the next logical id to the PaymentDetails table with the type of the payment details we are trying to create, and then adds an entry to that table with the details I want to enter. I can then add methods to these ORM classes to handle the different ways that we would handle buying, selling, and refunding for each method, such that they can be treated as identical.
You then need to switch on FK constraints as van mentioned - I did so by adding the FK listener to the helper class I use for DB access.
I am using NHibernate (version 1.2.1) for the first time so I wrote a simple test application (an ASP.NET project) that uses it. In my database I have two tables: Persons and Categories. Each person gets one category, seems easy enough.
| Persons | | Categories |
|--------------| |--------------|
| Id (PK) | | Id (PK) |
| Firstname | | CategoryName |
| Lastname | | CreatedTime |
| CategoryId | | UpdatedTime |
| CreatedTime | | Deleted |
| UpdatedTime |
| Deleted |
The Id, CreatedTime, UpdatedTime and Deleted attributes are a convention I use in all my tables, so I have tried to bring this fact into an additional abstraction layer. I have a project DatabaseFramework which has three important classes:
Entity: an abstract class that defines these four properties. All 'entity objects' (in this case Person and Category) must inherit Entity.
IEntityManager: a generic interface (type parameter as Entity) that defines methods like Load, Insert, Update, etc.
NHibernateEntityManager: an implementation of this interface using NHibernate to do the loading, saving, etc.
Now, the Person and Category classes are straightforward, they just define the attributes of the tables of course (keeping in mind that four of them are in the base Entity class).
Since the Persons table is related to the Categories table via the CategoryId attribute, the Person class has a Category property that holds the related category. However, in my webpage, I will also need the name of this category (CategoryName), for databinding purposes for example. So I created an additional property CategoryName that returns the CategoryName property of the current Category property, or an empty string if the Category is null:
Namespace Database
Public Class Person
Inherits DatabaseFramework.Entity
Public Overridable Property Firstname As String
Public Overridable Property Lastname As String
Public Overridable Property Category As Category
Public Overridable ReadOnly Property CategoryName As String
Get
Return If(Me.Category Is Nothing, _
String.Empty, _
Me.Category.CategoryName)
End Get
End Property
End Class
End Namespace
I am mapping the Person class using this mapping file. The many-to-one relation was suggested by Yads in another thread:
<id name="Id" column="Id" type="int" unsaved-value="0">
<generator class="identity" />
</id>
<property name="CreatedTime" type="DateTime" not-null="true" />
<property name="UpdatedTime" type="DateTime" not-null="true" />
<property name="Deleted" type="Boolean" not-null="true" />
<property name="Firstname" type="String" />
<property name="Lastname" type="String" />
<many-to-one name="Category" column="CategoryId" class="NHibernateWebTest.Database.Category, NHibernateWebTest" />
(I can't get it to show the root node, this forum hides it, I don't know how to escape the html-like tags...)
The final important detail is the Load method of the NHibernateEntityManager implementation. (This is in C# as it's in a different project, sorry about that).
I simply open a new ISession (ISessionFactory.OpenSession) in the GetSession method and then use that to fill an EntityCollection(Of TEntity) which is just a collection inheriting System.Collections.ObjectModel.Collection(Of T).
public virtual EntityCollection< TEntity > Load()
{
using (ISession session = this.GetSession())
{
var entities = session
.CreateCriteria(typeof (TEntity))
.Add(Expression.Eq("Deleted", false))
.List< TEntity >();
return new EntityCollection< TEntity >(entities);
}
}
(Again, I can't get it to format the code correctly, it hides the generic type parameters, probably because it reads the angled symbols as a HTML tag..? If you know how to let me do that, let me know!)
Now, the idea of this Load method is that I get a fully functional collection of Persons, all their properties set to the correct values (including the Category property, and thus, the CategoryName property should return the correct name).
However, it seems that is not the case. When I try to data-bind the result of this Load method to a GridView in ASP.NET, it tells me this:
Property accessor 'CategoryName' on object 'NHibernateWebTest.Database.Person' threw the following exception:'Could not initialize proxy - the owning Session was closed.'
The exception occurs on the DataBind method call here:
public virtual void LoadGrid()
{
if (this.Grid == null) return;
this.Grid.DataSource = this.Manager.Load();
this.Grid.DataBind();
}
Well, of course the session is closed, I closed it via the using block. Isn't that the correct approach, should I keep the session open? And for how long? Can I close it after the DataBind method has been run?
In each case, I'd really like my Load method to just return a functional collection of items. It seems to me that it is now only getting the Category when it is required (eg, when the GridView wants to read the CategoryName, which wants to read the Category property), but at that time the session is closed. Is that reasoning correct?
How do I stop this behavior? Or shouldn't I? And what should I do otherwise?
Thanks!
Setting lazy loading = false in your mapping will solve the error. It would be a better practice though to tell NHibernate in your load query that you want to fetch the child collection of categories eagerly.
For a criteia query something like .SetFetchMode("Categories", FetchMode.Eager) should work.
Here is a link that gives some insight into the so called "n + 1" problem, how lazy loading relates to it, and how NHibernate is meant to be used.
HTH,
Berryl
something like this:
var entities = session
.CreateCriteria<TEntity>()
.SetFetchMode("Categories", FetchMode.Eager)
.Add(Expression.Eq("Deleted", false))
.List< TEntity >();
The problem is that when your entity is lazy loaded. The query only gets the items that it currently needs. So in your case it gets the Person object. Then when you access any linked entities, it fires off another query. It uses proxy objects for this that know about the Session that was used. You are only keeping the Session open for the Load and then you're closing it.
This is actually bad practice in the NHibernate world. You want to keep the session alive for a period known as a unit of work. This gives you a lot of benefits, like caching and lazy loading. Consequently you can disable lazy loading it should work. Although I'd recommend modifying your loader class if at all possiblem
Is there a way to bind data to a list and/or a table using the groovy swing builder bind syntax? I could only find simple examples that bind simple properties like strings and numbers to a text field, label, or button text.
Had a look round, and the best I could see was using GlazedLists rather than standard Swing lists
http://www.jroller.com/aalmiray/entry/glazedlists_groovy_not_your_regular
There is a GlazedList plugin. And this article is very helpful. The Griffon guys swear by GlazedLists.
I just did something like this--it's really not that hard to do manually. It's still a work in progress, but if it helps anyone I can give what I have. So far it binds the data in both directions (Updating the data updates the component, editing the table updates the data and sends a notification to any propertyChangeListeners of the "Row")
I used a class to define one row of a table. You create this class to define the nature of your table. It looks something like this:
class Row
{
// allows the table to listen for changes and user code to see when the table is edited
#Bindable
// The name at the top of the column
#PropName("Col 1")
String c1
#Bindable
// In the annotation I set the default editable to "false", here I'll make c2 editable.
// This annotation can (and should) be expanded to define more column properties.
#PropName(value="Col 2", editable=true)
String c2
}
Note that once the rest of the code is packaged up in a class, this "Row" class is the ONLY thing that needs to be created to create a new table. You create instances of this class for each row, add them to the table and you are completely done--no other gui work aside from getting the table into a frame.
This class could include quite a bit more code--I intend to have it contain a thread that polls a database and updates the bound properties, then the table should pick up the changes instantly.
In order to provide custom column properties I defined an annotation that looks like this (I plan to add more):
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.FIELD)
public #interface PropName {
String value();
boolean editable() default false
}
The rest is a class that builds the table. I keep it in a separate class so it can be reused (by instantiating it with a different "Row" class)
NOTE: I butchered this as I pasted it in so it may not run without a little work (braces probably). It used to include a frame which I removed to just include the table. You need to wrap the table returned from getTable() in a frame..
public class AutoTable<T>
{
SwingBuilder builder // This way external code can access the table
def values=[] // holds the "Row" objects
PropertyChangeListener listener={repaint()} as PropertyChangeListener
def AutoTable(Class<T> clazz)
{
builder = new SwingBuilder()
builder.build{
table(id:'table') {
tableModel(id:'tableModel') {
clazz.declaredFields.findAll{
it.declaredAnnotations*.annotationType().contains(PropName.class)}.each {
def annotation=it.declaredAnnotations.find{it.annotationType()==PropName.class
}
String n=annotation.value()
propertyColumn(header:n, propertyName:it.name, editable:annotation.editable())
}
}
tableModel.rowsModel.value=values
}
}
// Use this to get the table so it can be inserted into a container
def getTable() {
return builder.table
}
def add(T o) {
values.add(o)
o.addPropertyChangeListener(listener)
}
def remove(T o) {
o.removePropertyChangeListener(listener)
values.remove(o)
}
def repaint() {
builder.doLater{
builder.table.repaint();
}
}
}
There is probably a way to do this without the add/remove by exposing a bindable list but it seemed like more work without a lot of benifit.
At some point I'll probably put the finished class up somewhere--if you have read this far and are still interested, reply in a comment and I'll be sure to do it sooner rather than later.