Võ Văn Hải's blog

Chỉ có một điều tuyệt đối đó là mọi thứ đều tương đối…

JTable với các thao tác CRUD trên cơ sở dữ liệu

Nhiều bạn đã từng lập trình trên môi trường .net sau đó chuyển sang Java sẽ rất lo sợ khi trên Java không có một components để hiển thị dữ liệu, cập nhật,…tóm lại là các thao tác CRUD(Create, Read, Update, Delete) như DataGrid/DataGridView. Tuy nhiên, nếu bạn là người chịu khó, bạn có thể dùng JTable thay cho component bạn mong ước bên .net. Java cung cấp cho bạn các cơ chế làm việc hay ho và bạn phải làm việc, suy nghĩ để có cái bạn muốn. Khi bạn OK mọi thứ, bạn còn có thể có cái hay hơn mong đợi của bạn.
Trong nỗ lực cho những người hoài tưởng .Net, tôi viết 1 chương trình gần như 1 DataGrid ở mức độ người học cơ bản cũng có thể nắm bắt. Ngoài ra cũng trả lời cho một số bạn hay email đến hỏi vấn đề này.
Giao diên sơ khởi như sau:
https://vovanhai.files.wordpress.com/2011/03/mydatagridview.png
Giả sử ta giải quyết bài toán trên 1 bảng có cấu trúc Lophoc(msLop,tenLop,tenGVCN)
Thông tin lớp học được biểu diễn thành class sau:

package vovanhai.wordpress.com;

public class Lophoc {
	private String msLop;
	private String tenLop;
	private String tenGVCN;
	public String getMsLop() {
		return msLop;
	}
	public void setMsLop(String msLop) {
		this.msLop = msLop;
	}
	public String getTenLop() {
		return tenLop;
	}
	public void setTenLop(String tenLop) {
		this.tenLop = tenLop;
	}
	public String getTenGVCN() {
		return tenGVCN;
	}
	public void setTenGVCN(String tenGVCN) {
		this.tenGVCN = tenGVCN;
	}
	public Lophoc() {
		super();
	}
	public Lophoc(String msLop, String tenLop, String tenGVCN) {
		super();
		this.msLop = msLop;
		this.tenLop = tenLop;
		this.tenGVCN = tenGVCN;
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((msLop == null) ? 0 : msLop.hashCode());
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Lophoc other = (Lophoc) obj;
		if (msLop == null) {
			if (other.msLop != null)
				return false;
		} else if (!msLop.equals(other.msLop))
			return false;
		return true;
	}

	@Override
	public String toString() {
		return this.tenLop;
	}
}

Các phương thức làm việc trên database:

package vovanhai.wordpress.com;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;

