Tuesday, December 31, 2013

Google Map API in Sencha Touch

View:

Ext.define('MyApp.view.MyPanel', {
extend: 'Ext.Panel',

config: {
layout: {
type: 'hbox'
},
items: [
{
xtype: 'list',
itemId: 'list',
width: '200px',
itemTpl: [
'

{name}

'
],
store: 'MyJsonStore'
},
{
xtype: 'map',
flex: 1,
itemId: 'googleMap',
width: 300,
mapOptions: {
disableDefaultUI: true,
zoom: 17,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
}
],
listeners: [
{
fn: 'onListSelect',
event: 'select',
delegate: '#list'
}
]
},

onListSelect: function(dataview, record, eOpts) {
var me = this;
var googleMap = me.down('#googleMap');
console.log('name = '+ record.get('name')+' ; address = '+ record.get('address'));
if (record){
var address = record.get('address');
// Geodecode
var geocoder = new window.google.maps.Geocoder();
var map = googleMap;
geocoder.geocode({ 'address': address }, function (results, status) {
if (status == window.google.maps.GeocoderStatus.OK) {
setTimeout(function () {
map.getMap().setCenter(new google.maps.LatLng(results[0].geometry.location.lat(), results[0].geometry.location.lng()));
var marker = new google.maps.Marker({
map: map.getMap(),
position: results[0].geometry.location
});
//map.markersArray.push(marker);
var infowindow = new google.maps.InfoWindow({
content: address,
maxWidth: 120
});
infowindow.open(map.getMap(), marker);
}, 500);
} else {
console.log('Geocode was not successful for the following reason: ' + status);
}
});

}

}

});

Store

Ext.define('MyApp.store.UniversityStore', {
extend: 'Ext.data.Store',

requires: [
'MyApp.model.University'
],

config: {
autoLoad: true,
autoSync: true,
model: 'MyApp.model.University',
storeId: 'MyJsonStore',
proxy: {
type: 'ajax',
url: 'university.json',
reader: {
type: 'json'
}
}
}
});

Model:

Ext.define('MyApp.model.University', {
extend: 'Ext.data.Model',

config: {
fields: [
{
name: 'name'
},
{
name: 'address'
}
]
}
});

Data:

[
{
"name":"New York University",
"address":"70 Washington Square S New York, NY 10012"
}
,
{
"name":"University of Zurich",
"address":"Rämistrasse 71 8006 Zürich Switzerland"
},
{
"name":"Yale University",
"address":"New Haven, CT 06520"
},
{
"name":"Hanoi University of Science and Technology",
"address":"Số 1 Đại Cồ Việt Bách Khoa, Hai Bà Trưng Hà Nội, Vietnam"
},
{
"name":"Trường Đại Học Bách Khoa Đà Nẵng",
"address":"54 Nguyễn Lương Bằng Hòa Khánh Bắc, Liên Chiểu Đà Nẵng, Vietnam"
},
{
"name":"Trường Đại học Bách khoa tp Hồ Chí Minh",
"address":"268 Lý Thường Kiệt phường 14, Quận 10 Hồ Chí Minh, Vietnam"
}
]

Add listener when click

var me = this;
var googleMap = me.down('#googleMap');
console.log('name = '+ record.get('name')+' ; address = '+ record.get('address'));
if (record){
var address = record.get('address');
// Geodecode
var geocoder = new window.google.maps.Geocoder();
var map = googleMap;
geocoder.geocode({ 'address': address }, function (results, status) {
if (status == window.google.maps.GeocoderStatus.OK) {
setTimeout(function () {
map.getMap().setCenter(new google.maps.LatLng(results[0].geometry.location.lat(), results[0].geometry.location.lng()));
var marker = new google.maps.Marker({
map: map.getMap(),
position: results[0].geometry.location
});
//map.markersArray.push(marker);

var infowindow = new google.maps.InfoWindow({
content: address,
maxWidth: 120
});
google.maps.event.addListener(marker, 'click', (function(marker) {
return function() {
infowindow.open(map.getMap(), marker);
}
})(marker));

}, 500);
} else {
console.log('Geocode was not successful for the following reason: ' + status);
}
});

}

Saturday, December 28, 2013

Increase and Decrease height and width of panel.

Ext.define('MyApp.view.MyPanel', {
extend: 'Ext.Panel',

config: {
layout: {
type: 'hbox'
},
items: [
{
xtype: 'toolbar',
docked: 'top',
items: [
{
xtype: 'button',
docked: 'left',
itemId: 'increase',
text: 'Increase'
},
{
xtype: 'button',
docked: 'right',
itemId: 'decrease',
text: 'Decrease'
}
]
},
{
xtype: 'panel',
flex: 1,
height: 500,
itemId: 'container',
style: 'background-color: #A200FF',
width: 500,
scrollable: 'horizontal'
}
],
listeners: [
{
fn: 'onIncreaseButtonTap',
event: 'tap',
delegate: '#increase'
},
{
fn: 'onDecreaseButtonTap',
event: 'tap',
delegate: '#decrease'
}
]
},

onIncreaseButtonTap: function(button, e, eOpts) {
console.log('on click decrease button');
var container = this.down('#container');
var widthString = container.getWidth();
var heightString = container.getHeight();
var w = parseInt(widthString.substr(0,widthString.indexOf('px')),10);
var h = parseInt(heightString.substr(0,heightString.indexOf('px')),10);

console.log('width : '+ w +' height : '+ h);
container.setHeight((h+10).toString()+'px');
container.setWidth((w+10).toString()+'px');

},

onDecreaseButtonTap: function(button, e, eOpts) {
console.log('on click decrease button');
var container = this.down('#container');
var widthString = container.getWidth();
var heightString = container.getHeight();
var w = parseInt(widthString.substr(0,widthString.indexOf('px')),10);
var h = parseInt(heightString.substr(0,heightString.indexOf('px')),10);

console.log('width : '+ w +' height : '+ h);
container.setHeight((h-10).toString()+'px');
container.setWidth((w-10).toString()+'px');

}

});

Tuesday, November 5, 2013

Java Enum Example

Here is an example of Enum in Java
public class EnumExample {
    public static void main(String []args){
        
        System.out.println(SearchCriteriaComparisonExpression.equal);
        System.out.println(SearchCriteriaComparisonExpression.equal.sqlExpression());
        
        for(SearchCriteriaComparisonExpression value: SearchCriteriaComparisonExpression.values()){
            System.out.println(value.name()+" | "+value);
            
        }
        System.out.println();
    }

    
}
enum SearchCriteriaComparisonExpression {

    /**
     *
     */    
    equal("equal") , // equal (=)    
    notequal("notequal"), // Not equal (<>)
    greaterthan("gt"), // Greater Than (>)
    greaterthanorequal("ge"), // Greater Than or equal (>=)
    lessthan("lt"), // // Less Than (<)
    lessthanorequal("le"), // Less Than or equal (<=)       
    isnull("isnull"), // IS NULL
    isnotnull("isnotnull"); // IS NOT NULL
    
    private String expression;
   
    private SearchCriteriaComparisonExpression(String expression) {
        this.expression = expression;       
    }
       
    @Override
    public String toString() {        
        return this.expression.toLowerCase();
    }

    public String sqlExpression() {
        String value = "";
        if (this.compareTo(equal) == 0) {
            value = "=";
        } else if (this.compareTo(notequal) == 0) {
            value = "<>";
        } else if (this.compareTo(greaterthan) == 0) {
            value = ">";
        } else if (this.compareTo(greaterthanorequal) == 0) {
            value = ">=";
        } else if (this.compareTo(lessthan) == 0) {
            value = "<";
        } else if (this.compareTo(lessthanorequal) == 0) {
            value = "<=";
        } else if (this.compareTo(isnull) == 0) {
            value = "IS NULL";
        } else if (this.compareTo(isnotnull) == 0) {
            value = "IS NOT NULL";
        } 
        return value;
    }
}

Tuesday, October 29, 2013

SMALL SPACE BETWEEN DIV TAGS

When we have some h1, h2, h3, p ... in div tag:


 <html>  
<head>
<title> Hello World</title>
<style>
body {
background-color: #cc00ff;
margin: 0px;
}
#wrap {
background-color: #999999;
width: 380px;
height: 380px;
margin: 10px;
}
#hd {
background-color: #FFCCCC;
width: 380px;
height: 60px;
}
#bd {
background-color: #FFFFCC;
width: 380px;
height: 270px;
}
#bt {
background-color: #FF5432;
width: 380px;
height: 50px;
}
#bt h1 {
margin-top: 2px;
}
</style>
</head>
<body>
<div id="wrap">
<div id="hd">
<h1>Header</h1>
</div>
<div id="bd">
<h1>Body</h1>
</div>
<div id="bt">
<h1>Bottom</h1>
</div>
</div>
</body>
</html>

