Thursday, November 19, 2009

Join (association) Table

one-to-many can be mapped with join table as many-to-many (unique="true"), it gives some flexibility that many side doesn't need to have FK to one side, hence they are more loosely coupled. The relation is kept in a separated table. E.g., both Template and Task have one-to-many relationship with DeployWlc. Then we can keep DeployWlc table intact and have separated join tables ce_template_deployWlc, and ce_task_deployWlc.


<class name="Person">
<set name="addresses">
<key column="personId" not-null="true"/>
<one-to-many class="Address"/>
</set>
</class>

<class name="Person">
<set name="addresses" table="PersonAddress">
<key column="personId"/>
<many-to-many column="addressId"
unique="true"
class="Address"/>
</set>
</class>

For many-to-one, we can also have join table, so that on database table, many side doesn't have FK column, but on java object, it has the reference. If both side defines the join table, it creates a bidirectional one-to-many/many-to-one association using a join table.

<many-to-one name="person" class="Person" column="personId"/>


<key column="addressId" unique="true"/>
<many-to-one name="person" class="Person" column="personId"/>


A cascade myth: the CASCADE on collection is not for join(association) table, but for the base table on the other side. The data entries on association table are updated without cascade setting.

The association could be strong or weak. For strong association, define Hibernate cascade "all, delete-orphan" will do it; For weak association, we may run into some issues. For example, the bidirectional association table, the *inverse* side may have FK constraint violation issue. E.g., ApGroup(inverse) <--> Ap, the deletion of ApGroup will fail since it is referenced by association table. It is OK for Ap deletion which is taken care of by Hibernate. So the solution is add database level "on delete cascade" for FK constraint tbl_apGroup_ap -> apGroup.

alter table tbl_apGroup_ap add index FK4F9906CCF1F23ED3 (apGroupId), add constraint FK4F9906CCF1F23ED3 foreign key (apGroupId) references tbl_apGroup (id) on delete cascade;

It means the deletion on parent table (pointed) tbl_apGroup will cascade the deletion on child table tbl_apGroup_ap.

one-to-one is mapped with many-to-one (unique="true") with foreign key association. If using one-to-one, it is using primary key association.

Friday, September 4, 2009

AOP & OOP

OOP inheritance is good for behavior along vertical relationships;
AOP is good for behavior that applies cross horizontal layers (cross-cutting concern)

AOP works with OOP, doesn't replace OOP.

See here.

Tuesday, June 2, 2009

Add Tooltip on disabled button


<div style="position:relative;text-align:right;">
<span id="Configure_overlay" style="z-index:2; position:absolute; background-color:white; opacity:0.60; filter:alpha(opacity=60); width:125px; height:20px; display:none;"></span>
<input type="button" name="Configure" id="configure" value="Configure" onclick="clickMe()"style="font-size: 7pt;width:125px">
</div>

The overlay must be absolute positioned to be placed right on top of the button. Because the default position is static which means overlay will occupy space in document flow. For postion:absolute, the element is removed from the document. The surrounding relative div is required to deal with scroll case. Without it, the overlay is relative to the body and is fixed whereas the button may move in a scrolling area.

function disableCustomConfig(rId, msg) {
var customConfigOverlay = document.getElementById("Configure_overlay");
var customConfigTooltip = new YAHOO.widget.Tooltip("customConfigTooltip", {
context:"Configure_overlay", text:msg, showDelay:0, hideDelay:0, disabled: false
});

customConfigOverlay.style.display = "";
customConfigTooltip.cfg.setProperty("text",msg);
}

Wednesday, May 6, 2009

Javascript Closures

A re-introduction to JavaScript and Simplify Scope with Javascript Closures have a good introduction on the concept of javascript closures. A closure is the combination of a function and the scope object in which it was created. Closures let you save state. The memory of a closure can be freed only when the returned callMe is no longer accessible.

function createClosure(scope_) {
    var origScope = scope_;

    var callMe = function() {   // inner private function
        origScope.somefunc();
    }
    return callMe;    // inner function returned
}

// preserve 'this'
someobject.someproperty = createClosure(this);

function makeAdder(a) {
    return function(b) {
        return a + b;
    }
}

x = makeAdder(5);  // each call to the outer function create a closure
y = makeAdder(20);

x(6)    // return 11, with scope object a=5, 
        // a closure preserves the arguments and variables in all scopes it contains. 
y(7)    // return 27, with scope object a=20

Any nested function forms closure. It doesn't have to be returned, it can be an anonymous inner function as below. We should try to avoid closure whenever possible, it may potentially cause memory leak if there exists circular reference between JS object and DOM object.
function assignOnclick(element) {
   element.onclick = function() {
      this.style.backgroundColor = 'blue';
   };
}

See: Functions and function scope