orm

Using HashMaps as MyBatis’ Parameter and Return Values

Usually im using javabean as both parameter and return values for MyBatis. But actually, MyBatis also able to use HashMaps as both parameter and return values. Here is the example,

First is a simple pom file to load all the libraries needed,

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.edw</groupId>
    <artifactId>MyBatisSelectMap</artifactId>
    <version>1.0</version>
    <packaging>jar</packaging>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
    </properties>
    
    <dependencies>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.2.2</version>
        </dependency>
    </dependencies>
</project>

And my configuration.xml file, to hold my MyBatis’ configuration

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="UNPOOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost/test"/>
                <property name="username" value="root"/>
                <property name="password" value="password"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="com/edw/mybatisselectmap/sqlmap/SelectMapper.xml" />
    </mappers>
</configuration>

An xml file, to hold all my queries, i named it SelectMapper.xml.
Please note the difference between using #{} and ${}. Hashtags sign means a prepared statement variables, while dollar sign means a simple string replace.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.edw.mybatisselectmap.mapper.SelectMapper" >    
    <select resultType="java.util.Map"  parameterType="java.util.Map" id="select" >
        SELECT
                *
        FROM
                testing 
        WERE  
                name LIKE #{myname}
        ORDER BY ${orderBy} 
    </select>    
</mapper>

A simple java file to map my xml queries,

package com.edw.mybatisselectmap.mapper;

import java.util.HashMap;
import java.util.List;

public interface SelectMapper {
    List<HashMap<Object, Object>> select(HashMap<Object, Object> hashMap);
}

and my java configuration file, to load all my MyBatis’ configurations

package com.edw.mybatisselectmap.config;

import java.io.IOException;
import java.io.Reader;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

public class MyBatisSqlSessionFactory {

    private static final SqlSessionFactory FACTORY;

    static {
        try {
            Reader reader = Resources.getResourceAsReader("com/edw/mybatisselectmap/sqlmap/Configuration.xml");
            FACTORY = new SqlSessionFactoryBuilder().build(reader);
        } catch (IOException e) {
            throw new RuntimeException("Fatal Error. Cause: " + e, e);
        }
    }

    public static SqlSessionFactory getSqlSessionFactory() {
        return FACTORY;
    }
}

And finally my main java file,

package com.edw.mybatisselectmap;

import com.edw.mybatisselectmap.config.MyBatisSqlSessionFactory;
import com.edw.mybatisselectmap.mapper.SelectMapper;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.apache.log4j.Logger;

public class Main {

    private static Logger logger = Logger.getLogger(Main.class);

    public static void main(String[] args) {
        SqlSession sqlSession = null;
        try {
            
            HashMap<Object, Object> hashMapParameter = new HashMap<Object, Object>();
            hashMapParameter.put("orderBy", "id");
            hashMapParameter.put("myname", "%edw%");
            
            sqlSession = MyBatisSqlSessionFactory.getSqlSessionFactory().openSession(true);
            SelectMapper mapper = sqlSession.getMapper(SelectMapper.class);
            
            List<HashMap<Object, Object>> hashMapResults = mapper.select(hashMapParameter);
            
            for (HashMap<Object, Object> hashMapResult : hashMapResults) {
                logger.debug(hashMapResult);
            }
        } catch (Exception e) {
            logger.error(e, e);
        } finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
        }
    }
}

You can find this post’s sourcecode at my github page here, https://github.com/edwinkun/MyBatisSelectMap.

[Book Review] Packt Publishing’s Ebook, Java Persistence with MyBatis 3

Among lots of java frameworks, MyBatis is a very popular especially because it is a database-centric-framework and it has a shallow and short learning curve, and today im trying to do a book review for it. The book that i want to review is Packt Publishing’s Java Persistence with MyBatis 3. You can see the ebook on this link, http://www.packtpub.com/java-persistence-with-mybatis-3/book.