The result is unexpected :

Because :
h1,h2,h3,p,span,iframe,a,body,html and possibly a many others will always have default paddings and margins which vary between element and browser types. I've been caught out a few times myself. With divs, to my knowledge they don't have default paddings and margins BUT the elements stated above can effect the positioning of other elements. Not really sure why to be honest lol might be something to do with the structure and z-index of each elements but don't hold me to that. 
This answer from StackOverFlow.

And just add :



 h1{
margin: 0px;
}
Problem gone!

Saturday, August 24, 2013

Dependency Injection

If you have a class Employee and this employee has an Address you can have the Employee class defined as follows:
class Employee {
private Address address;

// constructor
public Employee( Address newAddress ) {
this.address = newAddress;
}

public Address getAddress() {
return this.address;
}
public void setAddress( Address newAddress ) {
this.address = newAddress;
}
}
Everything looks fine so far.
This code shows a HAS-A relationship between the employee and his address, that's fine.
Now, this HAS-A relationship created a dependency between them. The problem comes within the constructor.
Each time you want to create an Employee instance you need an Address instance:
 Address someAddress = ....
Employee oscar = new Employee( someAddress );
Working this way becomes problematic especially when you want to perform unit testing.
The main problem comes when you need to test one particular object, you need to create an instance of other object, and most likely you need to create an instance of yet other object to do that. The chain may become unmanageable.
To avoid this, you could change the constructor like this:
  public Employee(){
}
Using a no args constructor.
Then you can set the address when ever you want:
 Address someAddress = ....
