Java

java

[Tutorial] Belajar ZKoss Yuu…

Karena kebutuhan project yang mengharuskan gw bikin aplikasi RIA yang jalan diatas browser, gw terpaksa cari-cari framework AJAX yang cepet jadinya dan bagus tampilannya. ZKoss adalah pilihan pertama gw, kebetulan background gw Java jadinya ga terlalu sulit codingin si ZKoss ini.

Disini gw akan coba bikin aplikasi CRUD sederhana banget, antara ZKoss sebagai UI-nya, MySQL sebagai databasenya dan Hibernate buat menghubungkan keduanya. IDE yg gw pakek adalah Netbeans dan Webserver gw Apache Tomcat.

Kita mulai dengan struktur database gw,
nama database “test”, nama table “person”.

CREATE TABLE person
(
        name VARCHAR(20) NOT NULL,
        gender VARCHAR(10),
        birthdate DATE,
        age INT,
        PRIMARY KEY (name)
)

insert into person (name, gender, birthdate, age) values ('Christian Gonzales', 'Male', '1988-12-24', 29);
insert into person (name, gender, birthdate, age) values ('Firman Utina', 'Male', '1977-11-20', 28);
insert into person (name, gender, birthdate, age) values ('Irfan Bachdim', 'Male', '1990-01-01', 19);
insert into person (name, gender, birthdate, age) values ('Julia Perez', 'Female', '1966-04-18', 64);

Kemudian javabean dan hibernate xml-nya.

package com.baculsoft.zk.bean;

import java.util.Date;

public class Person {
    
    private String name;
    private int age;
    private String gender;
    private Date birthdate;

    public Person(String name, int age, String gender, Date birthdate) {
        this.name = name;
        this.age = age;
        this.gender = gender;
        this.birthdate = birthdate;
    }

    public Person() {
    }    

    // other setter getter

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
  <class catalog="test" name="com.baculsoft.zk.bean.Person" table="person">
    <id name="name" type="string">
      <column length="20" name="name"/>
      <generator class="assigned"/>
    </id>
    <property name="gender" type="string">
      <column length="10" name="gender"/>
    </property>
    <property name="birthdate" type="date">
      <column length="10" name="birthdate"/>
    </property>
    <property name="age" type="java.lang.Integer">
      <column name="age"/>
    </property>
  </class>
</hibernate-mapping>

Jangan sampe lupa settingan hibernate.cfg.xml-nya yeh.

<?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>
    <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
    <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/test</property>
    <property name="hibernate.connection.username">root</property>
    <property name="hibernate.connection.password">password</property>
    <property name="hibernate.connection.autocommit">true</property>
    <property name="hibernate.show_sql">true</property>
    <mapping resource="com/baculsoft/zk/bean/Person.hbm.xml"/>
  </session-factory>
</hibernate-configuration>

abis itu gw bikin class PersonDAO buat handle transaksi ke db

package com.baculsoft.zk.dao;

import com.baculsoft.zk.bean.Person;
import java.util.List;
import org.hibernate.Session;

// disini pake hibernate util bawaan zkoss
import org.zkoss.zkplus.hibernate.HibernateUtil;

public class PersonDAO {

    public List<Person> findAll() throws Exception {
        Session session = HibernateUtil.getSessionFactory().openSession();
        return (List<Person>) session.createCriteria(Person.class).list();
    }

    public boolean delete(Person person) throws Exception {
        if (person == null) {
            throw new Exception("empty person");
        }
        Session session = HibernateUtil.getSessionFactory().openSession();
        session.delete(person);
        session.flush();
        session.close();
        return true;
    }

    public boolean insert(Person person) throws Exception {
        if (person == null) {
            throw new Exception("empty person");
        }
        Session session = HibernateUtil.getSessionFactory().openSession();
        session.save(person);
        session.flush();
        session.close();
        return true;
    }

    public boolean update(Person person) throws Exception {
        if (person == null) {
            throw new Exception("empty person");
        }
        Session session = HibernateUtil.getSessionFactory().openSession();
        session.update(person);
        session.flush();
        session.close();
        return true;
    }
}

nah, ini class Service adalah salah satu class yang paling diperlukan, coba cek baris ke 34, 43 dan 51. Itu method2 jadi semacem “listener” buat “event” yang terjadi di aplikasi.

package com.baculsoft.zk.service;

import com.baculsoft.zk.bean.Person;
import com.baculsoft.zk.dao.PersonDAO;
import java.util.List;
import org.apache.log4j.Logger;
import org.zkoss.zk.ui.util.GenericForwardComposer;

public class PersonService extends GenericForwardComposer {