This book’s author, K. Siva Prasad Reddy, really show the reasons of why MyBatis is very popular by providing with various code samples, from simple “down to earth” codes to a much more complicated codes, such as Spring Framework integration and Caching strategy.

These are the Table of Contents of the book,
Chapter 1: Getting started with MyBatis
Chapter 2: Bootstrapping
Chapter 3: SQL Mappers using XML
Chapter 4: SQL Mappers using Annotations
Chapter 5: Integration with Spring

So needless to say, this is the kind of ebook that i wish i had read since long time ago.

A Simple Caching Example on MyBatis using EhCache

Today i will show a simple example on how to combine ehcache caching framework with MyBatis ORM. I use Maven as my build tool, and Netbeans as my IDE.

Okay, here is my pom.xml,

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.edw.ehcache</groupId>
    <artifactId>MyBatisEhCache</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>MyBatisEhCache</name>
    <url>http://maven.apache.org</url>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.2.2</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis.caches</groupId>
            <artifactId>mybatis-ehcache</artifactId>
            <version>1.0.2</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>      
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
        <dependency>
            <groupId>net.sf.ehcache</groupId>
            <artifactId>ehcache</artifactId>
            <version>2.7.0</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.5</version>
        </dependency>     
    </dependencies>
</project>

And i create a simple mysql table,

