先看完http://blog.csdn.net/yunji3344/article/details/8789876这里。本文是基于上面一篇文章的修改。
修改以下几个java文件
News.java
package org.extbook.pojo;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "News")
public class News implements Serializable {
private static final long serialVersionUID = 6313339878536761197L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(nullable = false, unique = true)
private Integer id;
@Column(length = 100)
private String name;
@Column(length = 10000)
private String content;
@Column(length = 1000)
private String remark;
@Column
private Date createTime;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
}
EntityDao.java
package org.extbook.dao;
import java.io.Serializable;
import java.util.List;
public interface EntityDao<T extends Serializable> {
public List<T> findBySql(String queryString, Class<?> clazz,
Object[] values, Object[][] scalar, int start, int limit);
public T save(final T model);
public void update(final T model);
public T get(final Class<T> entityClass,final Serializable id);
public void delete(final T model);
}
EntityDaoImpl.java
package org.extbook.dao;
import java.io.Serializable;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.SessionFactory;
import org.hibernate.transform.Transformers;
import org.springframework.stereotype.Repository;
@Repository
public class EntityDaoImpl<T extends Serializable> implements EntityDao<T>{
private SessionFactory sessionFactory;
public EntityDaoImpl(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public EntityDaoImpl() {
}
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
@Override
public List<T> findBySql(String queryString, Class<?> clazz, Object[] values, Object[][] scalar, int start, int limit) {
SQLQuery sqlQuery = getSessionFactory().getCurrentSession().createSQLQuery(queryString);
if (scalar != null) {
for (Object[] element : scalar) {
sqlQuery.addScalar((String) element[0], (org.hibernate.type.Type) element[1]);
}
}
if (clazz != null) {
sqlQuery.setResultTransformer(Transformers.aliasToBean(clazz));
}
if (values != null) {
for (int i = 0; i < values.length; i++) {
sqlQuery.setParameter(i, values[i]);
}
}
Query query = sqlQuery;
query.setFirstResult(start).setMaxResults(limit);
@SuppressWarnings("unchecked")
List<T> list = query.list();
return list;
}
@Override
public T save(T model) {
getSessionFactory().getCurrentSession().save(model);
return model;
}
@Override
public void update(T model) {
getSessionFactory().getCurrentSession().update(model);
}
@Override
public void delete(T model) {
getSessionFactory().getCurrentSession().delete(model);
}
@SuppressWarnings("unchecked")
@Override
public T get(final Class<T> entityClass,final Serializable id) {
T t = (T) getSessionFactory().getCurrentSession().get(entityClass, id);
return t;
}
}
NewsService.java
package org.extbook.service;
import java.util.Date;
import java.util.List;
import javax.annotation.Resource;
import org.extbook.dao.EntityDao;
import org.extbook.dao.EntityDaoImpl;
import org.extbook.pojo.News;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class NewsService {
@Resource
private EntityDao<News> entityDao;
@Autowired
public void setSessionFactory(SessionFactory sessionFactory) {
entityDao = new EntityDaoImpl<News>(sessionFactory);
}
@Transactional
public List<News> getList(Integer start, Integer limit){
//asc desc
String sql = "select * from News order by id asc";
List<News> list = null;
if(start==null||limit==null){
list = entityDao.findBySql(sql, News.class, null, null, 0, Integer.MAX_VALUE);
}else{
list = entityDao.findBySql(sql, News.class, null, null, start, limit);
}
return list;
}
public void save(String name,String content){
News news = new News();
news.setName(name);
news.setContent(content);
news.setCreateTime(new Date());
entityDao.save(news);
}
public void update(Integer id,String name,String content){
News news = entityDao.get(News.class, id);
news.setName(name);
news.setContent(content);
entityDao.update(news);
}
public void delete(News news){
entityDao.delete(news);
}
public boolean deleteById(Integer id){
News news = entityDao.get(News.class, id);
if(news != null){
entityDao.delete(news);
}
return true;
}
public int getTotalCount() {
String sql = "select * from News";
List<News> list = entityDao.findBySql(sql, News.class, null, null, 0, Integer.MAX_VALUE);
int totalCount = list==null?0:list.size();
return totalCount;
}
}
NewsController.java
package org.extbook.controller;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.extbook.pojo.News;
import org.extbook.service.NewsService;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping(value="/NewsController")
public class NewsController {
protected final transient Log log = LogFactory.getLog(NewsController.class);
@Resource
private NewsService newsService;
@RequestMapping(value="/add")
@ResponseBody
public Object add(
@RequestParam String name,
@RequestParam String content
) {
newsService.save(name, content);
Map<String, Object> map = new HashMap<String, Object>();
map.put("susses", true);
map.put("msg", "添加成功!");
return map;
}
@RequestMapping(value="/update")
@ResponseBody
public Object update(
@RequestParam Integer id,
@RequestParam String name,
@RequestParam String content
) {
newsService.update(id, name, content);
Map<String, Object> map = new HashMap<String, Object>();
map.put("susses", true);
map.put("msg", "更新成功!");
return map;
}
<span style="white-space:pre"> </span>@RequestMapping(value="/delete")
<span style="white-space:pre"> </span>@ResponseBody
<span style="white-space:pre"> </span>public Object delete(
<span style="white-space:pre"> </span>@RequestParam String ids
<span style="white-space:pre"> </span>) {
<span style="white-space:pre"> </span>String[] idarr = ids.split(",");
<span style="white-space:pre"> </span>for(String tmp:idarr){
<span style="white-space:pre"> </span>Integer id = new Integer(Integer.parseInt(tmp));
<span style="white-space:pre"> </span>newsService.deleteById(id);
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>Map<String, Object> map = new HashMap<String, Object>();
<span style="white-space:pre"> </span>map.put("susses", true);
<span style="white-space:pre"> </span>map.put("msg", "删除成功!");
<span style="white-space:pre"> </span>return map;
<span style="white-space:pre"> </span>}
@RequestMapping(value="/list")
@ResponseBody
public Object list(
@RequestParam(required=false) Integer start,
@RequestParam(required=false) Integer limit
) {
List<News> list = newsService.getList(start,limit);
Map<String, Object> map = new HashMap<String, Object>();
map.put("result", list);
map.put("totalCount", newsService.getTotalCount());
return map;
}
}
主要增加了新闻增删改查几个接口,工程比较干净,没警告。。。
下面来开发extjs客户端部分
启动Sencha Architect,创建一个editgrid工程保存在ExtBook工程的webroot目录下,创建如下图所示控件

其实就是一个viewport和一个gridpanel。我们即将使得这个gridpanel具有编辑功能。
创建相应的store和model
这里不详细说,如果不会的可以参考我之前的文章。
主要参数为url:../NewsController/list
和root:results
配置好了基本就能看到如下图显示的效果了。
随便提一下,在myeclipse每次要看效果够要刷新一下工程。如果数据库里面已经有News表则需要删除好让hibernate重新为我们自动创建最新的数据表。测试数据是我用Navicat for MySQL手动添加上去的。
接下来为gridpanel添加一个头部toolbar,并在所添加的toolbar上添加三个按钮,一个叫“添加”,一个叫”删除“,另一个叫“保存”。继续添加一个分页控件(paging toolbar)到gridpanel,设置pagingboolbar的display msg为“当前显示 {0} - {1} of {2}”,empty msg为“暂无数据”,设置NewsStore的pageSize为20,,如下图
接下来添加一个单元格编辑插件Cell Editing plugin,在grid面板可以找到。然后为每一个column添加编辑器。除了createTime和id其他都添加textfield,具体才操作方法为找到column的editor属性,点击加号选择textfield即可。createTime和id的editor不添加,因为这里这两个属性是只读的。
运行一下,达到如下图效果即可
接下来编辑控制器,添加一个Controller到Controllers中,重命名为NewsController,并在NewsController中添加以下几个函数init,onAdd,onDel,onSave。具体操作方法为选中NewsController,找到functions属性点击加号会添加一个函数,点击新函数上的箭头选中函数即可修改函数名,参数都为空(不设置)
双击init进入函数init函数体进行编写
init内容如下
this.control(
{
'button[cls=addBtn]':
{
click: this.onAdd
},
'button[cls=delBtn]':
{
click: this.onDel
},
'button[cls=saveBtn]':
{
click: this.onSave
}
}
);
这里是为了绑定事件。还要设置添加按钮的cls为”addBtn“,删除按钮的cls为”delBtn“,保存按钮的cls为”saveBtn“
接下来编辑onAdd函数,内容如下
var news = new MyApp.model.NewsModel({
id: 0,
name: '',
content: ''
});
grid = Ext.getCmp('NewsGridPanel');
//debugger;
edit = grid.getPlugin('NewsGridEditing');
edit.cancelEdit();
grid.store.insert(0, news);
edit.startEditByPosition({
row: 0,
column: 1
});
另外还需要更改GridPanel的id为NewsGridPanel,editingCellplugin的pluginid为NewsGridEditing,选中autoLoad,不勾选autoSync。
保存刷新运行,点击"添加"即可添加一行数据
接下来编写onDel函数,内容如下
grid = Ext.getCmp('NewsGridPanel');
//debugger;
edit = grid.getPlugin('NewsGridEditing');
edit.cancelEdit();
//grid.store.
var selRecords = grid.getSelectionModel().getSelection();
var len = selRecords.length;
var ids = "";
if (len == 0) {
Ext.MessageBox.alert("提示消息", "您未选中任何数据!");
return false;
}
Ext.Msg.confirm("提示", "确定要删除吗?", function (btn)
{
if (btn == "yes") {
for (var i = 0; i < len; i++) {
idd = selRecords[i].get("id");
if(!idd)
{
Ext.getCmp('NewsGridPanel').store.removeAt(i);
}
}
selRecords = grid.getSelectionModel().getSelection();
len = selRecords.length;
if(len == 0){
return;
}
for (var i = 0; i < len; i++) {
if (i == len - 1)
{
ids += selRecords[i].get("id");
}
else {
ids += selRecords[i].get("id") + ",";
}
}
Ext.Ajax.request(
{
url: "../NewsController/delete",
params: {
"ids": ids
},
success: function (reponse, option) {
Ext.getCmp("NewsGridPanel").getStore().reload();
Ext.MessageBox.alert("提示消息", "删除成功!");
},
failure: function () {
Ext.MessageBox.alert("提示消息", "删除失败!");
}
}
);
}
});
这里需要配置一下NewsGridPanel为多选模式,即配置设置Selection Model为”Ext.selection.CheckboxModel“,看下图已经可以删除了
接下来编写onSave函数,内容如下
grid = Ext.getCmp('NewsGridPanel');
grid.store.sync();
var records = grid.store.getUpdatedRecords();//获取修改的行的数据,无法获取幻影数据
var newRecords = grid.store.getNewRecords();//获得幻影行
if(newRecords.length>0){
for(var i=0;i<newRecords.length;i++){
data = newRecords[i];
kv = data.getChanges();
Ext.Ajax.request(
{
url: "../NewsController/add",
params: {
'name': data.get('name'),
'content':data.get('content')
},
success: function (reponse, option) {
Ext.getCmp('NewsGridPanel').store.reload();
},
failure: function () {
Ext.MessageBox.alert("提示消息", "网络连接失败!");
}
}
);
}
}
//debugger;
if(records.length>0){
for(var i=0;i<records.length;i++){
data = records[i];
Ext.Ajax.request(
{
url: "../NewsController/update",
params: {
'id': data.get('id'),
'name': data.get('name'),
'content':data.get('content')
},
success: function (reponse, option) {
Ext.getCmp('NewsGridPanel').store.reload();
},
failure: function () {
Ext.MessageBox.alert("提示消息", "网络连接失败!");
}
}
);
}
}
grid.store.reload();
之前的hibernate连接会有中文问题,修改hibernate.properties文件中的dataSource属性为
dataSource.url=jdbc:mysql://localhost:3306/extbook?createDatabaseIfNotExist=true&autoReconnect=true&useUnicode=true&characterEncoding=utf-8&mysqlEncoding=utf8
好了,打完收工