    private PersonDAO dao = new PersonDAO();
    private Person person = new Person();
    
    private Logger logger = Logger.getLogger(PersonService.class);

    public Person getCurrent() {
        return person;
    }

    public void setCurrent(Person person) {
        this.person = person;
    }

    public List<Person> getAllPersons() {
        try {
            return dao.findAll();
        } catch (Exception ex) {
            logger.error(ex.getMessage(), ex);
            return null;
        }

    }

    public void onClick$add() {
        try {
            Person nowPerson = new Person(person.getName(), person.getAge(), person.getGender(), person.getBirthdate());
            dao.insert(nowPerson);
        } catch (Exception ex) {
            logger.error(ex.getMessage(), ex);
        }
    }

    public void onClick$update() {
        try {
            dao.update(person);
        } catch (Exception ex) {
            logger.error(ex.getMessage(), ex);
        }
    }

    public void onClick$delete() {
        try {
            dao.delete(person);
        } catch (Exception ex) {
            logger.error(ex.getMessage(), ex);
        }
    }
}

berikut ini adalah yang terpenting dari si aplikasi zkoss, yaitu UI-nya. Gw kasih nama “index.zul” (extension .zul bisa diganti sesuka loe di dalem web.xml). Perhatikan baris ke 34, 35 dan 36. Id-nya button harus sama dengan nama method di class PersonService. Dibaris ke 3 adalah class yang didaftarkan sebagai listener.

<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit"?>
<window id="win" width="900px" title="Person" border="normal" 
    apply="com.baculsoft.zk.service.PersonService">
    <listbox id="box" multiple="true" rows="5"
        model="@{win$composer.allPersons, load-after='add.onClick, delete.onClick, update.onClick'}"
        selectedItem="@{win$composer.current}">

        <listhead>
            <listheader label="Name" sort="auto(name)"/>
            <listheader label="Age" width="80px" sort="auto(age)" />
            <listheader label="Gender" width="170px" sort="auto(gender)" />
            <listheader label="Birthdate" width="170px" sort="auto(birthdate)" />
        </listhead>

        <listitem self="@{each='person'}" value="@{person}">
            <listcell label="@{person.name}"/>
            <listcell label="@{person.age}"/>
            <listcell label="@{person.gender}"/>
            <listcell label="@{person.birthdate}"/>
        </listitem>

    </listbox>

    <groupbox>
        <caption label="Person" />
        Name: <textbox id="name" cols="25" value="@{win$composer.current.name}" />
        Age: <intbox id="age" cols="1" value="@{win$composer.current.age}" />
        Gender: <combobox id="gender" value="@{win$composer.current.gender}">
                    <comboitem label="Male" description="Alpha Male"/>
                    <comboitem label="Female" description="Girl Power"/>
                    <comboitem label="Others" description="WTF..?!?!"/>
                </combobox>
        Birthdate: <datebox id="birthdate" cols="8" value="@{win$composer.current.birthdate}" />
        <button id="add" label="Add" height="24px"/>
        <button id="update" label="Update" height="24px"/>
        <button id="delete" label="Delete" height="24px"/>
    </groupbox>
</window>

last but not least, komponen terpenting dari aplikasi gw, yaitu web.xml.

<?xml version="1.0" encoding="UTF-8"?>

<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