public class UpdateAction {
	private Connection con;
	/**
	 * Khởi gán connection. Ở đây giả sử dùng DB là MS SQL server
	 * --Nhớ thêm driver--
	 * @throws Exception
	 */
	public UpdateAction() throws Exception{
		Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
		String url="jdbc:sqlserver://localhost:1433;databaseName=GC0563";
		con=DriverManager.getConnection(url,"sa","");
	}
	/**
	 * Lấy tất cả các dòng trong bảng Lớp học bỏ vào ArrayList để hiển
	 * thị lên JTable
	 * @return danh sách các lớp
	 */
	public ArrayList<Lophoc>getAllRows()throws Exception{
		ArrayList<Lophoc> lst=new ArrayList<Lophoc>();
		String sql="select * from lophoc";
		ResultSet rs=con.createStatement().executeQuery(sql);
		Lophoc lh=null;
		while(rs.next()){
			lh=new Lophoc(rs.getString("msLop"),
					rs.getString("tenLop"),
					rs.getString("tenGVCN"));
			lst.add(lh);
		}
		return lst;
	}
	/**
	 * Lấy lớp học khi biết mã số lớp
	 * @param id
	 * @return
	 * @throws Exception
	 */
	public Lophoc getLophocByID(String id)throws Exception{
		Lophoc lh=null;
		String sql="select * from Lophoc where msLop=?";
		PreparedStatement ps=con.prepareStatement(sql);
		ps.setString(1, id);
		ResultSet rs=ps.executeQuery();
		if(rs.next()){
			lh=new Lophoc(rs.getString("msLop"),
					rs.getString("tenLop"),
					rs.getString("tenGVCN"));
		}
		return lh;
	}
	/**
	 * Cập nhật thông tin lớp học
	 * @param newlh
	 * @return
	 * @throws Exception
	 */
	public boolean UpdateLop(Lophoc newlh) throws Exception{
		String sql="Update Lophoc set tenLop=?, tenGVCN=? where msLop=?";
		PreparedStatement pstmt=con.prepareStatement(sql);
		pstmt.setString(1, newlh.getTenLop());
		pstmt.setString(2, newlh.getTenGVCN());
		pstmt.setString(3, newlh.getMsLop());
		return pstmt.executeUpdate()>0;
	}
	/**
	 * Thêm lớp học mới
	 * @param newlh
	 * @return
	 * @throws Exception
	 */
	public boolean AddNewLophoc(Lophoc newlh)throws Exception {
		String sql="Insert lophoc values(?,?,?)";
		PreparedStatement pstmt=con.prepareStatement(sql);
		pstmt.setString(1, newlh.getMsLop());
		pstmt.setString(2, newlh.getTenLop());
		pstmt.setString(3, newlh.getTenGVCN());
		return pstmt.executeUpdate()>0;
	}
	/**
	 * Xóa lớp học khỏi danh sách
	 * @param id
	 * @return
	 * @throws Exception
	 */
	public boolean DeleteLophocByID(String id)throws Exception{
		String sql="delete Lophoc where msLop=?";
		PreparedStatement pstmt=con.prepareStatement(sql);
		pstmt.setString(1,id);
		return pstmt.executeUpdate()>0;
	}
}

Giao diện chương trình:

package vovanhai.wordpress.com;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JToolBar;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableModel;

public class JTableWithDbCRUD extends JFrame implements ActionListener{
	private JToolBar toolbar;
	private JButton btnF,btnP,btnN,btnL,btnAdd,btnSave,btnDelete;
	private DefaultTableModel dtm;
	private JTable table;
	private UpdateAction action;
	private JLabel statusBar;