Employee oscar = new Employee();
oscar.setAddress( someAddress );
Now, this may be a drag, if you have several attributes or if the objects are hard to create.
Yet, think about this, let's say, you add the Department attribute:
  class Employee {
private Address address;
private Department department;

....
If you have 300 employees, and all of them need to have the same department, and plus that same department has to be shared between some other objects ( like the company list of departments, or the roles each department have etc ) then you'll have a hard time with the visibility of the Departmentobject and to share it through all the network of objects.
What the Dependency Injection is all about it to help you to, well, "inject" these dependencies in your code. Most of the frameworks allow you to do this by specifying in an external file, what object is to be injected.
Assume a properties file for a fictitious dependency injector:
  #mock employee
employee.address = MockAddress.class
employee.department = MockDepartment.class

#production setup
employee.address = RealAddress.class
employee.department = RealDepartment.class
You'll define what to inject for a given scenario.
What the Dependency Injector framework will do is to set the correct objects for you, so you don't have to code setAddress or setDepartment. This would be done either by reflection or by code generation or other techniques.
So, the next time you need to test the Employee class you may inject mock Address andDepartments objects without having to code all the set/get for all your test. Even better, you can injectreal Address and Department objects in production code, and still have the confidence your code works as tested.
That's pretty much about it.
Still I don't think this explanation is suitable for a 5 yr old as you requested.
I hope you still find it useful.
Another explain:
I give you dependency injection for five year olds.
When you go and get things out of the refrigerator for yourself, you can cause problems. You might leave the door open, you might get something Mommy or Daddy doesn't want you to have. You might even be looking for something we don't even have or which has expired.
What you should be doing is stating a need, "I need something to drink with lunch," and then we will make sure you have something when you sit down to eat.
References: Link

Monday, August 12, 2013

Insert hight light code

<pre class="brush: csharp">// Comment
public class Testing {
public Testing() {
}
 
public void Method() {
/* Another Comment
on multiple lines */
int x = 9;
}
}
</pre>


Becomes :
 // Comment
public class Testing {
public Testing() {
}

public void Method() {
/* Another Comment
on multiple lines */
int x = 9;
}
}

Sunday, August 11, 2013

Validation in hibernate objects


import java.util.Date;

import javax.persistence.AttributeOverride;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinColumns;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;

import org.hibernate.annotations.AccessType;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.Type;
import org.hibernate.validator.AssertTrue;
import org.hibernate.validator.Min;
import org.hibernate.validator.NotNull;
import org.hibernate.validator.Valid;

import com.security.access.audit.HistoricallyAuditable;
import com.security.access.audit.NotAudited;
import com.security.access.audit.HistoricallyAuditable.AuditScope;
import com.security.facade.OrganizationContextProviderFactory;
import com.security.model.DuplicableObject;
import com.security.model.STCodeIntExtObject;
import com.security.model.StateEnum;
import com.security.model.StateEnumNotCanceledTransitionHandler;
import com.security.model.StateObject;
import com.security.model.aspect.AssociationId;
import com.security.model.aspect.AssociationObject;
import com.security.model.catalog.ProductFamily;
import com.security.model.type.MLExternalName;
import com.security.model.type.MLInternalName;
import com.security.util.helper.DateHelper;

@Entity
@AttributeOverride(name = "pk.id", column = @Column(name = "activity_id", nullable = false, insertable = false,
  updatable = false))
@HistoricallyAuditable(parentEntityRef = "season",
  validationGroup = OrganizationParameters.VALIDATION_GROUP_SEASON_PARAM, auditScope = { AuditScope.SEASON })
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Activity extends STCodeIntExtObject implements StateObject, DuplicableObject {

 private Integer seasonId;
 private Season season;

 private Integer productFamilyId;
 private ProductFamily productFamily;

 private StateEnum state = StateEnum.PREPARING;

 private ActivityTypeEnum type;

 private Date startDate = DateHelper.pastInfinite();
 private Date endDate = DateHelper.futureInfinite();
 private Date sellingStartDate = DateHelper.pastInfinite();

 private Integer maxDelayBetweenReservationAndConfirmation;
 private Integer reservationConfirmationMaxDelayBeforePerformance;

 private boolean seatOptionsAllowed = false;
 private OptionParameter optionParameter;
 private Integer optionParameterId;

 private Boolean outsideSeasonTicketAllowed;

 private Boolean unclosed = false;
 private String optionParameterInstitCode;

 private final StateEnumNotCanceledTransitionHandler transitionHandler =
   new StateEnumNotCanceledTransitionHandler(this);


 private Integer optionParamId;

 @Transient
 public Integer getOptionParamId() {
  return optionParamId;
 }

 @Transient
 public void setOptionParamId(Integer opId) {
  optionParamId = opId;
 }

 public Activity() {
 }

 public Activity(Activity original) {

 }
 
 public Activity duplicate() {
  Activity copy = new Activity();
  return copy;
 }
 
 @Temporal(TemporalType.DATE)
 @NotNull
 public Date getEndDate() {
  return endDate;
 }

 public void setEndDate(Date endDate) {
  this.endDate = endDate;
 }


 @AssertTrue
 public boolean validateEndDateEqualOrAfterStartDate() {
  return DateHelper.dateBeforeOrEqual(getStartDate(), getEndDate());
 }

 @AssertTrue
 public boolean validateStartDateVsSeason() {
  return DateHelper.dateBeforeOrEqual(getSeason().getStartDate(), getStartDate());
 }

 @AssertTrue
 public boolean validateSellingStartDateVsSeason() {
  return DateHelper.dateBeforeOrEqual(getSeason().getSellingStartDate(), getSellingStartDate());
 }

 @AssertTrue
 public boolean validateEndDateVsSeason() {
  return DateHelper.dateBeforeOrEqual(getEndDate(), getSeason().getEndDate());
 }

 @Column(name = "optionparam_instit_code")
 @NotAudited
 public String getOptionParameterInstitCode() {
  if (null == optionParameterInstitCode) {
   OptionParameter op = getOptionParameter();
   if (null != op) {
    setOptionParameterInstitCode(op.getPk().getInstitutionCode());
   }

  }
  return optionParameterInstitCode;
 }

 public void setOptionParameterInstitCode(String optionParameterInstitCode) {
  this.optionParameterInstitCode = optionParameterInstitCode;
 }

 @Column(name = "MAX_DELAY_BW_RESERVAT_CONFIRM")
 @Min(0)
 public Integer getMaxDelayBetweenReservationAndConfirmation() {
  return maxDelayBetweenReservationAndConfirmation;
 }

 public void setMaxDelayBetweenReservationAndConfirmation(Integer maxDelayBetweenReservationAndConfirmation) {
  this.maxDelayBetweenReservationAndConfirmation = maxDelayBetweenReservationAndConfirmation;
 }

 @Column(name = "RESERVAT_MAX_DELAY_B4_PERFORM")
 @Min(0)
 public Integer getReservationConfirmationMaxDelayBeforePerformance() {
  return reservationConfirmationMaxDelayBeforePerformance;
 }

 public void setReservationConfirmationMaxDelayBeforePerformance(
   Integer reservationConfirmationMaxDelayBeforePerformance) {
  this.reservationConfirmationMaxDelayBeforePerformance = reservationConfirmationMaxDelayBeforePerformance;
 }

 @NotNull
 @Type(type = "true_false")
 public boolean isSeatOptionsAllowed() {
  return seatOptionsAllowed;
 }

 public void setSeatOptionsAllowed(boolean seatOptionsAllowed) {
  this.seatOptionsAllowed = seatOptionsAllowed;
 }

 @NotNull
 @Temporal(TemporalType.DATE)
 public Date getSellingStartDate() {
  return sellingStartDate;
 }

 public void setSellingStartDate(Date sellingStartDate) {
  this.sellingStartDate = sellingStartDate;
 }

 @Temporal(TemporalType.DATE)
 @NotNull
 public Date getStartDate() {
  return startDate;
 }

 public void setStartDate(Date startDate) {
  this.startDate = startDate;
 }

 @NotNull
 @Enumerated(EnumType.STRING)
 @AccessType(value = "field")
 public StateEnum getState() {
  return state;
 }

 public void setState(StateEnum state) {
  this.state = transitionHandler.changeState(this.state, state);
 }

 @NotNull
 @Enumerated(EnumType.STRING)
 public ActivityTypeEnum getType() {
  return type;
 }

 public void setType(ActivityTypeEnum type) {
  this.type = type;
 }

 @NotNull
 @Type(type = "true_false")
 public Boolean isUnclosed() {
  return unclosed;
 }

 public void setUnclosed(Boolean unclosed) {
  this.unclosed = unclosed;
 }

 @ManyToOne(fetch = FetchType.LAZY, optional = false)
 @JoinColumns({
   @JoinColumn(name = "season_id", referencedColumnName = "season_id", insertable = false, updatable = false),
   @JoinColumn(name = "instit_code", referencedColumnName = "instit_code", insertable = false,
     updatable = false) })
 public Season getSeason() {
  return season;
 }

 @AssociationObject
 public void setSeason(Season season) {
  this.season = season;
 }

 // Parent
 @AccessType(value = "field")
 @Column(name = "season_id", updatable = false)
 @NotNull
 public Integer getSeasonId() {
  return seasonId;
 }

 @AssociationId
 public void setSeasonId(Integer seasonId) {
  this.seasonId = seasonId;
 }

 @AssociationId
 public void setProductFamilyId(Integer productFamilyId) {
  this.productFamilyId = productFamilyId;
 }

 @AccessType("field")
 @Column(name = "prodfamily_id")
 @NotNull
 public Integer getProductFamilyId() {
  return productFamilyId;
 }

 @AssociationObject
 public void setProductFamily(ProductFamily productFamily) {
  this.productFamily = productFamily;
 }

 @ManyToOne(fetch = FetchType.LAZY, optional = false)
 @JoinColumns({ @JoinColumn(name = "prodfamily_id", insertable = false, updatable = false),
   @JoinColumn(name = "instit_code", insertable = false, updatable = false) })
 public ProductFamily getProductFamily() {
  return productFamily;
 }


 @Valid
 @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
 @JoinColumns({
   @JoinColumn(name = "optionparam_id", referencedColumnName = "optionparam_id", insertable = false,
     updatable = false),
   @JoinColumn(name = "optionparam_instit_code", referencedColumnName = "instit_code", insertable = false,
     updatable = false) })
 public OptionParameter getOptionParameter() {
  return optionParameter;
 }

 @AssociationObject
 public void setOptionParameter(OptionParameter optionParameter) {
  this.optionParameter = optionParameter;
 }

 @Column(name = "optionparam_id")
 public Integer getOptionParameterId() {
  if (optionParameterId == null) {
   OptionParameter optionParameter = getOptionParameter();
   if (optionParameter != null) {
    optionParameterId = optionParameter.getPk().getId();
   }
  }
  return optionParameterId;
 }


 public void setOptionParameterId(Integer optionParameterId) {
  this.optionParameterId = optionParameterId;
 }

 @NotNull
 @Column(name = "outside_seastickt_allowed")
 @Type(type = "true_false")
 public Boolean getOutsideSeasonTicketAllowed() {
  return outsideSeasonTicketAllowed;
 }

 public void setOutsideSeasonTicketAllowed(Boolean outsideSeasonTicketAllowed) {
  this.outsideSeasonTicketAllowed = outsideSeasonTicketAllowed;
 }

 

 @Transient
 public boolean isDuplicateAllowed() {
  return true;
 }

 @Transient
 public boolean isDeleteAllowed() {
  return getState() == StateEnum.PREPARING
    && !equals(OrganizationContextProviderFactory.getOrganizationContextProvider().getCurrentActivity());
 }

 @AssertTrue
 public boolean validateSeatOptionMaxDelayRequiredWhenSeatOptionIsAllowed() {
  if (isSeatOptionsAllowed()) {
   return getOptionParameter().getMaxDelayBetweenOptionAndConfirmation() != null
     || getOptionParameter().getOptionConfirmationMaxDelayBeforePerformance() != null;
  } else {
   return true;
  }
 }

 @AssertTrue
 public boolean validateSameDecreaseQuotaAvailabilityOptionAsSeason() {
  if (isSeatOptionsAllowed() && getSeason().isSeasonTicketOptionsAllowed()
    && (getSeason().getOptionParameter() != null)) {
   return (getOptionParameter().getOptionDecreaseQuota().equals(getSeason().getOptionParameter()
     .getOptionDecreaseQuota()));
  } else {
   return true;
  }
 }
}


Sunday, July 7, 2013

Make your eclipse look better on ubuntu



When using eclipse on ubuntu, extra space between items and fonts size make it look awkward. I try to adjust fonts by go to [Window->Preferences->General->Appearance->Colors and Fonts]. This will not much help, reduce fonts size does not change space between item. Here is Eclipse Europa before tweak.
Anyway, at last I found the way to make eclipse look more compact from googling. Thank forWesley and Vladimir Buell for this trick. Create ".gtkrc-2.0" in your home directory enable you to customize gtk object style[more about gtkrc-2.0]. Here is my ".gtkrc-2.0".
pnix@pnix-a7n:~$ cat .gtkrc-2.0
style "gtkcompact" {
font_name="Sans 8"
GtkButton::default_border={0,0,0,0}
GtkButton::default_outside_border={0,0,0,0}
GtkButtonBox::child_min_width=0
GtkButtonBox::child_min_heigth=0
GtkButtonBox::child_internal_pad_x=0
GtkButtonBox::child_internal_pad_y=0
GtkMenu::vertical-padding=1
GtkMenuBar::internal_padding=0
GtkMenuItem::horizontal_padding=4
GtkToolbar::internal-padding=0
GtkToolbar::space-size=0
GtkOptionMenu::indicator_size=0
GtkOptionMenu::indicator_spacing=0
GtkPaned::handle_size=4
GtkRange::trough_border=0
GtkRange::stepper_spacing=0
GtkScale::value_spacing=0
GtkScrolledWindow::scrollbar_spacing=0
GtkExpander::expander_size=10
GtkExpander::expander_spacing=0
GtkTreeView::vertical-separator=0
GtkTreeView::horizontal-separator=0
GtkTreeView::expander-size=8
GtkTreeView::fixed-height-mode=TRUE
GtkWidget::focus_padding=0
}
class "GtkWidget" style "gtkcompact"

style "gtkcompactextra" {
xthickness=0
ythickness=0
}
class "GtkButton" style "gtkcompactextra"
class "GtkToolbar" style "gtkcompactextra"
class "GtkPaned" style "gtkcompactextra"
pnix@pnix-a7n:~$

and here is the result. No more extra space, I also change fonts for text editor and Dialog to "DejaVu San size 8".

Source : http://lj4newbies.blogspot.com/2008/02/make-your-eclipse-look-better-on-ubuntu.html

Tuesday, June 4, 2013

InnoDB,MyISAM và MEMORY, nên sử dụng Storage Engine nào khi dùng MySQL

InnoDB và MyISAM, khác nhau giữa InnoDB và MyISAM, so sánh InnoDB và MyISAM, dùng InnoDB hay MyISAM, Kiểu table MEMORYtrong mySQL

MySQL là hệ quản trị cơ sở dữ liệu miễn phí được sử dụng nhiều nhất khi ứng dụng được viết bằng ngôn ngữ PHP. Tuy nhiên, khi tạo 1 bảng trong MySQL sẽ có nhiều kiểu Storage Engine để bạn lựa chọn. Trong đó có 3 kiểu lưu trữ bảng được dùng nhiều nhất là InnoDBMyISAM vàMemory

Nhưng ta nên dùng InnoDB,MyISAM hay MEMORY ? Tại sao lại như thế ? Bài viết này sẽ giúp các bạn nắm được cách hoạt động của cácStorage Engine này. Từ đó có thể biết được cách chọn loại phù hợp khi xây dựng website của mình để hiệu suát và độ ổn định đạt được cao nhất.



Nên chọn MyISAM,InnoDB hay Memory ?


1. MyISAM trong MySQL

Đây là kiểu Storage Engine mặc định khi tạo bảng và được dùng phổ biết nhất. Storage Engine này cho phép lập chỉ mục toàn cột (Full Text Index). Do đó, Storage Engine này cho tốc độ truy suất (Đọc và tìm kiếm) nhanh nhất trong các Storage Engine.

Tuy nhiên, Nhược điểm của MyISAM là hoạt động theo kiểu Table Level locking nên khi cập nhật (Thêm,xóa,sửa) 1 bản ghi nào đó trong cùng 1 table thì table đó sẽ bị khóa lại, không cho cập nhật (Thêm,xóa,sửa) cho đến khi thao tác cập nhật trước đó thực hiện xong.

Ngoài ra, do thiết kế đơn giản và không kiểm tra ràng buộc dữ liệu nên loại Storage Engine này dễ bị hỏng chỉ mục và dễ bị Crash. Đây là cơn ác mộng của các webmaster khi table Crash là table có dung lượng lớn, khi phục hồi rất lâu và hồi hộp 



Table dạng MyISAM hay bị Crash


Làm sao để chuyển 1 bảng từ Storage Engine khác (VD: InnoDB) sang MyISAM ?
Bạn có thể dùng truy vấn sau: 
Code:
ALTER TABLE table_name ENGINE = MyISAM;
2. InnoDB trong MySQL

Đây là kiểu Storage Engine mới hơn MyISAMStorage Engine này không hỗ trợ Full Text Index như MyISAM (Tin mừng là sắp có hỗ trợ ở các phiên bản mới, hiện tại đã có beta rồi ) nhưng hỗ trợ quan hệ giữa các bảng (Khóa ngoại). Do đó, kiểu Storage này kiểm tra tính toàn vẹn dữ liệu và ràng buộc rất cao => Khó sảy ra tình trạng hỏng chỉ mục và Crash như MyISAM.

Ngoài ra, kiểu Storage Engine này hoạt động theo cơ chế Row Level Locking nên khi cập nhật (Thêm,xóa,sửa) 1 bảng thì chỉ có bản ghi đang bị thao tác bị khóa mà thôi, các hoạt động khác trên table này vẫn diễn ra bình thường.

Vì những tính chất trên, kiểu Storage Engine này thích hợp sử dụng cho Ngân hàng và các trang web có tần suất cập nhật dữ liệu cao như Mạng xã hội, diễn đàn....

Tuy nhiên, nó có nhược điểm là hoạt động tốn RAM hơn so với MyISAM  (Nếu MyISAM mà tần suất insert hay update cao thì nếu cấu hình chưa đủ mạnh thì khéo còn tốn RAM nhiều hơn InnoDB vì hàng đợi lớn  )

=> vBulletin, mã nguồn diễn đàn lớn nhất hiện nay thật sai lầm khi chọn MyISAM làm kiểu Storage Engine cho các bảng dữ liệu forum. Vì thế mà các trang lớn mới hay bị Crash bảng như vậy (Database Error)

Làm sao để chuyển 1 bảng từ Storage Engine khác (VD: MyISAM) sang InnoDB ?
Bạn có thể dùng truy vấn sau: 
Code:
ALTER TABLE table_name ENGINE = InnoDB;
(Lưu ý là nếu trước đó table này dùng MyISAM mà có cột nào đặt Full Text Index thì bạn phải xóa Full Text Index trên cột đó đi mới có thể chuyển được)


3. MEMORY trong MySQL

Đây là kiểu Storage Engine được lưu trữ dữ liệu trực tiếp lên RAM nên tốc độ truy xuất và cập nhật rất nhanh. Vì thế, nó được dùng làm các table chứa dữ liệu tạm, chứa các phiên làm việc của user...

Khi khởi động lại dịch vụ MySQL thì dữ liệu trên bảng có Storage Engine là MEMORY sẽ mất hết dữ liệu. Chính vì thế nên khi các bạn khởi động lại mysqld trên VPS hay Server thì sẽ thấy số người online = 0 
MEMORY sử dụng cơ chế table-level locking như MyISAM.

Dung lượng của 1 bảng Storage Engine dạng MEMORY tối đa là bao nhiêu ?
Nó phụ thuộc vào cấu hình thông số max_heap_table_size trong file my.cnf, mặc định 1 bảng kiểu MEMORY có dung lượng tối đa là 16MB. Nếu vượt quá bạn sẽ nhận được lỗi: Table xyz is full... 


Tóm lại, 
-> Với 1 ứng dụng có tần suất đọc cao như trang tin tức,blog... thì bạn nên dùng MyISAM.
-> Với ứng dụng có tần suất insert và update cao như: Diễn đàn, mạng xã hội.. thì bạn nên dùng InnoDB
-> Bạn nên dùng MEMORY Storage Engine cho các table chứa dữ liệu tạm và thông tin phiên làm việc của người dùng (Session)
-> Việc chuyển đổi 1 table từ storage engine này sang storage engine khác sẽ diễn ra tương đối lâu nếu dữ liệu trên table lớn. Do đó cần kiên nhẫn.


Bài viết chỉ post trên sinhvienit.net, ai copy đi đâu vui lòng ghi rõ nguồn http://sinhvienit.net/forum/threads...hi-dung-mysql/.
Cám ơn !