    <description><![CDATA[Edw's ZK Application]]></description>
    <display-name>ZKossTest</display-name>

    <listener>
        <description>ZK listener for session cleanup</description>
        <listener-class>org.zkoss.zk.ui.http.HttpSessionListener</listener-class>
    </listener>
    <servlet>
        <description>ZK loader for ZUML pages</description>
        <servlet-name>zkLoader</servlet-name>
        <servlet-class>org.zkoss.zk.ui.http.DHtmlLayoutServlet</servlet-class>

        <init-param>
            <param-name>update-uri</param-name>
            <param-value>/zkau</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>zkLoader</servlet-name>
        <url-pattern>*.zul</url-pattern>
    </servlet-mapping>

    <servlet>
        <description>The asynchronous update engine for ZK</description>
        <servlet-name>auEngine</servlet-name>
        <servlet-class>org.zkoss.zk.au.http.DHtmlUpdateServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>auEngine</servlet-name>
        <url-pattern>/zkau/*</url-pattern>
    </servlet-mapping>

    <welcome-file-list>
        <welcome-file>index.zul</welcome-file>
    </welcome-file-list>
</web-app>

nanti kalo berhasil dijalankan akan tampil seperti ini di browser,

Berikut adalah struktur project netbeans gw, btw untuk library ZKoss dan Hibernate bisa di download dari web masing-masing.


Btw, contoh project gw bisa di download disini. Ternyata ZKoss ngga terlalu susah kan? (*)

[Tutorial] Upload File atau Image Dengan JSP

Beberapa hari terakhir di forum programmer Kaskus lagi rame pertanyaan tentang caranya upload file pakek JSP. Daripada pusing-pusing mendingan gw pake library bawaan apache, yaitu Apache Commons FileUpload.

Aplikasi sederhana ini terdiri dari 1 buah JSP sebagai presentation layer dan 1 Servlet buat handle uploading file-nya. Konsep-nya sederhana, semua file yang keupload akan disimpan didalam folder /image yang terletak 1 folder dengan file index.jsp.

Oke, langsung kita mulai kalo gitu. Ini file index.jsp gw,

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP Page</title>
    </head>
    <body>
        <h1>Hello World!</h1>
        <form action="upload" method="POST" enctype="multipart/form-data">
            Select file : <input type="file" name="fileSelect" />
            <br />
            <input type="submit" />
        </form>
    </body>
</html>

dan ini servlet buat handle upload file ataupun image,

package com.baculsoft.servlet;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

public class UploadServlet extends HttpServlet {

    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();

        // get your absolute path
        String uploadTo = getServletContext().getRealPath("/") + "image/";

        try {

            boolean isMultipart = ServletFileUpload.isMultipartContent(request);

            // no multipart form
            if (!isMultipart) {
                out.println("<html>");
                out.println("<head>");
                out.println("<title>Servlet UploadServlet</title>");
                out.println("</head>");
                out.println("<body>");
                out.println("<h1>No Multipart Files</h1>");
                out.println("</body>");
                out.println("</html>");
            }
            // multipart form
            else {
                // Create a new file upload handler
                ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());

                // parse requests
                List<FileItem> fileItems = upload.parseRequest(request);

                // Process the uploaded items
                for (FileItem fileItem : fileItems) {
                    // a regular form field
                    if (fileItem.isFormField()) {
                        
                    }
                    // upload field
                    else {
                        String fileName = fileItem.getName();
                        File fileTo = new File(uploadTo + fileName);
                        fileItem.write(fileTo);

                        out.println("<html>");
                        out.println("<head>");
                        out.println("<title>Servlet UploadServlet</title>");
                        out.println("</head>");
                        out.println("<body>");
                        out.println("<h1> success write to " + fileTo.getAbsolutePath() + "</h1>");
                        out.println("</body>");
                        out.println("</html>");

                    }
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            out.close();
        }
    }
   
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }
}

abis itu gw register servlet gw di web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <servlet>
        <servlet-name>upload</servlet-name>
        <servlet-class>com.baculsoft.servlet.UploadServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>upload</servlet-name>
        <url-pattern>/upload</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>

ini struktur project gw di Netbeans.

Nah gampang kan 😉

nb.
untuk tutorial lebih lengkapnya bisa dicek disini

How to Convert PDF Files to Images using Java

Several days ago, i met a very rare condition where i had to open pdf files on my java swing application. After spending several time brainstorming and googling i decide to convert pdf pages into jpg images and attach it to JPanel using a very neat library, pdf-renderer.

To diplay pdf files, it’s a simple as this,

package com.baculsoft.pdfviewer.main;

import com.sun.pdfview.PDFViewer;
import java.io.File;

/**
 *
 * @author edw
 * @created Dec 28, 2010, 1:23:46 PM
 * @purpose Main Frame to Display PDF files
 */
public class Main {

    private void execute() throws Exception{

        //  load a pdf from a file
        File file = new File("a.pdf");

        // display it on a JFrame
        PDFViewer pdfv = new PDFViewer(true);
        pdfv.openFile(file) ;
        pdfv.setEnabling();
        pdfv.pack();
        pdfv.setVisible(true);

    }

    public static void main(String[] args) {
        Main main = new Main();
        try {
            main.execute();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

It will show a PDF Viewer Frame like this.

But then i was thinking, if it can displays PDF pages on JPanel, can it also convert pdf pages to images? The answer is obviously yes. This is how to do it.

package com.baculsoft.pdfviewer.util;

import com.sun.pdfview.PDFFile;
import com.sun.pdfview.PDFPage;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import javax.imageio.ImageIO;

public class PDFToImageConverter {

    private void convert() throws Exception {
        
        //  load a pdf from a file
        File file = new File("a.pdf");
        RandomAccessFile raf = new RandomAccessFile(file, "r");
        ReadableByteChannel ch = Channels.newChannel(new FileInputStream(file));

        FileChannel channel = raf.getChannel();
        ByteBuffer buf = channel.map(FileChannel.MapMode.READ_ONLY,
                0, channel.size());
        PDFFile pdffile = new PDFFile(buf);

        //   get number of pages
        int jumlahhalaman = pdffile.getNumPages();

        //  iterate through the number of pages
        for (int i = 1; i <= jumlahhalaman; i++) {
            PDFPage page = pdffile.getPage(i);

            //  create new image
            Rectangle rect = new Rectangle(0, 0,
                    (int) page.getBBox().getWidth(),
                    (int) page.getBBox().getHeight());

            Image img = page.getImage(
                    rect.width, rect.height, //width & height
                    rect, // clip rect
                    null, // null for the ImageObserver
                    true, // fill background with white
                    true // block until drawing is done
                    );

            BufferedImage bufferedImage = new BufferedImage(rect.width, rect.height, BufferedImage.TYPE_INT_RGB);
            Graphics g = bufferedImage.createGraphics();
            g.drawImage(img, 0, 0, null);
            g.dispose();

            File asd = new File("bbb" + i + ".jpg");
            if (asd.exists()) {
                asd.delete();
            }
            ImageIO.write(bufferedImage, "jpg", asd);
        }
    }

    public static void main(String[] args) {
        PDFToImageConverter converter = new PDFToImageConverter();
        try {
            converter.convert();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

Before :

After :

As you can see, it will create some jpg files. The number of jpg files created depends on how many pages your PDF files have. You can also test to convert to PNG or maybe GIF file types. Just change on line 57 and 61 from “jpg” to “png” or “gif”.

This is my Netbeans 6.9 project structure

Cheers. (B)

Beginning MyBatis 3 Part 3 : How to Get Table’s Generated Ids

I have a very simple MySql table with an auto increament primary key,

CREATE TABLE sampah
(
    id INT(10) NOT NULL AUTO_INCREMENT,
    name VARCHAR(30),
    PRIMARY KEY (id)
)

my question is, how can i get my object’s generated primary key if i insert a new object to table “sampah”?

The answer is actually quite easy, as you can see here on my xml sql mapper, take a look an line 11.

<?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.SampahMapper" >

    <resultMap id="SampahMap" type="com.edw.mybatis.bean.Sampah" >
        <id column="id" property="id" jdbcType="INTEGER" />
        <result column="name" property="name" jdbcType="VARCHAR" />
    </resultMap>

    <insert id="saveUsingXML" parameterType="com.edw.mybatis.bean.Sampah"
            useGeneratedKeys="true" keyProperty="id" >
    insert into sampah(name)
    values (#{name,jdbcType=VARCHAR})
    </insert>

</mapper>

Here is my main java class, you can see how i got my generated id in line 25.

package com.edw.mybatis.main;

import com.edw.mybatis.bean.Sampah;
import com.edw.mybatis.config.MyBatisSqlSessionFactory;
import com.edw.mybatis.mapper.SampahMapper;
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 testSampah() {
        SqlSession session = MyBatisSqlSessionFactory.getSqlSessionFactory().openSession();
        try {
            SampahMapper sampahMapper = session.getMapper(SampahMapper.class);
            Sampah sampah1 = new Sampah();
            sampah1.setName("satu satu");
            sampahMapper.saveUsingXML(sampah1);           

            // my generated ID
            logger.debug(sampah1.getId());

            session.commit();
        } finally {
            session.close();
        }
    }

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

Easy isnt it? (H)

Beginning MyBatis 3 Part 2 : How to Handle One-to-Many and One-to-One Selects

One of the latest MyBatis feature is the ability to use Annotations or XML to do One-to-One or One-to-Many queries. Let’s start with an example, as usual im using PostgreSQL, Netbeans 6.9 and MyBatis 3.0.2.
First is a simple database with 2 different tables,

CREATE DATABASE test
CREATE TABLE master
    (
        nama CHARACTER VARYING(30) NOT NULL,
        usia SMALLINT,
        CONSTRAINT idnama PRIMARY KEY (nama)
    )
CREATE TABLE contoh
    (
        id INTEGER NOT NULL,
        nama CHARACTER VARYING(30),
        alamat CHARACTER VARYING(50),
        CONSTRAINT id PRIMARY KEY (id)
    )
ALTER TABLE
    contoh ADD CONSTRAINT master FOREIGN KEY (nama) REFERENCES master (nama) 
    ON DELETE CASCADE 
    ON UPDATE CASCADE

insert into master (nama, usia) values ('pepe', 17);
insert into master (nama, usia) values ('bubu', 19);

insert into contoh (id, nama, alamat) values (1, 'bubu', 'Tangerang');
insert into contoh (id, nama, alamat) values (2, 'pepe', 'Jakarta');
insert into contoh (id, nama, alamat) values (3, 'bubu', 'Singapore');
insert into contoh (id, nama, alamat) values (4, 'pepe', 'Kuburan');

My java bean, as my java object representation of my database tables,

package com.edw.bean;

import java.util.List;

public class Master {
    
    private String nama;
    private Short usia;
    private List<Contoh> contohs;

    // other setters and getters

    @Override
    public String toString() {
        return "Master{" + "nama=" + nama + " usia=" + usia + " contohs=" + contohs + '}';
    }    
}
package com.edw.bean;

public class Contoh {

    private Integer id;
    private String nama;
    private String alamat;
    private Master master;

    // other setters and getters

    @Override
    public String toString() {
        return "Contoh{" + "id=" + id + " nama=" + nama + " alamat=" + alamat + " master=" + master + '}';
    }
}

My XML files for table Contoh and Master queries, please take a look at association tags and collection tags. The association element deals with a has-one type relationship. While collection deals with a has-lots-of type relationship.

<?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.mapper.MasterMapper" >
    <!--    result maps     -->
    <resultMap id="ResultMap" type="com.edw.bean.Master" >
        <id column="nama" property="nama"  />
        <result column="usia" property="usia" />
        <!--    collections of Contoh     -->
        <collection property="contohs" ofType="com.edw.bean.Contoh" 
            column="nama" select="selectContohFromMaster" />
    </resultMap>

    <!--    one to many select  -->
    <select id="selectUsingXML" resultMap="ResultMap" parameterType="java.lang.String" >
        SELECT
            master.nama,
            master.usia
        FROM
            test.master
        WHERE master.nama = #{nama}
    </select>

    <select id="selectContohFromMaster"
          parameterType="java.lang.String"
          resultType="com.edw.bean.Contoh">
        SELECT
            id,
            nama,
            alamat
        FROM
            test.contoh
        WHERE
            nama = #{nama}
    </select>
</mapper>
<?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.mapper.ContohMapper" >
    <!--    result maps     -->
    <resultMap id="BaseResultMap" type="com.edw.bean.Contoh" >
        <id column="id" property="id" jdbcType="INTEGER" />
        <result column="nama" property="nama" jdbcType="VARCHAR" />
        <result column="alamat" property="alamat" jdbcType="VARCHAR" />

        <!--        one to one     -->
        <association property="master" column="nama" javaType="com.edw.bean.Master"
            select="selectMasterFromContoh"/>            
    </resultMap>

    <!-- one to one select  -->
    <select id="selectUsingXML" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
    SELECT
        contoh.id,
        contoh.nama,
        contoh.alamat
    FROM
        test.contoh
    WHERE
        id = #{id,jdbcType=INTEGER}
    </select>

    <select id="selectMasterFromContoh"
          parameterType="java.lang.String"
          resultType="com.edw.bean.Master">
        SELECT
            master.nama,
            master.usia
        FROM
            test.master
        WHERE
            nama = #{nama}
    </select>
</mapper>

This is my main xml configuration to handle my database connections,

<?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="org.postgresql.Driver"/>
                <property name="url" value="jdbc:postgresql://localhost:5432/test"/>
                <property name="username" value="postgres"/>
                <property name="password" value="password"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="com/edw/xml/ContohMapper.xml" />
        <mapper resource="com/edw/xml/MasterMapper.xml" />
    </mappers>
</configuration>

and a java class to load my XML files

package com.edw.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 {

    protected static final SqlSessionFactory FACTORY;

    static {
        try {
            Reader reader = Resources.getResourceAsReader("com/edw/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;
    }
}

These are my mapper interfaces, i put my annotation queries here. Please take a note at @Many and @One annotations. MyBatis use @One to map a single property value of a complex type, while @Many for mapping a collection property of a complex types.

package com.edw.mapper;

import com.edw.bean.Contoh;
import com.edw.bean.Master;
import java.util.List;

import org.apache.ibatis.annotations.Many;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;

public interface MasterMapper {

    Master selectUsingXML(String nama);   

    /*
     *  one to many Select.
     */
    @Select("SELECT master.nama, master.usia FROM test.master WHERE master.nama = #{nama}")
    @Results(value = {
                      @Result(property="nama", column="nama"),
                      @Result(property="usia", column="usia"),
                      @Result(property="contohs", javaType=List.class, column="nama", 
                             many=@Many(select="getContohs"))
                      })
    Master selectUsingAnnotations(String nama);

    @Select("SELECT contoh.id, contoh.nama, contoh.alamat FROM test.contoh WHERE contoh.nama = #{nama}")
    List<Contoh> getContohs(String nama);
}
package com.edw.mapper;

import com.edw.bean.Contoh;
import com.edw.bean.Master;
import org.apache.ibatis.annotations.One;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;

public interface ContohMapper {

    Contoh selectUsingXML(Integer nama);

    /*
     *  one to one Select.
     */
    @Select("SELECT contoh.id, contoh.nama, contoh.alamat FROM test.contoh WHERE contoh.id = #{id}")
    @Results(value = {
        @Result(property = "nama", column = "nama"),
        @Result(property = "alamat", column = "alamat"),
        @Result(property = "master", column = "nama", one=@One(select = "getMaster"))
    })
    Contoh selectUsingAnnotations(Integer id);

    @Select("SELECT master.nama, master.usia FROM test.master WHERE master.nama = #{nama}")
    Master getMaster(String nama);
}

Here is my main java class

package com.edw.main;

import com.edw.bean.Contoh;
import com.edw.bean.Master;
import com.edw.config.MyBatisSqlSessionFactory;
import com.edw.mapper.ContohMapper;
import com.edw.mapper.MasterMapper;
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 Main() {
    }

    private void execute() throws Exception{
       SqlSession session = MyBatisSqlSessionFactory.getSqlSessionFactory().openSession();
        try {
            MasterMapper masterMapper = session.getMapper(MasterMapper.class);

            // using XML queries ------------------------------
            Master master = masterMapper.selectUsingXML("pepe");
            logger.debug(master);

            List<Contoh> contohs = master.getContohs();
            for (Contoh contoh : contohs) {
                logger.debug(contoh);
            }

            // using annotation queries ------------------------------
            master = masterMapper.selectUsingAnnotations("pepe");
            logger.debug(master);

            List<Contoh> contohs2 = master.getContohs();
            for (Contoh contoh : contohs2) {
                logger.debug(contoh);
            }

            // using XML queries ------------------------------
            ContohMapper contohMapper = session.getMapper(ContohMapper.class);
            Contoh contoh = contohMapper.selectUsingXML(1);
            logger.debug(contoh.getMaster());
            
            // using annotation queries ------------------------------
            contoh = contohMapper.selectUsingAnnotations(1);
            logger.debug(contoh);

            session.commit();
        } finally {
            session.close();
        }
    }

    public static void main(String[] args) throws Exception {
        try {
            Main main = new Main();
            main.execute();
        } catch (Exception exception) {
            logger.error(exception.getMessage(), exception);
        }
    }
}

And this is what happen on my java console, im using log4j to do all the loggings.

DEBUG java.sql.Connection:27 - ooo Connection Opened
DEBUG java.sql.PreparedStatement:27 - ==>  Executing: SELECT master.nama, master.usia FROM test.master WHERE master.nama = ? 
DEBUG java.sql.PreparedStatement:27 - ==> Parameters: pepe(String)
DEBUG java.sql.ResultSet:27 - <==    Columns: nama, usia
DEBUG java.sql.ResultSet:27 - <==        Row: pepe, 17
DEBUG java.sql.PreparedStatement:27 - ==>  Executing: SELECT id, nama, alamat FROM test.contoh WHERE nama = ? 
DEBUG java.sql.PreparedStatement:27 - ==> Parameters: pepe(String)
DEBUG java.sql.ResultSet:27 - <==    Columns: id, nama, alamat
DEBUG java.sql.ResultSet:27 - <==        Row: 2, pepe, Jakarta
DEBUG java.sql.ResultSet:27 - <==        Row: 4, pepe, Kuburan
DEBUG com.edw.main.Main:32 - Master{nama=pepe usia=17 contohs=[Contoh{id=2 nama=pepe alamat=Jakarta master=null}, Contoh{id=4 nama=pepe alamat=Kuburan master=null}]}
DEBUG com.edw.main.Main:36 - Contoh{id=2 nama=pepe alamat=Jakarta master=null}
DEBUG com.edw.main.Main:36 - Contoh{id=4 nama=pepe alamat=Kuburan master=null}
DEBUG java.sql.PreparedStatement:27 - ==>  Executing: SELECT master.nama, master.usia FROM test.master WHERE master.nama = ? 
DEBUG java.sql.PreparedStatement:27 - ==> Parameters: pepe(String)
DEBUG java.sql.ResultSet:27 - <==    Columns: nama, usia
DEBUG java.sql.ResultSet:27 - <==        Row: pepe, 17
DEBUG java.sql.PreparedStatement:27 - ==>  Executing: SELECT contoh.id, contoh.nama, contoh.alamat FROM test.contoh WHERE contoh.nama = ? 
DEBUG java.sql.PreparedStatement:27 - ==> Parameters: pepe(String)
DEBUG java.sql.ResultSet:27 - <==    Columns: id, nama, alamat
DEBUG java.sql.ResultSet:27 - <==        Row: 2, pepe, Jakarta
DEBUG java.sql.ResultSet:27 - <==        Row: 4, pepe, Kuburan
DEBUG com.edw.main.Main:41 - Master{nama=pepe usia=17 contohs=[Contoh{id=2 nama=pepe alamat=Jakarta master=null}, Contoh{id=4 nama=pepe alamat=Kuburan master=null}]}
DEBUG com.edw.main.Main:45 - Contoh{id=2 nama=pepe alamat=Jakarta master=null}
DEBUG com.edw.main.Main:45 - Contoh{id=4 nama=pepe alamat=Kuburan master=null}
DEBUG java.sql.PreparedStatement:27 - ==>  Executing: SELECT contoh.id, contoh.nama, contoh.alamat FROM test.contoh WHERE id = ? 
DEBUG java.sql.PreparedStatement:27 - ==> Parameters: 1(Integer)
DEBUG java.sql.ResultSet:27 - <==    Columns: id, nama, alamat
DEBUG java.sql.ResultSet:27 - <==        Row: 1, bubu, Tangerang
DEBUG java.sql.PreparedStatement:27 - ==>  Executing: SELECT master.nama, master.usia FROM test.master WHERE nama = ? 
DEBUG java.sql.PreparedStatement:27 - ==> Parameters: bubu(String)
DEBUG java.sql.ResultSet:27 - <==    Columns: nama, usia
DEBUG java.sql.ResultSet:27 - <==        Row: bubu, 19
DEBUG com.edw.main.Main:51 - Master{nama=bubu usia=19 contohs=null}
DEBUG java.sql.PreparedStatement:27 - ==>  Executing: SELECT contoh.id, contoh.nama, contoh.alamat FROM test.contoh WHERE contoh.id = ? 
DEBUG java.sql.PreparedStatement:27 - ==> Parameters: 1(Integer)
DEBUG java.sql.ResultSet:27 - <==    Columns: id, nama, alamat
DEBUG java.sql.ResultSet:27 - <==        Row: 1, bubu, Tangerang
DEBUG java.sql.PreparedStatement:27 - ==>  Executing: SELECT master.nama, master.usia FROM test.master WHERE master.nama = ? 
DEBUG java.sql.PreparedStatement:27 - ==> Parameters: bubu(String)
DEBUG java.sql.ResultSet:27 - <==    Columns: nama, usia
DEBUG java.sql.ResultSet:27 - <==        Row: bubu, 19
DEBUG com.edw.main.Main:55 - Contoh{id=1 nama=bubu alamat=Tangerang master=Master{nama=bubu usia=19 contohs=null}}
DEBUG java.sql.Connection:27 - xxx Connection Closed

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=%-5p %c:%L - %m%n

And finally, this is my netbeans project structure

Well despite lack of documentations, im still enjoy using MyBatis. 😉