CREATE TABLE `testing` (
  `Id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(30) NOT NULL DEFAULT '',
  `address` varchar(255) NOT NULL DEFAULT '',
  PRIMARY KEY (`Id`),
  UNIQUE KEY `ix` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=latin1;

and a simple bean and xml representation from my table,

package com.edw.mybatisehcache.bean;

import java.io.Serializable;

public class Testing implements Serializable  {

    private Integer id;
    private String name;
    private String address;

    // setter and getter

    @Override
    public String toString() {
        return "testing{" + "id=" + id + ", name=" + name + ", address=" + address + '}';
    }            
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.edw.mybatisehcache.mapper.TestingMapper" >
  
     <cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
    
    <resultMap id="Testings" type="com.edw.mybatisehcache.bean.Testing" >
        <id column="id" property="id" jdbcType="BIGINT" />
        <result column="name" property="name" jdbcType="VARCHAR" />
        <result column="address" property="address" jdbcType="VARCHAR" />
    </resultMap>  

    <select id="select" resultMap="Testings">
        select 
        *
        from testing    
    </select>   
</mapper>

An xml configuration to load my database connection,

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <environments default="development">
       <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="UNPOOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost/test"/>
                <property name="username" value="root"/>
                <property name="password" value=""/>
            </dataSource>
        </environment>          
    </environments>
     <mappers>        		
        <mapper resource="com/edw/mybatisehcache/xml/TestingMapper.xml" />  
    </mappers>              		
</configuration>

A java code to load my xml configuration,

package com.edw.mybatisehcache.config;

import java.io.Reader;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

public class MyBatisSqlSessionFactory {

    private static final SqlSessionFactory FACTORY;

    static {
        try {
            Reader reader = Resources.getResourceAsReader("com/edw/mybatisehcache/xml/Configuration.xml");
            FACTORY = new SqlSessionFactoryBuilder().build(reader);
        } catch (Exception e){
            throw new RuntimeException("Fatal Error.  Cause: " + e, e);
        }
    }

    public static SqlSessionFactory getSqlSessionFactory() {
        return FACTORY;
    }
}

A java interface to do handle queries,

package com.edw.mybatisehcache.mapper;

import com.edw.mybatisehcache.bean.Testing;
import java.util.List;

public interface TestingMapper {
    public List<Testing> select();    
}

And this is my ehcache.xml configuration,

<?xml version="1.0" encoding="UTF-8"?>
<!--
    caching configuration
-->
<ehcache>
    
    <diskStore path="F:\\cache" />
    
    <defaultCache eternal="true" maxElementsInMemory="1000"
                   overflowToDisk="true" diskPersistent="true" timeToIdleSeconds="0"
                   timeToLiveSeconds="0" memoryStoreEvictionPolicy="LRU" statistics="true" />
</ehcache>

This is my main java class, as you can see i try to do a repeated simple select queries,

package com.edw.mybatisehcache.main;

import com.edw.mybatisehcache.bean.Testing;
import com.edw.mybatisehcache.config.MyBatisSqlSessionFactory;
import com.edw.mybatisehcache.mapper.TestingMapper;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.log4j.Logger;

public class Main {

    private static Logger logger = Logger.getLogger(Main.class);

    public static void main(String[] args) {

        for (int i = 0; i < 3; i++) {
            SqlSessionFactory sqlSessionFactory = MyBatisSqlSessionFactory.getSqlSessionFactory();
            SqlSession sqlSession = sqlSessionFactory.openSession();
            TestingMapper testingMapper = sqlSession.getMapper(TestingMapper.class);

            List<Testing> testings = testingMapper.select();
            for (Testing testing : testings) {
                logger.debug(testing);
            }
            sqlSession.close();

            try {
                Thread.sleep(3000);
            } catch (Exception e) {
                logger.error(e, e);
            }
        }
    }
}

This is what is written on my netbeans’ console,

2013-07-25 15:30:10,648 [Segment] DEBUG net.sf.ehcache.store.disk.Segment:779 - fault removed 0 from heap
2013-07-25 15:30:10,648 [Segment] DEBUG net.sf.ehcache.store.disk.Segment:796 - fault added 0 on disk
2013-07-25 15:30:13,722 [Cache] DEBUG net.sf.ehcache.Cache:1970 - Cache: com.edw.mybatisehcache.mapper.TestingMapper store hit for 2026218237:1652924294:com.edw.mybatisehcache.mapper.TestingMapper.select:0:2147483647:select 
        *
        from testing
2013-07-25 15:30:13,722 [Main] DEBUG com.edw.mybatisehcache.main.Main:24 - testing{id=1, name=edw, address=Ciledug}
2013-07-25 15:30:13,722 [Main] DEBUG com.edw.mybatisehcache.main.Main:24 - testing{id=2, name=kamplenk, address=Cikokol}
2013-07-25 15:30:13,722 [Main] DEBUG com.edw.mybatisehcache.main.Main:24 - testing{id=3, name=nugie, address=Pamulang}
2013-07-25 15:30:13,722 [Main] DEBUG com.edw.mybatisehcache.main.Main:24 - testing{id=4, name=tebek, address=Karawaci}

Here is my Netbeans project structure

Have fun (K)

A Weird Hibernate Exception : org.hibernate.ObjectNotFoundException: No row with the given identifier exists

Today i met a weird hibernate exception, somehow it show that my User object does not exists. A little bit weird because i’m querying Comment tables, but the exceptions show “object user does not exist”.

	A Weird Hibernate Error : org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [com.edw.entity.User#anonymousUser]
    org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [com.edw.entity.User#anonymousUser]
	at org.hibernate.impl.SessionFactoryImpl$1.handleEntityNotFound(SessionFactoryImpl.java:377)
	at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:145)
	at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:195)
	at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:103)
	at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:878)
	at org.hibernate.impl.SessionImpl.internalLoad(SessionImpl.java:846)
	at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:557)
	at org.hibernate.type.EntityType.resolve(EntityType.java:379)
	at org.hibernate.engine.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:120)

After some minutes digging on my sourcecode, i found out that javabean Comment has a @ManyToOne (Hibernate annotation for many to one relationship) to javabean User. Too bad one Comment object, still has a foreign key to a deleted User object.

This is my previous User class and Comment class, the main culprit is on line 30.

package com.edw.entity;

import java.io.Serializable;
import java.util.Date;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import org.hibernate.annotations.NotFound;
import org.hibernate.annotations.NotFoundAction;

@Entity
@Table(name="tbl_comment")
public class Comment implements Serializable {

	@Id
	@GeneratedValue
	private Long id;
	
	@Temporal(TemporalType.TIMESTAMP)
	private Date timestamp;
	
	private String content;
		
	@ManyToOne
	private User user;
		
	@ManyToOne
	private News news;

	public Long getId() {
		return id;
	}
	// other setter and getter
}
package com.edw.entity;

import java.io.Serializable;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="tbl_user")
public class User implements Serializable {

	@Id
    private String username;
    private String password;
    private Boolean status;
    
    private String email;
    private String name;
    private String address;
    private String city;
    private String job;
    private String about;
    private String relationship;
    private String privacy;
    
    private String role;
    
    private String tokenRegistration;
    private String tokenForgotPassword;
    
    public User() {}
    public User(String username) {
    	this.username = username;
    }   	
}

The workaround is by adding @NotFound annotation to ignore the condition when Hibernate unable to find the User class.

package com.edw.entity;

import java.io.Serializable;
import java.util.Date;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import org.hibernate.annotations.NotFound;
import org.hibernate.annotations.NotFoundAction;

@Entity
@Table(name="tbl_comment")
public class Comment implements Serializable {

	@Id
	@GeneratedValue
	private Long id;
	
	@Temporal(TemporalType.TIMESTAMP)
	private Date timestamp;
	
	private String content;
	
	@NotFound(action=NotFoundAction.IGNORE)
	@ManyToOne
	private User user;
	
	@NotFound(action=NotFoundAction.IGNORE)
	@ManyToOne
	private News news;

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

Hope it helped others, have fun 😉

Beginning MyBatis 3

MyBatis framework is a complete rewrite of iBatis, it’s a data mapper framework that makes it easier to use a relational database with object-oriented applications. The difference from old iBatis is that now everything can now be written in java, from queries, configuration to mappers.

Some people might ask why MyBatis use a different approach from its ancestor, iBatis? iBatis’ code generator use *DAOs while MyBatis use *Mappers. I think they all the same, but then according to Clinton Begin they are, despite their similarity, are not exact in concepts.

DAOs can collect multiple statements and thus aggregate or cohesive data logic into one method. That said, this isn’t necessarily a good thing. After 10 years of writing DAOs, I can say with enough experience that DAOs are a waste of time. They fragment business logic, they’re extra code and the abstraction goes largely unused for the lifetime of most applications that implement it. DAOs were often implemented incorrectly and code would sneak into them that should not.

Mappers on the other hand, are named function that executes a single SQL statement or procedure. There is no extra code, and it eliminates strings in the execution of mapped statements. Mappers also help define the mapped statement.

In a sense, you can also think of it as:

  • DAOs USE mapped statements.
  • Mapper methods ARE mapped statements.

The cohesive grouping or aggregation of related statements that work together to form a business process should now exist in your service layer (be it a Spring bean, or an EJB or a POJO service layer).

Okay enough with the chit-chat, let me show you the code, first as always, a simple mysql database named test, and a table named Contoh.

CREATE TABLE contoh
(
    nama VARCHAR(30) NOT NULL,
    alamat VARCHAR(100),
    PRIMARY KEY (nama)
)

and a java bean

package com.edw.mybatis.bean;

public class Contoh {
    private String nama;
    private String alamat;

    // other setter and getter

    @Override
    public String toString(){
        return nama+" : "+alamat;
    }
}

This is my Contoh table queries, i named it ContohMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.edw.mybatis.mapper.ContohMapper" >
    
  <resultMap id="ContohMap" type="com.edw.mybatis.bean.Contoh" >
    <id column="nama" property="nama" jdbcType="VARCHAR" />
    <result column="alamat" property="alamat" jdbcType="VARCHAR" />
  </resultMap>

  <insert id="save" parameterType="com.edw.mybatis.bean.Contoh" >
    insert into contoh (nama, alamat)
    values (#{nama,jdbcType=VARCHAR}, #{alamat,jdbcType=VARCHAR})
  </insert>

  <update id="update" parameterType="com.edw.mybatis.bean.Contoh" >
    update contoh
    set alamat = #{alamat,jdbcType=VARCHAR}
    where nama = #{nama,jdbcType=VARCHAR}
  </update>

</mapper>

I register my ContohMapper.xml on Configuration.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="UNPOOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost/test"/>
                <property name="username" value="root"/>
                <property name="password" value="xxx"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="com/edw/mybatis/xml/ContohMapper.xml"/>
    </mappers>
</configuration>

What makes MyBatis different from iBatis, is the ability to put queries on interfaces using annotations. Here is the example.

package com.edw.mybatis.mapper;

import com.edw.mybatis.bean.Contoh;
import java.util.List;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Select;

public interface ContohMapper {    
    int save(Contoh contoh);

    @Delete("DELETE FROM contoh WHERE nama = #{nama}")
    int delete(String nama);

    @Select("SELECT * FROM contoh WHERE nama = #{nama}")
    Contoh select(String nama);

    @Select("SELECT * FROM contoh")
    List<Contoh> selectAll();
}

and a factory class to load my configuration

package com.edw.mybatis.config;

import java.io.Reader;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;


/**
 *
 * @author edw
 */
public class MyBatisSqlSessionFactory {

    protected static final SqlSessionFactory FACTORY;

    static {
        try {
            Reader reader = Resources.getResourceAsReader("com/edw/mybatis/xml/Configuration.xml");
            FACTORY = new SqlSessionFactoryBuilder().build(reader);
        } catch (Exception e){
            throw new RuntimeException("Fatal Error.  Cause: " + e, e);
        }
    }

    public static SqlSessionFactory getSqlSessionFactory() {
        return FACTORY;
    }
}

And here’s my main class

package com.edw.mybatis.main;

import com.edw.mybatis.bean.Contoh;
import com.edw.mybatis.config.MyBatisSqlSessionFactory;
import com.edw.mybatis.mapper.ContohMapper;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.apache.log4j.Logger;

public class Main {

    private Logger logger = Logger.getLogger(Main.class);

    public Main() {
    }

    private void execute() {
        SqlSession session = MyBatisSqlSessionFactory.getSqlSessionFactory().openSession();
        try {
            // select all
            ContohMapper mapper = session.getMapper(ContohMapper.class);
            List<Contoh> contohs = mapper.selectAll();
            for (Contoh contoh1 : contohs) {
                logger.debug(contoh1);
            }

            // delete
            int success = mapper.delete("pepe");
            if (success == 0) {
                logger.debug("failed to delete");
            } else {
                logger.debug("successfully deleted");
            }

            // insert
            Contoh contohExample = new Contoh();
            contohExample.setNama("kacrut");
            contohExample.setAlamat("kacrut alamat");
            int insertSuccess = session.insert("save", contohExample);
            if (insertSuccess == 0) {
                logger.debug("failed to insert");
            } else {
                logger.debug("successfully inserted");
            }

            // check is it inserted yet
            Contoh contoh = (Contoh) mapper.select(contohExample.getNama());
            logger.debug(contoh);

            // update
            Contoh contohExample2 = new Contoh();
            contohExample2.setNama("kacrut");
            contohExample2.setAlamat("kacrut alamat 22");
            int updateSuccess = session.update("com.edw.mybatis.mapper.ContohMapper.update", contohExample2);
            if (updateSuccess == 0) {
                logger.debug("failed to update");
            } else {
                logger.debug("successfully updated");
            }

            session.commit();
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            session.close();
        }
    }

    public static void main(String[] args) {
        Main main = new Main();
        main.execute();
    }
}

this is what happen when i run my project,

run:
2010-11-12 15:40:41,804 - DEBUG java.sql.Connection:27 - ooo Connection Opened
2010-11-12 15:40:42,041 - DEBUG java.sql.PreparedStatement:27 - ==>  Executing: SELECT * FROM contoh 
2010-11-12 15:40:42,041 - DEBUG java.sql.PreparedStatement:27 - ==> Parameters: 
2010-11-12 15:40:42,100 - DEBUG java.sql.ResultSet:27 - <==    Columns: nama, alamat
2010-11-12 15:40:42,101 - DEBUG java.sql.ResultSet:27 - <==        Row: edwin, singapore
2010-11-12 15:40:42,103 - DEBUG java.sql.ResultSet:27 - <==        Row: kamplenk, ciledug
2010-11-12 15:40:42,104 - DEBUG java.sql.ResultSet:27 - <==        Row: nugie, pamulang
2010-11-12 15:40:42,105 - DEBUG java.sql.ResultSet:27 - <==        Row: samsu, dago
2010-11-12 15:40:42,120 - DEBUG java.sql.ResultSet:27 - <==        Row: tebek, jayapura
2010-11-12 15:40:42,122 - DEBUG com.edw.mybatis.main.Main:24 - edwin : singapore
2010-11-12 15:40:42,122 - DEBUG com.edw.mybatis.main.Main:24 - kamplenk : ciledug
2010-11-12 15:40:42,123 - DEBUG com.edw.mybatis.main.Main:24 - nugie : pamulang
2010-11-12 15:40:42,123 - DEBUG com.edw.mybatis.main.Main:24 - samsu : dago
2010-11-12 15:40:42,123 - DEBUG com.edw.mybatis.main.Main:24 - tebek : jayapura
2010-11-12 15:40:42,133 - DEBUG java.sql.PreparedStatement:27 - ==>  Executing: DELETE FROM contoh WHERE nama = ? 
2010-11-12 15:40:42,134 - DEBUG java.sql.PreparedStatement:27 - ==> Parameters: pepe(String)
2010-11-12 15:40:42,136 - DEBUG com.edw.mybatis.main.Main:30 - failed to delete
2010-11-12 15:40:42,137 - DEBUG java.sql.PreparedStatement:27 - ==>  Executing: insert into contoh (nama, alamat) values (?, ?) 
2010-11-12 15:40:42,138 - DEBUG java.sql.PreparedStatement:27 - ==> Parameters: kacrut(String), kacrut alamat(String)
2010-11-12 15:40:42,159 - DEBUG com.edw.mybatis.main.Main:43 - successfully inserted
2010-11-12 15:40:42,160 - DEBUG java.sql.PreparedStatement:27 - ==>  Executing: SELECT * FROM contoh WHERE nama = ? 
2010-11-12 15:40:42,160 - DEBUG java.sql.PreparedStatement:27 - ==> Parameters: kacrut(String)
2010-11-12 15:40:42,163 - DEBUG java.sql.ResultSet:27 - <==    Columns: nama, alamat
2010-11-12 15:40:42,163 - DEBUG java.sql.ResultSet:27 - <==        Row: kacrut, kacrut alamat
2010-11-12 15:40:42,164 - DEBUG com.edw.mybatis.main.Main:48 - kacrut : kacrut alamat
2010-11-12 15:40:42,166 - DEBUG java.sql.PreparedStatement:27 - ==>  Executing: update contoh set alamat = ? where nama = ? 
2010-11-12 15:40:42,166 - DEBUG java.sql.PreparedStatement:27 - ==> Parameters: kacrut alamat 22(String), kacrut(String)
2010-11-12 15:40:42,202 - DEBUG com.edw.mybatis.main.Main:58 - successfully updated
2010-11-12 15:40:42,259 - DEBUG java.sql.Connection:27 - xxx Connection Closed
BUILD SUCCESSFUL (total time: 2 seconds)

this is my Netbeans 6.9 project structure

Again, another great framework that i’ll obviously use. Cheers, :-[

ps.
i almost forget, here is my log4j.properties.

# Global logging configuration
log4j.rootLogger=DEBUG,stdout

# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d - %-5p %c:%L - %m%n