	private ArrayList<Lophoc> lst;
	private int curPos=0;//vị trí hiện tại của dòng trên lưới
	private JLabel lblPos;
	private int NoExistRecords=0;//Giữ số mẫu tin cũ
	public JTableWithDbCRUD() throws Exception{
		setTitle("MyDataGridViewDemo");
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setSize(600,400);
		this.add(statusBar=new JLabel("ready..."),BorderLayout.SOUTH);
		createToolbar();

		action=new UpdateAction();
		lst=action.getAllRows();

		String []title={"Mã số lớp","Tên lớp","Tên GVCN"};
		dtm=new DefaultTableModel(title,0){
			public boolean isCellEditable(int row, int column) {
				if(column==0&&(row>=0&&row<lst.size()))
					return false;
				return true;
			};
		};
		table=new JTable(dtm);
		table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);//cho chọn 1 dòng
		table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
			@Override
			public void valueChanged(ListSelectionEvent e) {
				curPos=table.getSelectedRow();
				lblPos.setText((curPos+1)+"/"+dtm.getRowCount());
			}
		});
		this.add(new JScrollPane(table));
		FillData(lst);//điền dữ liệu lên JTable
		table.setRowSelectionInterval(curPos, curPos);
	}
	/**
	 * Điền dữ liệu từ bảng lên JTable
	 */
	private void FillData(ArrayList<Lophoc> lst){
		try {
			for(Lophoc lh:lst){
				String []row={lh.getMsLop(),lh.getTenLop(),lh.getTenGVCN()};
				dtm.addRow(row);
			}
			NoExistRecords=lst.size();//Số mẫu tin cũ
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void createToolbar(){
		this.add(toolbar=new JToolBar(),BorderLayout.NORTH);
		toolbar.add(btnF=new JButton(new ImageIcon("images/MoveFirstHS.png")));
		toolbar.add(btnP=new JButton(new ImageIcon("images/MovePreviousHS.png")));
		toolbar.add(lblPos=new JLabel());
		toolbar.add(btnN=new JButton(new ImageIcon("images/MoveNextHS.png")));
		toolbar.add(btnL=new JButton(new ImageIcon("images/MoveLastHS.png")));
		toolbar.add(new JToolBar.Separator());
		toolbar.add(btnAdd=new JButton(new ImageIcon("images/NewDocumentHS.png")));
		toolbar.add(btnSave=new JButton(new ImageIcon("images/SaveAllHS.png")));
		toolbar.add(btnDelete=new JButton(new ImageIcon("images/deleteHS.png")));
		btnAdd.addActionListener(this);btnSave.addActionListener(this);
		btnDelete.addActionListener(this);btnF.addActionListener(this);
		btnP.addActionListener(this);btnN.addActionListener(this);
		btnL.addActionListener(this);
		btnAdd.setToolTipText("Insert new row");
		btnSave.setToolTipText("Update data to database");
		btnDelete.setToolTipText("Delete selection row");
	}

	//Thực thi chương trình
	public static void main(String[] args)throws Exception {
		new JTableWithDbCRUD().setVisible(true);
	}
	@Override
	public void actionPerformed(ActionEvent e) {
		Object o=e.getSource();
		if(o.equals(btnAdd)){
			String []row={"","",""};
			dtm.addRow(row);
			//dtm.setRowCount(dtm.getRowCount()+1);
		}
		else if(o.equals(btnDelete)){
			try{
				int selrow=table.getSelectedRow();
				String id=dtm.getValueAt(selrow, 0).toString();
				if(id.trim().equals("")){
					dtm.removeRow(selrow);
					statusBar.setText("delete row completed");
				}
				else if(action.DeleteLophocByID(id)){
					dtm.removeRow(selrow);
					statusBar.setText("delete row completed");
				}
				else
					statusBar.setText("delete row failed");
			}
			catch (Exception e2) {
				JOptionPane.showMessageDialog(null,
						"Select Row before using this command","Error",
						JOptionPane.ERROR_MESSAGE);
			}
		}
		else if(o.equals(btnSave)){
			try {
				xulycapnhat();
			} catch (Exception e1) {
				e1.printStackTrace();
			}
		}
		else{
			XuLyCacNutDichuyen(e);
		}
	}
	/**
	 * 1.Duyệt qua từng dòng trong JTable<br/>
	 * 2.Lấy giá trị ID của mỗi dòng<br/>
	 * 3.Kiểm tra ID này trong cơ sở dữ liệu<br/>
	 * 	<ul>
	 * 	<li>Nếu có
	 * 		<ul>
	 * 		<li>Kiểm tra các cột còn lại có thay đổi gì không
	 * 			<ul>
	 * 			<li>Nếu có thì tiến hành cập nhật
	 * 			<li>Ngược lại thì bỏ qua
	 * 			</ul>
	 * 		</ul>
	 * 	<li>Nếu không thì tiến hành thêm 1 mẫu tin mới
	 *  </ul>
	 *  Chưa xử lý được vấn đề sửa giá trị id thì xóa record cũ thêm record mới
	 */
	private void xulycapnhat() throws Exception{
		int rows=dtm.getRowCount();
		//int cols=dtm.getColumnCount();

		for (int i = 0; i < rows; i++) {
			String ms=dtm.getValueAt(i, 0).toString();
			String tenlop=dtm.getValueAt(i, 1).toString();
			String gvcn=dtm.getValueAt(i, 2).toString();
			Lophoc newlh=new Lophoc(ms,tenlop,gvcn);

			//nếu i<so mau tin cu thì chỉ cho cập nhật
			if(i<NoExistRecords){
				Lophoc lh=action.getLophocByID(ms);
				if(!lh.getTenLop().equalsIgnoreCase(tenlop)
						|| !lh.getTenGVCN().equalsIgnoreCase(gvcn)){
					action.UpdateLop(newlh);
				}
			}
			else{//Những dòng mới thêm
				//dòng không có msLop thì bỏ qua
				if(ms.trim().equals(""))continue;

				Lophoc lh=action.getLophocByID(ms);
				if(lh!=null){//mẫu tin thêm vào trùng ID
					if(!lh.getTenLop().equalsIgnoreCase(tenlop)
							|| !lh.getTenGVCN().equalsIgnoreCase(gvcn)){
						action.UpdateLop(newlh);
					}
				}
				else{//Mẫu tin mới
					action.AddNewLophoc(newlh);
				}
			}

			/*String ms=dtm.getValueAt(i, 0).toString();
			String tenlop=dtm.getValueAt(i, 1).toString();
			String gvcn=dtm.getValueAt(i, 2).toString();
			Lophoc newlh=new Lophoc(ms,tenlop,gvcn);
			Lophoc lh=action.getLophocByID(ms);
			//dòng không có msLop thì bỏ qua
			if(ms.trim().equals(""))continue;
			if(lh!=null){//mẫu tin cũ
				if(!lh.getTenLop().equalsIgnoreCase(tenlop)
						|| !lh.getTenGVCN().equalsIgnoreCase(gvcn)){
					action.UpdateLop(newlh);
				}
			}
			else{//Mẫu tin mới
				action.AddNewLophoc(newlh);
			}*/
		}
		statusBar.setText("Update completed");
	}

	private void XuLyCacNutDichuyen(ActionEvent e) {
		Object o=e.getSource();
		if(o.equals(btnF)){
			curPos=0;
		}
		else if(o.equals(btnP)){
			if(curPos>0) curPos--;
		}
		else if(o.equals(btnN)){
			if(curPos<dtm.getRowCount()-1) curPos++;
		}
		else if(o.equals(btnL)){
			curPos=dtm.getRowCount()-1;
		}
		table.setRowSelectionInterval(curPos, curPos);
	}
}

7 Responses to “JTable với các thao tác CRUD trên cơ sở dữ liệu”

  1. thanhvt said

    E có một thắc mắc là nếu em có một bảng tên là TenantDetails và có 13 trường nhưng số lượng người(row) thì có thể tăng thêm nhiều.Vậy đoạn code sau:

    if(i<NoExistRecords){
    Lophoc lh=action.getLophocByID(ms); if(!lh.getTenLop().equalsIgnoreCase(tenlop) || !lh.getTenGVCN().equalsIgnoreCase(gvcn)){
    action.UpdateLop(newlh);
    }
    }
    thì phải sửa như thế nào.
    Nếu một bảng luôn được cập nhật thường xuyên thì việc phải lấy ra từng ấy người là rất mất thời gian.E nghĩ k thể lặp lại việc đó được.Hãy giúp em có thể hiểu rõ vấn đề này hơn.

    Ngoài ra e còn chưa hiểu chỗ này:for(Lophoc lh:lst)

  2. vantuan said

    thanks, bài viết rất hay của bạn, mình copy nhé,hìhif

  3. Cao Trung Kiên said

    Chào thầy a !
    Em muốn xóa tất cả dữ liệu trong bảng thì em cần dùng câu lệnh gì ạ. Thầy giúp em với.
    Em cảm ơn thầy .

  4. Võ Văn Hải said

    dùng câu lệnh sql:

    delete from tên_bảng
    
  5. Thảo said

    Chào thầy, cho em hỏi có cách nào khi mình run chương trình lên thì mặc định dòng được chọn trong JTable là dòng đầu tiên không? Hoặc là dòng khác cũng được nhưng khi run lên thì có 1 dòng được chọn?

  6. Nguyễn Hậu said

    chào Thầy, cảm ơn thầy đã dành thời gian chia sẻ cho mọi người. E có 1 thắc mắc mong thầy có thể giúp e. E có 1 JTable, e đã load dữ liệu để hiển thị lên đó thành công, nhưng e không biết thế nào để khi e cho người dùng tác động dữ liệu (thêm, xóa, sửa) thì bảng JTable có thể tự load lại để hiện thị ạ.

  7. Phu Le said

    chào thầy, thầy cho em hỏi: e có một jtable có 5 cột và có các textField tương ứng với các trường trong bảng. e muốn lấy dữ liệu từ jtable để đưa lên các textField thì e dùng sự kiện gì? và load lên như thế nào? thầy giúp e với. e cám ơn

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: