Thursday, January 27, 2011

Clean Cache Process from Phisical Memory in Linux OS


As already known, Linux operating system knows with mature memory management facility, where the system will use maximum extra space in the memory as cache storage. The free area in memory should be accessible to be used by running processes in the system. But unfortunately there are some Linux distributions which doesn’t automatically include this facility, as now I use openSUSE 11.2 32bit and 64bit, maybe the developers are thinking cache memory eliminate is not very important compare to provide an empty memory space for running system optimally.

Currently I’m maintaining a server with 8GB memory, when the server first time startup or restarts, it can be seen by put "top" command to shell, then it will be see very much availability of space in physical memory. It could be said from 8GB available memory is only use 500MB, but when the operating system has been running for more than 2 days with applications that run on the Java platforms and MySQL database it has to be ascertained the server will crash because it ran out of empty space in memory while the JVM cache management and database cache system already sett to maximum configuration in order not to spend to much space in physical memory, and at last it requires to manual restart periodically.

But this is not a concern anymore now, when I found a command to clear the cache from memory. When I search it in Google and will be discussed in the following note.

There are 3 kinds of cleaning cache methods in memory, which can only be distinguished by the numbers 1, 2 or 3, the first is to clean pagecache (pagecache is information stored in memory which result from process of reading and writing data to disk), the second clean dentries and inodes (dentries and inodes are part of the Virtual File System in Linux), the third cleaning pagecache, dentries and inodes:

echo 1 > /proc/sys/vm/drop_caches
echo 2 > /proc/sys/vm/drop_caches
echo 3 > /proc/sys/vm/drop_caches

But do not forget to write "sync" command in the shell before writing the above three kinds of commands. From the three script mentioned above to obtain maximum results we recommend use the "echo 3 > /proc/sys/vm/drop_caches", and by using "top" command we can see that there is impairment results in "Memory Used" section from generated "top" command interface.

After knowing the useful of these commands then we can use it when the memory full in server, but this would be done manually? The response is "It can!”, imagine if it can not be done automatically it will lead to people who served as server administrator to suffer. Therefore it's good to use crontab in scheduling command is executed. Simply by inserting the commands written below to crontab editor then the function to clear the memory cache has to run every hour 6 am and 6 pm.

0 6,18 * * * sync
1 6,18 * * * echo 3 > /proc/sys/vm/drop_caches

In this article did not explain more about crontab and how to edit this function, because to know more about this can be found in article http://gienvision-en.blogspot.com/2011/01/periodic-backups-mysql-database-server.html.

Maybe for now, only this knowledge can be shared with readers, and hopefully may be useful, if there is a shortage or entries which can improve please feel free to add comments.


Read More...

Wednesday, January 19, 2011

Periodic backups MySQL Database Server in Solaris 10


After several years struggling with the Solaris server, I am grateful much new knowledge that can digging during that period, and it makes me want to share with others. And now I would like to share how MySQL database backup periodically, into compressed *. tar.gz file, this can be done by using 'time scheduler' if used windows OS, but what would we use if it works in Solaris environment as a server, and now we going to discuss it.

The first thing to know is how the process of 'dump and restore' in MySQL database, as has been stated in the manual doc, process can be done by execution of command as follows:

mysqldump –u username --password=pass_user --databases schema_db > one_file.sql

The script above is showing database command for backup into *.sql file, for a glance we can describe this commands as follows: 'mysqldump' is one of few basic commands in MySQL database to save the database to a file, '-u' is one of property command in mysql to access database using username, which is an important component to access MySQL database, 'username' is used to authorize users to access and manipulate commands in the database, for this we will use 'root' as user, '- password = pass_user ', while MySQL passwords are properties that must be included when users want to access the database as an authentication key, while 'schema_db' is a name of database schema to be data loaded into SQL dump file.

After 'dump' the database schema into a file 'one_file.sql' finished, the next process is to change the file into more compact file by using '*. tar.gz' extension, in the following manner:

tar –cf one_file.sql | gzip –c > /destination_folder/one_file_tar.tar.gz

And now we get sql dump files that have been zipped into tar.gz file, then what else to do? Next is to remove sql file from temporary folder so that left behind is only tar.gz file using 'rm' command.

rm *.sql

And now we know some major orders in Autobackup process on server, now we're going to combine a collection of several commands into 'sh' file which can be executed. For example if we send a command to database server use Solaris platform with database schema named 'gienet' that will be saved to a folder '/export/home0/gienet_backup', backup file with naming format 'gienet-yyyy-MM-dd-HH-mm-ss.sql', which will be save in zip format with naming convention 'gienet-yyyy-MM-dd-HH-mm-ss.tar.gz', this backup process will execute when the clock system shows at 00:30.

Now lets create a file named backup-script.sh (names not required to use this name), use command 'touch backup-script.sh' in the shell, then do editing with this command 'vi backup-script.sh', begins with the first line contains '#! / bin / sh' with a few lines of comment followed by examples like show below:

#!/bin/sh
#
# This is example executable file for mysql database backup
#

Continue with add a declaration variable for date format on the file name, and also folder name variable that will become a place to store backup files.

NEW_DATE=’date +%Y-%m-%d-%T’
NEW_DIR=’/export/home0/gienet_backup’

Then proceed with the database script backup, assuming we use a root as user to perform backups and 'admin' as password, then the next script which should be written like this:

mysqldump –u root –password=admin –-databases gienet > $NEW_DIR/gienet-$NEW_DATE.sql

Once the mysqldump process completed and produces 'gienet-yyyy-MM-dd-HH-mm-ss.sql' file continue with a compress the files to smaller sizes into a tar.gz file with the command like show below:

cd $NEW_DIR
tar –cf gienet-$NEW_DATE.sql | gzip –c > $NEW_DIR/gienet-$NEW_DATE.tar.gz

Perform delete sql files in a folder that was setting in variable '$ NEW_DIR' with the aim of remaining files in the folder only tar.gz file and maintain disk space not full by ambiguous file contents, with this script:

rm $NEW_DIR/*.sql

It's finished to make MySQL database automatic backups scripts in the file 'backup-script.sh', do the saving process on the active editor 'vi' with command ':wq!'. The process followed by move the file to the folder '/usr/bin' and give the file system permissions with this command 'chmod + x backup-script.sh', and then register the file to Solaris scheduler use 'crontab', you must first do some setting editor default in shell. With this command sequence:

#export DISPLAY=vi
#crontab -e

So the shell will produce output like shows below:

#ident  "@(#)root       1.21    04/03/23 SMI"
#
# The root crontab should be used to perform accounting data collection.
#
#
10 3 * * * /usr/sbin/logadm
15 3 * * 0 /usr/lib/fs/nfs/nfsfind
30 3 * * * [ -x /usr/lib/gss/gsscred_clean ] && /usr/lib/gss/gsscred_clean
#
# The rtc command is run to adjust the real time clock if and when
# daylight savings time changes.
#
1 2 * * * [ -x /usr/sbin/rtc ] && /usr/sbin/rtc -c > /dev/null 2>&1
#10 3 * * * /usr/lib/krb5/kprop_script ___slave_kdcs___

Point the cursor on last row and last column then press enter, do some input script to run the backup-script.sh file for every 0:30 AM every day in server with the script as follows:

#
# Script for autobackup database
#
30 0 * * * sh /usr/bin/backup-script.sh

To learn more about crontab script, it can be seen in http://adminschoice.com/crontab-quick-reference, to know the script running as desired, the next morning you can see to the folder '/export/home0/gienet_backup', if there any 'gienet-yyyy-MM-dd-HH-mm-ss.tar.gz' files, so the script is successfully without any error, if not meaning there still have errors in script. Do some check to that script and repeat the process from above.

Maybe for now, only this knowledge can be shared with readers, and hopefully may be useful, if there is a shortage or entries which can improve please feel free to add comments.


Read More...

Thursday, October 21, 2010

IP Address configuration for Sun Solaris 10


Just to share the experience, for this time is a little bit different. I’m going to share how to manage ip address configuration on Server Sun Solaris 10, either for fresh installation Solaris or just change old ip address configuration to a new one. Basically command shell in Sun Solaris look alike operating system unix base, but it slightly different with Linux Further more discuss on next line.

First we must know how syntax in network command on unix environment, such as ifconfig, netstat, ping and traceroute. Usually when run on solaris installation process on the first time, installation procedure always begin with network installation and all derivative process, until the procedure finish with no error result, when we in solaris shell console and type ifconfig or netstat command will show result like show below on display:

# ifconfig -a
lo0: flags=2001000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv4,VIRTUAL> mtu 8232 index 1
inet 127.0.0.1 netmask ff000000
nge0: flags=1000843<UP,BROADCAST,RUNNING,MULTICAST,IPv4> mtu 1500 index 2
inet xx.xx.x.x netmask ffff0000 broadcast xx.xx.xxx.xxx
ether 0:21:28:25:6b:c4
nge1: flags=1000843<UP,BROADCAST,RUNNING,MULTICAST,IPv4> mtu 1500 index 3
inet xxx.xxx.xxx.xxx netmask fffffff8 broadcast xxx.xxx.xxx.xxx
ether 0:21:28:25:6b:c5
#

Notice the sample script above, from three interface shown above we can see the status is UP and looked in this script “<UP,LOOPBACK,RUNNING,MULTICAST,IPv4,VIRTUAL>” and “<UP,BROADCAST,RUNNING,MULTICAST,IPv4>” which mean this configuration is correct and working properly, also we can looked at sample script like shown below. Figure below is show how the route between pc to gateway and to intranet or internet.

# netstat -rn

Routing Table: IPv4
Destination Gateway Flags Ref Use Interface
-------------------- -------------------- ----- ----- ------ ---------
xxx.xxx.xxx.xxx xxx.xxx.xxx.xxx U 1 700 nge1
xx.xx.x.x xx.xx.x.x U 1 64128 nge0
224.0.0.0 xxx.xxx.xxx.xxx U 1 0 nge1
default xxx.xxx.xxx.xxx UG 11495783
127.0.0.1 127.0.0.1 UH 235 829415 lo0
#

If in shell type ping command then the result we like shown below and mark the netword card configuration is connected:

# ping localhost
localhost is alive
#

# ping xx.xx.x.x
xx.xx.x.x is alive
#

And now big mark question are? How possible, If we want to replace old ip address to new one with result any conflict or error? This stuff is going to discuss now, first we must to know that in Solaris OS hade two type configuration effect, which is temporary and permanent, when we chose to set the configuration temporary and if the server restarted then the configuration we already made before will lost and return to original configuration before the set, and when we chose to set permanently if the server restarted the configuration will stand still.

For temporary we can use this command: “ifconfig <interface> <ip address> <netmask> <broadcast address>” or if we use command above to real command become like this “ifconfig nge0 10.11.2.3 netmask 255.255.0.0”. After reconfigure ip address finish, then recheck using this command “ifconfig –a”, if the indicator show UP status it’s mean the configuration runs well. If not repeat this procedure until the configuration runs properly.

Beside temporary configuration we have permanent too, which evolved four file and the process outlined as follows, first we must to know the file evolved to this process are which one?

/etc/hosts
/etc/defaultrouter
/etc/netmask
/etc/inet/ipnodes

First file must to know is /etc/hosts if used “vi” command in unix shell then will produce snapshot like shown below, this written configuration below for three interface, which is “lo0”, “nge1” and “nge0”, for lo0 interface with default ip 127.0.0.1 and hostname “localhost” not necessary to change, cause it’s already default loopback system, for other interface beside lo0 still can change according with needed. We have “loghost” which mark this ip as default connection to network when system startup. If used ip address want to change into new ones just to change this “xxx” section. For “host-name” naming best way not to change it, followed first naming which already assign on first installation Sun Solaris System.

#
# Internet host table
#
127.0.0.1 localhost
xxx.xxx.xxx.xxx pc-server loghost
xx.xx.x.x pc-local

After /etc/hosts configure then specify which router will be taken as center for network connection in /etc/defaultrouter file, in this file contain one row only that specify IP address destination as router, change this line if you wish to change your default router.

If /etc/defaultrouter configure properly, then continue with /etc/netmask, as you can see below, this file specifying IP address as subnetmask installed in Solaris, for instance if you wish to use nge1 interface connect to gateway with this IP 192.101.0.160 and netmask written was 255.255.255.248 then this netmask will broadcast max in 192.101.0.167, so the gateway 192.101.0.160 only contain IP range between 161 to 167, while for nge0 interface if netmask set to this gateway 10.10.0.0 with netmask 255.255.0.0 then it will contain IP range between 1 to 255 in third segment and also 1 to 255 on the fourth segment.

#
# The netmasks file associates Internet Protocol (IP) address
# masks with IP network numbers.
#
# network-number netmask
#
# The term network-number refers to a number obtained from the Internet Network
# Information Center.
#
# Both the network-number and the netmasks are specified in
# "decimal dot" notation, e.g:
#
# 128.32.0.0 255.255.255.0
#
192.101.0.160 255.255.255.248
10.10.0.0 255.255.0.0

The last step before the restart is to change the system configuration files in /etc/inet/ipnodes, make necessary change to ip address in this file, in sample below configure make equal to /etc/netmask which ip address for “nge1” and “nge0” interface is 192.101.0.161 and 10.10.2.2, while for lo0 interface it’s already default would use 127.0.0.1, but for this configuration works make it equal with ip address contain in /etc/hosts.

After finishing all the stages in the Solaris network configuration settings then save all the files that have been configured, then restart the Solaris system, after start-up sequence is complete, then go to the unix console and give the command "ifconfig -a" and "netstat -rn", and look again at the status results of each interface is UP or not, if the configuration is correct UP and ready to connect to the network and another computer. Give the ping command to the gateway, if the status of "192.101.0.160 is alive" means all steps successfully, if not then repeat again the above process until finished.

#
# Internet host table
#
::1 localhost
127.0.0.1 localhost
192.101.0.161 suatu-server loghost
10.10.2.2 suatu-local

Maybe for now, only this knowledge can be shared with readers, and hopefully may be useful, if there is a shortage or entries which can improve please feel free to add comments.


Read More...

Sunday, July 25, 2010

CRUD using Hibernate Annotations with Netbean 6.0


In this article we will discuss about the basic make the process of Create, Read, Update and Delete using Hibernate as the Framework and Netbean as its IDE, Hibernate configuration usually always never loose with Spring configuration, but on this occasion I will elaborate on Hibernate without Spring, with the aim if you want to create desktop applications the Spring configuration is not required.

Before we start it's good to know a class-library will be need it takes to build applications using Hibernate Annotations, as follows:


Now how do I enter all libraries into the project properties that we will create? Enough that we follow these steps: from the Toolbar select Tools then clicked, will popup dropdown menu, then select Libraries then will come out the window box with title "Library Manager", then press the "New Library", then come out again the window box with the title "New Library", fill in the word "Hibernate” in the Library Name text box, continue to select the "Class Libraries" dropdown box Type Library, then press OK, then select Hibernate library jar file that has been listed above to the folder which we have previously determined by press the button "Add Jar / Folder" on the tab "Classpath", after the files sent it will displayed like this:

After that, press "OK" button, now the discussion will be continued by creating a new project in the IDE Netbean. After creating a new project, whether web or desktop project, the project window will as follows:

After creating a project, first enter the hibernate libraries by right click on the library folder, then click "Add Library" and will come out a window with the title "Add Library", forwarded by selecting the necessary library which is selected, then "Add Library", then the Library folder in the project will display the entire library jar file that will required in the application to be built.

After all required libraries are prepared in the library folder, now it's time to discuss making CRUD using Hibernate, before you start coding with java class we need to know beforehand the basic configuration that must be met, so that Hibernate can work properly, this configuration involves an xml file that will be placed in the root folder of the folder "Source Packages", these files must be named "hibernate.cfg.xml" and the contents of the file will be as follows:


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Database connection settings -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/latih</property>
<property name="connection.username">root</property>
<property name="connection.password">admin</property>
<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">1</property>
<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>
<!-- Drop and re-create the database schema on startup -->
<property name="hbm2ddl.auto">none</property>

<mapping class="xxx.TabelSiswa"/>
</session-factory>
</hibernate-configuration>

From the source xml above configuration, there are several properties that must exist to build hibernate based application framework, the following list and description for more details can be viewed on the link http://www.hibernate.org/hib_docs/reference/en/html/session-configuration.html:

- connection.driver.class, This property is used as a determinant of what database driver will be used to connect to database.

- connection.url, This property is used to determine the url destination of database to be used as a connection to the database.

- connection.username, property user name that is used to access databases.

- connection.password, property password that is used to access databases.

- connection.pool.size, property that is used as maximum limit how many connections may used to connect to the database.

- dialect, property that determines what types dialect that will be used, adjusted to the type of database used.

- current_session_context_class, property that is used to treat the session context, the choice is jta | thread | managed | custom.Class.

- cache.provider_class, property to specify a custom class that will be used to CacheProvide.

- show_sql, property to show that the execution of SQL commands the choice can be true or false.

- hbm2ddl.auto, property for automatic validation or export a database schema to the SessionFactory when made, and create-drop properties directly in the schema will drop when the SessionFactory is closed. When the properties set to none means not to do anything against the database schema.

While for a line of code <mapping class="xxx.TabelSiswa"/> is command for mapping an Annotation Model classes so that it can be read by hibernate.cfg.xml file, the amount of mapping will be more or less depending on the number of class models are made to support your application.

When finished with the configuration now the time to make a model class that represents a table in a database. As an example we will create a class "TabelSiswa" which will be stored in the package "xxx", the code as follow:

package xxx;

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "tbl_siswa")
public class TabelSiswa implements Serializable{
@Id
@GeneratedValue
private int id;

@Column(name="no_induk", nullable=false,length=10)
private String nomorInduk;

@Column(name="nama", nullable=false,length=30)
private String nama;

@Column(name="alamat", nullable=false,length=45)
private String alamat;

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getNomorInduk() {
return nomorInduk;
}

public void setNomorInduk(String nomorInduk) {
this.nomorInduk = nomorInduk;
}

public String getNama() {
return nama;
}

public void setNama(String nama) {
this.nama = nama;
}

public String getAlamat() {
return alamat;
}

public void setAlamat(String alamat) {
this.alamat = alamat;
}
}

The above code represents a table in a MySQL database called "tbl_siswa" with field names specified in the @ Column properties above, from source code "TabelSiswa" above we can see some syntax code that begins with "@" sign, which is called Annotations briefly will be explained the meaning of each following the above commands, but for more details can be viewed on the following link http://www.hibernate.org/hib_docs/annotations/reference/en/html/entity.html:

- @Entity, serves to define a model class is an bean associated with the POJO persistence.

- @Table, serves to connect an Entity classes on a table in a database schema.

- @Id, serves to define the propery of the entity bean fields that will serve as the primary key.

- @GeneratedValue, serves to define generator type that is used to obtain the value of identifier @Id.

- @Column, serves as the property of field mapping a field in the table in the database.

Then create a java class file that called HibernateUtility.java used as a Session Factory, which connects a process which was generated programmatic transaction with hibernate configuration system that has been predetermined. The source code of HibernateUtility would this as follow:

package xxx;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;

public class HibernateUtil {
private static final SessionFactory sessionFactory;

static{
try{
sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
}catch(Throwable th){
System.err.println("Initial SessionFactory creation failed"+th);
throw new ExceptionInInitializerError(th);
}
}

public static SessionFactory getSessionFactory(){
return sessionFactory;
}
}

When finished making HibernateUtility.java now begin discussing the process of Create, Read, Update and Delete, which will be stored in the package "xxx.client", here is source code "CreateData.java" which contains examples of commands to enter data:

package xxx.client;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import xxx.HibernateUtil;
import xxx.TabelSiswa;

public class CreateData {
public static void main(String[] args) throws Exception {
SessionFactory sessFact = HibernateUtil.getSessionFactory();
Session sess = sessFact.getCurrentSession();
Transaction tr = sess.beginTransaction();
TabelSiswa stu = new TabelSiswa();
stu.setNama("Yudhi");
stu.setNomorInduk("100");
stu.setAlamat("Jl. Sukajadi No. 10");
sess.save(stu);
tr.commit();
System.out.println("Successfully inserted");
sessFact.close();
}
}

Discussing what is written on the source code in the first row to third in the method "main" written to initialize Hibernate Session and Transaction, then proceed with initialization "TabelSiswa" that connects directly to the table "tabel_siswa" in the database, with the amount of variables to the method "set" and then inserted into the method "save" that are under the initialization Session, it has been a process of "insert into" on the table in database. Then close the command with "commit" to the execution of insert data to table and "close" to terminate the Session initialization.

Followed by "ReadData.java" source code:


package xxx.client;

import java.util.Iterator;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import xxx.HibernateUtil;
import xxx.TabelSiswa;

public class ReadData {
public static void main(String[] args) throws Exception {
SessionFactory sessFact = HibernateUtil.getSessionFactory();
Session sess = sessFact.getCurrentSession();
Transaction tr = sess.beginTransaction();
Query query = sess.createQuery("from TabelSiswa");
List result = query.list();
Iterator it = result.iterator();
System.out.println("id sname sroll scourse");
while(it.hasNext()){
TabelSiswa st = (TabelSiswa)it.next();
System.out.print(st.getId());
System.out.print(" "+st.getNomorInduk());
System.out.print(" "+st.getNama());
System.out.print(" "+st.getAlamat());
System.out.println();
}
sessFact.close();
}
}

Slightly different from the source code before, the above command is to display data from tables or the same with the command "select" in the query, but if you use Hibernate enough with the "createQuery" command and specify the name of instant mapping table, it’s enough to retrieve the data, the need to take data can be changed based on the 'where clause' as required. It also required List and Iterator class to parse the class that will encapsulate the smallest object.


Followed by "UpdateData.java" source code:

package xxx.client;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import xxx.HibernateUtil;
import xxx.TabelSiswa;

public class UpdateData {
public static void main(String[] args) throws Exception{
SessionFactory sessFact = HibernateUtil.getSessionFactory();
Session sess = sessFact.getCurrentSession();
Transaction tr = sess.beginTransaction();
TabelSiswa st = (TabelSiswa)sess.load(TabelSiswa.class,4);
st.setAlamat("Jl. Lodaya No. 125");
tr.commit();
System.out.println("Update Successfully");
sessFact.close();
}
}

For the source code UpdateData processes that occurred not far different from what happened in the process CreateData, little things that differentiate only on the line "TabelSiswa st = (TabelSiswa) sess.load (TabelSiswa.class, 4);" that is used to retrieve data that will edited into the database with the entity model "TabelSiswa" and make any changes, after which it did commit. And the last is deleting process in "DeleteData.java" file, source code as follows:

package xxx.client;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import xxx.HibernateUtil;
import xxx.TabelSiswa;

public class DeleteData {
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub

SessionFactory sessFact = HibernateUtil.getSessionFactory();
Session sess = sessFact.getCurrentSession();
Transaction tr = sess.beginTransaction();
TabelSiswa st = (TabelSiswa)sess.load(TabelSiswa.class,4);
sess.delete(st);
System.out.println("Deleted Successfully");
tr.commit();
sessFact.close();

}
}

DeleteData source code process that occurs is not much different from what happens in UpdateData process, little things that differentiate only on the line "sess.delete(st);" that is used to retrieve data to be deleted from the database with the entity model "TabelSiswa" after that do commit.

Ok good luck! Maybe for this time this is trick that can be shared with the reader hope it useful, if there is a shortage or entries which can improve please feel free to give comment.

Here's a list of links that can be used to download the required jar files:

- http://antlr.org/

- http://www.java2s.com/Code/Jar/Spring-Related/cglib-nodep-2.1_3.jar.htm

- http://sourceforge.net/project/showfiles.php?group_id=56933

- http://sourceforge.net/project/showfiles.php?group_id=40712

- http://commons.apache.org/downloads/

- http://www.dom4j.org/download.html

- http://sourceforge.net/project/showfiles.php?group_id=93232

- http://logging.apache.org/log4j/1.2/download.html


Read More...

Thursday, March 19, 2009

Hibernate Criteria Query - MySQL Command Syntax Dictionary


For some viewer already know about Java Platform may already familiar with Hibernate, and so for viewer already familiar with Hibernate probably already know with “Criteria Query” term. In this time I’ll try to discuss equality function between Criteria Query and MySQL, with purpose to help other in order to learn about Hibernate and how the function similarity between Criteria Query and basic standard command in MySQL query syntax.

And now we can start to discuss those thing, first we take a table for example in MySQL and going to convert into a class model with java platform and follow by term of Hibernate. In this case we going to use Hibernate Annotation so we not need xml file for field class mapping to field table in a database. For simple case we try to create a table and called it with name “karyawan” and so we create java class model with a same name.


Nama FieldType FieldPrimary Key
idInteger / NumericYes
namaVarchar(30)
tgl_masukDate
upahDecimal(20,10)

With this command we can create this table on MySQL:

CREATE TABLE `karyawan` (                                  
`id` int(11) NOT NULL auto_increment,
`nama` varchar(30) default NULL,
`tgl_masuk` date NOT NULL default '1970-01-01',
`upah` decimal(20,10) default NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC

Then create model class “Karyawan” made by these syntax show below:

@Entity
@Table(name="karyawan")
public class Karyawan implements Serializable {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;

@Column(name="nama")
private String nama;

@Temporal(TemporalType.DATE)
@Column(name="tgl_masuk",nullable=false,columnDefinition="date")
private Date tglMasuk;

@Column(name="upah")
@Type(type="big_decimal")
private BigDecimal upah;

public Karyawan() {}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getNama() {
return nama;
}

public void setNama(String nama) {
this.nama = nama;
}

public Date getTglMasuk() {
return tglMasuk;
}

public void setTglMasuk(Date tglMasuk) {
this.tglMasuk = tglMasuk;
}

public BigDecimal getUpah() {
return upah;
}

public void setUpah(BigDecimal upah) {
this.upah = upah;
}
}

By assuming that you already know about Hibernate by this reference article “Proses CRUD Dengan Hibernate Annotations Menggunakan Netbean 6.0”, then we can strait to discuss how to use Criteria Query, we can use these class “Criteria” from “org.hibernate.Criteria” or “DetachedCriteria” from “org.hibernate.criterion.DetachedCriteria” and followed by these class “Expression” from “org.hibernate.criterion.Expression” or “Restriction” from “org.hibernate.criterion.Restriction”, and than with assumption we going to call all data in the table “Karyawan” then we can use this SQL command like shown below:

select * from Karyawan;

whereas used Criteria Query even though “Criteria” or “DetachedCriteria” will produce command line syntax like shown below:

getSession().createCriteria(Karyawan.class).list();

The table shown below are equality command between Criteria Query and MySQL command:

MySQLHibernate Criteria Query
select * from Karyawan where id = 1;getSession().createCriteria(Karyawan.class) .add(Expression.eq(“id”, Long.valueOf(1)))
.list();
select * from Karyawan where id != 1;getSession().createCriteria(Karyawan.class) .add(Expression.ne(“id”, Long.valueOf(1)))
.list();
select * from Karyawan where id <> 1;getSession().createCriteria(Karyawan.class) .add(Expression.ne(“id”, Long.valueOf(1)))
.list();
select * from Karyawan where nama = “sesuatu”;getSession().createCriteria(Karyawan.class)
.add(Expression.eq(“nama”, “sesuatu”))
.list();
select * from Karyawan where tgl_masuk = “1900-01-01”;getSession().createCriteria(Karyawan.class)
.add(Expression.eq(“tglMasuk”, new java
.util.Date(java.sql.Date
.valueOf("1900-01-01"))))
.list();
select * from Karyawan where upah = 10000;getSession().createCriteria(Karyawan.class)
.add(Expression.eq(“upah”, BigDecimal
.valueOf(10000)))
.list();
select * from Karyawan where id > 10;getSession().createCriteria(Karyawan.class)
.add(Expression.gt(“id”, Long.valueOf(10)))
.list();
select * from Karyawan where id < 10 and id > 30;getSession().createCriteria(Karyawan.class)
.add(Expression.lt(“id”, Long.valueOf(10)))
.add(Expression.gt(“id”, Long.valueOf(30)))
.list();
select * from Karyawan where id < 10 or id > 30;getSession().createCriteria(Karyawan.class)
.add(Expression.or(Expression.lt(“id”, Long.valueOf(10)), Expression.gt(“id”, Long.valueOf(30))))
.list();
select * from Karyawan where id <= 10;getSession().createCriteria(Karyawan.class)
.add(Expression.le(“id”, Long.valueOf(10)))
.list();
select * from Karyawan where id >= 10;getSession().createCriteria(Karyawan.class)
.add(Expression.ge(“id”, Long.valueOf(10)))
.list();
select * from Karyawan where nama like ‘sesu%’;getSession().createCriteria(Karyawan.class)
.add(Expression.like(“nama”, “sesu”, MatchMode.END))
.list();
select * from Karyawan where nama like ‘%sua%’;getSession().createCriteria(Karyawan.class)
.add(Expression.like(“nama”, “sua”, MatchMode.ANYWHERE))
.list();
select * from Karyawan where nama like ‘%atu’;getSession().createCriteria(Karyawan.class)
.add(Expression.like(“nama”, “atu”, MatchMode.START))
.list();
select * from Karyawan where nama like ‘sesuatu’;getSession().createCriteria(Karyawan.class)
.add(Expression.like(“nama”, “sesuatu”, MatchMode.EXACT))
.list();
select * from Karyawan where id between 0 and 100;getSession().createCriteria(Karyawan.class)
.add(Expression.between(“id”, Long.valueOf(0), Long.valueOf(100)))
.list();
select * from Karyawan where nama = ‘’;getSession().createCriteria(Karyawan.class)
.add(Expression.isEmpty(“nama”))
.list();
select * from Karyawan where nama <> ‘’;getSession().createCriteria(Karyawan.class)
.add(Expression.isNotEmpty(“nama”))
.list();
select * from Karyawan where nama is null;getSession().createCriteria(Karyawan.class)
.add(Expression.isNull(“nama”))
.list();
select * from Karyawan where nama is not null;getSession().createCriteria(Karyawan.class)
.add(Expression.isNotNull(“nama”))
.list();
select * from Karyawan where id in (1,3,5,7);List<Long> idlist = new ArrayList<Long>();
idlist.add(1);
idlist.add(3);
idlist.add(5);
idlist.add(7);
getSession().createCriteria(Karyawan.class)
.add(Expression.in(“id”, idlist))
.list();
select * from Karyawan where id not in (1,3,5,7);List<Long> idlist = new ArrayList<Long>();
idlist.add(1);
idlist.add(3);
idlist.add(5);
idlist.add(7);
getSession().createCriteria(Karyawan.class)
.add(Expression.not(Expression.in(“id”, idlist)))
.list();
select * from Karyawan where id > 1 order by id ASC;getSession().createCriteria(Karyawan.class)
.addOrder(Order.asc(“id”))
.add(Expression.ge(“id”, Long.valueOf(1)))
.list();
select * from Karyawan where id > 1 order by id DESC;getSession().createCriteria(Karyawan.class)
.addOrder(Order.desc(“id”))
.add(Expression.ge(“id”, Long.valueOf(1)))
.list();

For additional note, these “Expression.not” or “Restriction.not” command cannot used for MySQL query command like this “Select * from Karyawan where id <> 1” or “Select * from Karyawan where id != 1” though in syntax show where condition “not equal” cause by this command in Criteria Query already represent by “Expression.ne” or “Restriction.ne”. As reference for correct syntax, if Hibernate command we created as part of web-app using Spring Framework, then all example show above must written in Class DAO Implementation, but if isn’t than it necessary to write in Object Class. Like sample below:

@SuppressWarnings("unchecked")
public List<Karyawan> loadContohSatu() {
List<Long> idlist = new ArrayList<Long>();
idlist.add(1);
idlist.add(3);
idlist.add(5);
idlist.add(7);

return getSession().createCriteria(Karyawan.class)
    .add(Expression.not(Expression.in(“id”, idlist))).list();
}

@SuppressWarnings("unchecked")
public List<Karyawan> loadContohDua() {
return getSession getSession().createCriteria(Karyawan.class)
    .addOrder(Order.asc(“id”))
    .add(Expression.ge(“id”, Long.valueOf(1))).list();
}

Perhaps for this moment this knowledge that I can share to all reader, if in this article contain some mistake, please don’t mind to correct me if I done some wrong or give me some advise and comment.


Read More...

Sunday, December 21, 2008

Sortable Datagrid with Paginating Data


For this moment now I would like to discuss data grids show by browser which add by capability of data field sorting, can be an ascending or descending, beside that also add ability of data paginating, so as we want to expose a numerous of data in a browser, it don’t need scrolling anymore and replace by data paginating which divide the data into several page.

Step one is create a table tag in scope of html tag in php file which going to be expose on a browser, as an example we use 'tbl_siswa' as table on mysql database. And safe this file as 'sortable.php' and fill this file with this syntax like shown below:



<html>
<head>
<title>Editable Data Grid</title>
<script type="text/javascript" language="javascript">
<!—- Fill it with javascript -->
</script>
</head>
<body>
<form id="myForm" name="myForm" method="post">
<div class="area">
<br>
<table width="80%" cellpadding="0" cellspacing="0" border="0">
<tr><td align="right"><? //Fill it with paginating code ?></td></tr>
<tr><td align="right"> </td></tr>
</table>
<table width="80%" cellpadding="0" cellspacing="0" border="1" >
<tr>
<th width="0%"> </th>
<th width="24%" onclick="<!--Function sort-->">Nomor Induk</th>
<th width="24%" onclick="<!--Function sort-->">Nama Siswa</th>
<th width="50%" onclick="<!--Function sort-->">Alamat Lengkap</th>
</tr>
<? //Diisi kode looping data ?>
<tr>
<td> </td>
<td><? //Diisi kode php echo ?></td>
<td><? //Diisi kode php echo ?></td>
<td><? //Diisi kode php echo ?></td>
</tr>
<? //Diisi kode looping data ?>
</table>
</div>
</form>
</body>
</html>

Next thing to do is write code to query data in 'tbl_siswa' table, first we must create several variable to initialize and use it for sorting and paginating process, as follow is php code written in template file and place it in beginning of file before code like shown above, and the php code is like shown below:


<?
$fieldId = 1;
if (isset($_REQUEST['fieldId'])) {$fieldId = $_REQUEST['fieldId'];}

$lastSort = 'asc';
if (isset($_REQUEST['sort'])) {$lastSort = $_REQUEST['sort'];}

$link = mysql_connect('localhost', 'root', 'admin');
if (!$link) {die('Could not connect: ' . mysql_error());}

$link1 = mysql_select_db('latih');
if (!$link1) {die('Could not select database');}

if ($fieldId == '1') {
$field = 'no_induk';
} else if ($fieldId == '2') {
$field = 'nama';
} else if ($fieldId == '3') {
$field = 'alamat';
} else {
$field = 'no_induk';
}

$query0 = 'SELECT id, no_induk, nama, alamat FROM tbl_siswa ORDER BY '.$field.' '.$lastSort;
$resultRow = mysql_query($query0);
$num_rows = mysql_num_rows($resultRow);

$first_pages = 1; $data_content = 5;
$last_pages = ceil($num_rows / $data_content);

$increment = $first_pages;
if (isset($_REQUEST['increValue'])) {$increment = $_REQUEST['increValue'];}

// Is used limit offset mysql technique
$query1 = 'SELECT id, no_induk, nama, alamat FROM tbl_siswa ORDER BY '.$field.' '.$lastSort.' LIMIT '.$data_content.' OFFSET '.$increment;

$result = mysql_query($query0);
if (!$result) {die('Query failed: ' . mysql_error());}

// If used Array top and bottom edge technique and use it as
// temporary buffer, and split it as top and bottom edge
$idx = 0;
while ($line = mysql_fetch_array($result, MYSQL_ASSOC)) {
$showData[$idx]['no_induk'] = $line['no_induk'];
$showData[$idx]['nama'] = $line['nama'];
$showData[$idx]['alamat'] = $line['alamat'];
$idx++;
}

$firstEdge = ($data_content * $increment) - $data_content;
$lastEdge = ($data_content * $increment) - 1;
?>

After connection code follow by query code written in php, don’t forget to close the connection and place it in a bottom of that template file like shown below:


<?
mysql_free_result($result);
mysql_close($link);
?>

Don’t forget to write JavaScript code to activate sorting and paginating trigger, then place it all the JavaScript function into template file already setup before, but please remember to place it on place already mark with red color written, and if all the html template, JavaScript and php code combine will look like shown below:


<?
$fieldId = 1;
if (isset($_REQUEST['fieldId'])) {$fieldId = $_REQUEST['fieldId'];}

$lastSort = 'asc';
if (isset($_REQUEST['sort'])) {$lastSort = $_REQUEST['sort'];}

$link = mysql_connect('localhost', 'root', 'admin');
if (!$link) {die('Could not connect: ' . mysql_error());}

$link1 = mysql_select_db('latih');
if (!$link1) {die('Could not select database');}

if ($fieldId == '1') {
$field = 'no_induk';
} else if ($fieldId == '2') {
$field = 'nama';
} else if ($fieldId == '3') {
$field = 'alamat';
} else {
$field = 'no_induk';
}

$query0 = 'SELECT id, no_induk, nama, alamat FROM tbl_siswa ORDER BY '.$field.' '.$lastSort;
$resultRow = mysql_query($query0);
$num_rows = mysql_num_rows($resultRow);

$first_pages = 1;
$data_content = 5;
$last_pages = ceil($num_rows / $data_content);

$increment = $first_pages;
if (isset($_REQUEST['increValue'])) {$increment = $_REQUEST['increValue'];}

// Start of limit offset mysql technique
$query1 = 'SELECT id, no_induk, nama, alamat FROM tbl_siswa ORDER BY '.$field.' '.$lastSort.' LIMIT '.$data_content.' OFFSET '.$increment;
$result = mysql_query($query1);
if (!$result) {die('Query failed: ' . mysql_error());}

// End of limit offset mysql technique

// Start of array top and bottom edge technique
$result = mysql_query($query0);
if (!$result) {die('Query failed: ' . mysql_error());}
$idx = 0;
while ($line = mysql_fetch_array($result, MYSQL_ASSOC)) {
$showData[$idx]['no_induk'] = $line['no_induk'];
$showData[$idx]['nama'] = $line['nama'];
$showData[$idx]['alamat'] = $line['alamat'];
$idx++;
}

$firstEdge = ($data_content * $increment) - $data_content;
$lastEdge = ($data_content * $increment) - 1;

// End of array top and bottom edge technique and use it as
// temporary buffer, and split it as top and bottom edge
?>
<html>
<head>
<title>Editable Data Grid</title>
<script type="text/javascript" language="javascript">
function sortableField(par1,par2,par3) {
if (par2 == "asc") {
var lastSort = "desc";
} else if (par2 == "desc") {
var lastSort = "asc";
} else {
var lastSort = "asc";
}
document.myForm.action = "sortable.php?fieldId="+par1+"&sort="+lastSort+"&increValue="+par3;
document.myForm.submit();
}

function prev(par1,par2,par3) {
if (parseInt(par3) != 1) {
par3 = par3 - 1;
}
document.myForm.action = "sortable.php?fieldId="+par1+"&sort="+par2+"&increValue="+par3;
document.myForm.submit();
}

function next(par1,par2,par3) {
var lastPage = parseInt('');
if (parseInt(par3) != lastPage) {
par3 = par3 + 1;
}
document.myForm.action = "sortable.php?fieldId="+par1+"&sort="+par2+"&increValue="+par3;
document.myForm.submit();
}
</script>
</head>
<body>
<form id="myForm" name="myForm" method="post">
<div class="area"><br>
<table width="80%" cellpadding="0" cellspacing="0" border="0">
<tr>
<td align="right">
<?
if ($increment == $first_pages) {
echo ' prev ';
} else { ?>
<a href="#" onclick="prev(<? echo $fieldId; ?>, '<? echo $lastSort; ?>',<? echo $increment; ?>);"> prev</a>
<?}

echo $increment." of ".$last_pages;

if ($increment == $last_pages) {
echo ' next ';
} else { ?>
<a href="#" onclick="next(<? echo $fieldId; ?>, '<? echo $lastSort; ?>',<? echo $increment; ?>);"> next</a>
<? } ?>
</td>
</tr>
<tr><td align="right"> </td></tr>
</table>
<table width="80%" cellpadding="0" cellspacing="0" border="1" >
<tr>
<th width="0%">> </th>
<th width="24%" onclick="sortableField(1, '<? echo $lastSort; ?>',<? echo $increment; ?>);">Nomor Induk</th>
<th width="24%" onclick="sortableField(2, '<? echo $lastSort; ?>',<? echo $increment; ?>);">Nama Siswa</th>
<th width="50%" onclick="sortableField(3, '<? echo $lastSort; ?>',<? echo $increment; ?>);">Alamat Lengkap</th>
</tr>

<!-- If used limit offset mysql technique -->
<? while ($line = mysql_fetch_array($result, MYSQL_ASSOC)) {?>
<tr>
<td> </td>
<td><? echo $line['no_induk']; ?></td>
<td><? echo $line['nama']; ?></td>
<td><? echo $line['alamat']; ?></td>
</tr>
<? } ?>

<!-- If used array top and bottom edge technique -->
<? for ($i = 0; $i < count($showData); $i++) {
if ($i >= $firstEdge && $i <= $lastEdge) {?>
<tr>
<td> </td>
<td><? echo $showData[$i]['no_induk']; ?></td>
<td><? echo $showData[$i]['nama']; ?></td>
<td><? echo $showData[$i]['alamat']; ?></td>
</tr>
<? }
} ?>
</table>
</div>
</form>
</body>
</html>
<?
mysql_free_result($result);
mysql_close($link);
?>

From sample code above we can see two kind paginating technique written on purpose, each of technique have some advantage and lacked, if we use offset limit technique, then advantage we’ll got light weight of data loading, because paginating mechanism already handed by database server, but have a weakness on data that show on a browser always had a same limit weather on first page till end of page, for instance if we have 23 data record with limit 10, according to paging algorithm will produce 3 page with each page show 10 record except last page only show 3 record, but this couldn’t happen if used mysql limit offset technique, last page will always show 10 record, to fulfill term of limit 10 by take several record to page before last page than show it again on last page. This thing gave the effect of this program experience some error on it (probably true or false, correct me if I’m wrong..! ^__^ ).

Whereas if used array with top and bottom edge technique, then the result we going to see on browser will accord with expected algorithm, but it sacrifice of heavy weight data loading if it reach to thousand or event million of data. This cause by all record load from database on first step then filter it in php code. From this two technique within advantage and lacked, decision to used which technique is handover to developer. This image below is shown how looks like if these codes above see on a browser:

From figure above we can see paginating trigger can execute through clicked link “prev” or “next”, when browser in condition showing first page than link “prev” will disabled, and when condition showing last page then link “next” will disabled. Whereas for “ascending” and “descending” trigger from each fields, just click table header from each field then field already clicked will automatically sort. Unnecessary “asc” or “desc” properties for this sorting process cause that properties already set switch automatically every header clicked between “asc” and “desc”.

For your record this two technique name I made myself, I’m not searching yet in google for this issue weather this name exist or not (^__^V hehe.. peace). Perhaps only this knowledge I can share to all reader for this moment, if in this article contain some mistake, please don’t mind to correct me if I done some wrong or give me some advise and comment. To improve knowledge and share it to other.


Read More...

Monday, November 17, 2008

Having Game Dynamic Tabel Row with Javascript


On a world of web programming, we used to see insert, update, delete process to data in database, and so with select query into a view process using tag table and show the data’s by using script html and view it in a browser.

And now we try to research process of “Add New Row” and “Delete Row” about tag table in web-app by using javascript, why we should use javascript? Cause if we build a web sites or web application using javascript and gain some ability to process add new row or delete row in table tag without refresh, with the result that loading effort need to communicate with server might reducible, if edit process to table tag is done, and all the data’s going insert to database is correct than communication to database server could done by once insert data.

Now start to discuss step by step to get the process done, as a basic foundation we try to build it on php, foreknown this process could written on various web programming which is php, jsp, java or even .Net, but for now we only discuss it on php. Start with a file with any name *.php to shape a first page with a table on it and a link for further action, although action link to add row nor delete row. With this script shown below:




<html>
<head>
<title>Dynamic Table, Add / Delete Row</title>
</head>
<body>
<div class="area">
<div class="toolbar-clean">
<a href="javascript:addNewRow();"><span>New Row</span></a>
<a href="javascript:deleteRow();"><span>Delete Row</span></a>
</div>
<table width="80%" cellpadding="0" cellspacing="0" border="1" id="lineItemTable">
<tr>
<th width="0%"> </th>
<th width="2%" align="center">
<input type="checkbox" name="checkMaster" id="checkMaster" onClick="clickAll();"/>
</th>
<th width="24%">Nomor Induk</th>
<th width="24%">Nama Siswa</th>
<th width="50%">Alamat Lengkap</th>
</tr>
</table>
</div>
</body>
</html>

From script shown above will produce page like shown below:

After got the page like wanted, for the next step is to add javascript code into php file. This addition is to fulfill request link action “New Row” and “Delete Row” process than insert into html script tag, first we going to write function to add new row with function name “addNewRow” with all derivative function like shown below:


function addNewRow() {
var tbl = document.getElementById("lineItemTable");
var row = tbl.insertRow(tbl.rows.length);

var td0 = document.createElement("td");
var td1 = document.createElement("td");
var td2 = document.createElement("td");
var td3 = document.createElement("td");
var td4 = document.createElement("td");

td0.appendChild(generateIndex(row.rowIndex));
td1.appendChild(generateCheckBox(row.rowIndex));
td2.appendChild(generateNomorInduk(row.rowIndex));
td3.appendChild(generateNomorRegister(row.rowIndex));
td3.appendChild(generateNamaSiswa(row.rowIndex));
td4.appendChild(generateItemName(row.rowIndex));

row.appendChild(td0);
row.appendChild(td1);
row.appendChild(td2);
row.appendChild(td3);
row.appendChild(td4);
}

function generateIndex(index) {
var idx = document.createElement("input");
idx.type = "hidden";
idx.name = "index[ ]";
idx.id = "index["+index+"]";
idx.value = index;

return idx;
}

function generateCheckBox(index) {
var check = document.createElement("input");
check.type = "checkbox";
check.name = "check[ ]";
check.id = "check["+index+"]";

return check;
}

function generateNomorInduk(index) {
var idx = document.createElement("input");
idx.type = "text";
idx.name = "nomorInduk[ ]";
idx.id = "nomorInduk["+index+"]";
idx.size = "15";

return idx;
}

function generateNomorRegister(index) {
var idx = document.createElement("input");
idx.type = "hidden";
idx.name = "nomorRegister[ ]";
idx.id = "nomorRegister["+index+"]";

return idx;
}

function generateNamaSiswa(index) {
var idx = document.createElement("input");
idx.type = "text";
idx.name = "namaSiswa[ ]";
idx.id = "namaSiswa["+index+"]";
idx.size = "25";

return idx;
}

function generateItemName(index) {
var itemName = document.createElement("input");
itemName.type = "text";
itemName.name = "alamatSiswa[ ]";
itemName.id = "alamatSiswa["+index+"]";
itemName.size = "40";

return itemName;
}

From sample javascript code like show above, we can figure out process to produce new row which going to be generated, if “New Row” link clicked, generated column composition adapt with header composition, therefore when process been executed than page browser will show like figure below, and new row will continue add to the table if “New Row” link clicked continuously.

After got result like shown above, next step had to continue is adding new function to checked all checkbox in the table, so if we want to checked all the checkbox we don’t need to check one by one at the time, with this function we can check all at a time, this function written like this code below:


function clickAll() {
var checked = false;
if (document.getElementById("checkMaster").checked == true)
checked = true;

var tbl = document.getElementById("lineItemTable");
var rowLen = tbl.rows.length;
for (var idx = 1; idx < rowLen; idx++) {
var row = tbl.rows[idx];
var cell = row.cells[1];
var node = cell.lastChild;
node.checked = checked;
}
}

After the code insert into html script tag with new function “clickAll” as a name, then checkbox element placed on header can assume working properly. And if this checkbox clicked then we can see page like shown below. We can see the different between a second figure and third figure where the checkbox element clicked and not clicked.


And final step to insert function “deleteRow” which have a duty to delete row or picked row from table if necessary, this function can also to delete all row in the table with condition if all the checkbox element checked, javascript code written like shown below.



function deleteRow() {
var tbl = document.getElementById("lineItemTable");
var error = false;

if (document.getElementById("checkMaster").checked == false)
error = true;

var tbl = document.getElementById("lineItemTable");
var rowLen = tbl.rows.length;
for (var idx = 1; idx < rowLen; idx++) {
var row = tbl.rows[idx];
var cell = row.cells[1];
var node = cell.lastChild;
if (node.checked == true) {
error = false;
break;
}
}

if (error == true) {
alert ("Checkbox tidak di cek, proses tidak dapat dilanjutkan");
return;
}

if (document.getElementById("checkMaster").checked == true) {
deleteAll();
document.getElementById("checkMaster").checked = false;
} else {
var table = document.createElement("table");
bufferRow(table);
deleteAll();
reIndex(table);
}
}

function deleteAll() {
var tbl = document.getElementById("lineItemTable");
var rowLen = tbl.rows.length - 1;
for (var idx = rowLen; idx > 0; idx--)
tbl.deleteRow(idx)
}

function bufferRow(table) {
var tbl = document.getElementById("lineItemTable");
var rowLen = tbl.rows.length;
for (var idx = 1; idx < rowLen; idx++) {
var row = tbl.rows[idx];
var cell = row.cells[1];
var node = cell.lastChild;
if (node.checked == false) {
var rowNew = table.insertRow(table.rows.length);

var td0 = document.createElement("td");
var td1 = document.createElement("td");
var td2 = document.createElement("td");
var td3 = document.createElement("td");
var td4 = document.createElement("td");

td0.appendChild(row.cells[0].lastChild);
td1.appendChild(row.cells[1].lastChild);
td2.appendChild(row.cells[2].lastChild);
td3.appendChild(row.cells[3].firstChild);
td3.appendChild(row.cells[3].lastChild);
td4.appendChild(row.cells[4].lastChild);

rowNew.appendChild(td0);
rowNew.appendChild(td1);
rowNew.appendChild(td2);
rowNew.appendChild(td3);
rowNew.appendChild(td4);
}
}
}

function reIndex(table) {
var tbl = document.getElementById("lineItemTable");
var rowLen = table.rows.length;
for (var idx=0;idx < rowLen;idx++) {
var row = table.rows[idx];
var rowTbl = tbl.insertRow(tbl.rows.length);

var td0 = document.createElement("td");
var td1 = document.createElement("td");
var td2 = document.createElement("td");
var td3 = document.createElement("td");
var td4 = document.createElement("td");

td0.appendChild(row.cells[0].lastChild);
td1.appendChild(row.cells[1].lastChild);
td2.appendChild(row.cells[2].lastChild);
td3.appendChild(row.cells[3].firstChild);
td3.appendChild(row.cells[3].lastChild);
td4.appendChild(row.cells[4].lastChild);

rowTbl.appendChild(td0);
rowTbl.appendChild(td1);
rowTbl.appendChild(td2);
rowTbl.appendChild(td3);
rowTbl.appendChild(td4);
}
}

As seen on javascript “deleteRow” function, we can figure validate process before delete command executed in line 4th until 22nd to checking neither checkbox element are checked or not, if at least just one checkbox are checked then this process can be executed, but if non of this element are checked then process will stop and continue with alert in browser like shown below:


Perhaps only this knowledge I can share to all reader for this moment, if in this article contain some mistake, please don’t mind to correct me if I done some wrong or give me some advise and comment. To improve knowledge and share it to other.


Read More...