初次知道EXT还是通过看一个同事以前做的项目,当时他们用EXT做了一个桌面版的系统,看到就一下被吸引了,心想:"原来WEB版也可以做的这么酷",后来就买了一本有关EXT的书学习,发现EXT有好多面向对象的设计,给我的感觉就是每个JS文件就详单与Java中的类文件一样,学了一段时间之后就想着尝试自己做一个系统玩玩儿,做了一段时间发现,EXT其实还是挺难学的,后来就一直希望能在自己的项目中应用,但是一直没有机会实战,再后来由于项目使用easyui,就又投身到easyui的研究中,就放下了Ext的学习,在不经意间发现Ext已经跟新了好几个版本,最近趁项目运维阶段不是很忙,抽时间用EXT5做了一个系统,以前的东西忘得也差不多了,也是在网上找了一些资料,学习了一下,项目才算初步成型,不过还有很长的路要走啊,希望自己能坚持下去吧。
项目----项目管理系统
目的是想着一个公司肯定有好多系统,想OA,还有好多商业系统,然后自己就想能不能对这些项目进行一下统一管理呢,这样的话,如果项目里遇到问题还可以参考其他系统的实现,从而实现公司内部技术的共享。
目前项目的成果:
- 下图显示的是进入项目的主页的整体布局
点击---》项目信息--》进入项目信息页面
点击人员信息---》进入人员信息界面
点击用户管理---》进入用户管理界面
其他的操作类似就不一一列举了,目前的界面还有和数据库做交互
项目中使用的技术:
前端:Extjs5.0
后台:SpringMVC
服务器:Tomcat
数据库:Mysql
开发工具:eclipse
所有jar包的依赖通过Maven管理
Extjs的搭建过程:
- 新建一个Maven项目,过程如下:
点击next:
点击next
点击完成即可
2.生成Ext所需环境
需要使用sencha cmd,具体可以参考:http://lingyi.red/using-sencha-cmd-with-ext-js-5
EXT主要代码实现如下:
Main.js
/**
* This class is the main view for the application. It is specified in app.js as
* the "autoCreateViewport" property. That setting automatically applies the
* "viewport" plugin to promote that instance of this class to the body element.
*
* TODO - Replace this content of this view to suite the needs of your
* application.
*/
Ext.define('webapp.view.main.Main', {
extend : 'Ext.container.Container',
requires : [ 'webapp.view.main.MainController',
'webapp.view.main.MainModel' ],
uses : [ 'webapp.view.module.Module' ],
// 设置图标字体文件,只有设置了以后才能用glyph属性
initComponent : function() {
Ext.setGlyphFontFamily('FontAwesome');
// this.getViewModel().set('monetary.value','tenthousand');
this.callParent();
},
xtype : 'app-main',
uses : ['webapp.view.main.layout.Center', 'webapp.view.main.layout.Top', 'webapp.view.main.layout.Bottom',
'webapp.view.main.layout.AccordionMainMenu' ],
controller : 'main',
viewModel : {
type : 'main'
},
layout : {
type : 'border'
},
items : [ {
xtype : 'maintop',
region : 'north'
}, {
xtype : 'mainbottom',
region : 'south'
},
{
xtype : 'mainmenuaccordion',
region : 'west', // 左边面板
width : 250,
split : true
}, {
region : 'center',
xtype : 'maincenter'
} ]
});
MainController.js
/**
* This class is the main view for the application. It is specified in app.js as
* the "autoCreateViewport" property. That setting automatically applies the
* "viewport" plugin to promote that instance of this class to the body element.
*
* TODO - Replace this content of this view to suite the needs of your
* application.
*/
Ext.define('webapp.view.main.MainController', {
extend : 'Ext.app.ViewController',
requires : [ 'Ext.window.MessageBox' ],
uses : [ 'webapp.view.module.Module' ],
alias : 'controller.main',
// 选择了主菜单上的菜单后执行
onMainMenuClick : function(menuitem) {
var maincenter = this.getView().down('maincenter');
//获取tab组件
var tab = maincenter.getComponent(menuitem.moduleName);
//如果组件没有创建,则添加,否则不在添加,目的就是防止用户重复点击导航栏
if (tab == null) {
maincenter.setActiveTab(maincenter.add({
id : menuitem.moduleName,
xtype : 'modulepanel',
moduleName : menuitem.moduleName,
closable : true,
reorderable : true
}));
}
},
setting : function() {
alert(1);
}
});
MainModel.js
/**
* This class is the view model for the Main view of the application.
*/
Ext.define('webapp.view.main.MainModel', {
extend : 'Ext.app.ViewModel',
alias : 'viewmodel.main',
constructor : function() {
Ext.log('MainModel constructor');
var me = this;
// 这一句是关键,如果没有的话,this还没有初始化完成,下面的Ext.apply(me.data,....)这句就会出错
this.callParent(arguments);
// 同步调用取得系统参数
Ext.Ajax.request({
url : 'application.do',//加载模块信息
async : false, // 同步
success : function(response) {
var text = response.responseText;
// 将字段串转换成本地变量
var applicationInfo = Ext.decode(text, true);
// 把从后台传过来的参数加入到data中去
Ext.apply(me.data, applicationInfo);
}
});
},
data : {
name : '系统导航',
// 系统信息
system : {
name : '项目管理系统',
iconUrl : ''
},
// 单位信息
service : {
company : 'XXXX',
copyright : 'XXXX'
},
// 系统菜单的定义,这个菜单可以是从后台通过ajax传过来的
systemMenu : [ {
text : '项目管理', // 菜单项的名称
icon : '', // 菜单顶的图标地址
glyph : 0,// 菜单项的图标字体的数值
expanded : true, // 在树形菜单中是否展开
description : '', // 菜单项的描述
items : [ {
text : '项目信息', // 菜单条的名称
module : 'Global', // 对应模块的名称
icon : '', // 菜单条的图标地址
glyph : 0xf0f7
// 菜单条的图标字体
}, {
text : '人员信息',
module : 'Worker',
icon : '',
glyph : 0xf02e
} ]
}, {
text : '知识管理',
expanded : true,
items : [ {
text : '问题管理',
module : 'Problem',
glyph : 0xf02d
}, {
text : '技术分享',
module : 'Shared',
glyph : 0xf03a
} ]
}, {
text : '系统管理',
expanded : true,
items : [ {
text : '用户管理',
module : 'userMg',
glyph : 0xf02d
}, {
text : '角色管理',
module : 'Role',
glyph : 0xf03a
}, {
text : '权限管理',
module : 'Authority',
glyph : 0xf022
}, {
text : '菜单管理',
module : 'Resource',
glyph : 0xf0d6
} ]
}
],
},
getModuleDefine : function(moduleId) {
var result = null;
Ext.Array.each(this.get('tf_Modules'), function(module) {
if (module.tf_moduleId == moduleId + ''
|| module.tf_moduleName == moduleId) {
result = module;
return false;
}
})
return result;
}
// TODO - add data, formulas and/or methods to support your view
});
Top.js
/**
* 页面顶部设计
*/
Ext.define('webapp.view.main.layout.Top', {
extend : 'Ext.toolbar.Toolbar',
alias : 'widget.maintop', // 定义了这个组件的xtype类型为maintop
style : 'background-color : #cde6c7',
uses : [ 'webapp.ux.ButtonTransparent' ],
defaults : {
xtype : 'buttontransparent'
},
items : [ {
xtype : 'image',
bind : { // 数据绑定到MainModel中data的ystem.iconUrl
hidden : '{!system.iconUrl}', // 如果system.iconUrl未设置,则此image不显示
src : '{system.iconUrl}' // 根据system.iconUrl的设置来加载图片
}
}, {
xtype : 'label',
bind : {
text : '{system.name}' // text值绑定到system.name
},
style : 'font-size : 20px; color : blue;'
}, {
text : '注销',
glyph : 0xf011
}, {
text : '设置',
glyph : 0xf013,
style:'right:auto; left:1200px;top:0px',
handler:'setting'
} ]
});
Bottom.js
/**
* 页面底部实现
*/
Ext.define('webapp.view.main.layout.Bottom', {
extend : 'Ext.toolbar.Toolbar',
alias : 'widget.mainbottom',
uses : [ 'webapp.ux.ButtonTransparent' ],
defaults : {
xtype : 'buttontransparent'
},
// 背景颜色
style : 'background-color : #DFEAF2;',
items : [ {
bind : {
text : '服务单位:{service.company}'
}
}, {
bind : {
text : '©{service.copyright}'
}
} ]
});
Center.js
/**
* 系统界面的主区域,是一个tabpanel,可以有多个tab页面,用来放置各个模块。
*/
Ext
.define(
'webapp.view.main.layout.Center',
{
extend : 'Ext.tab.Panel',
alias : 'widget.maincenter',
closeAction : 'hide',
autoDestroy : true,
tabPosition : 'top',
plugins : [
{
ptype : 'tabclosemenu',
closeAllTabsText : '关闭所有',
closeOthersTabsText : '关闭其他',
closeTabText : '关闭',
extraItemsTail : [
'-',
{
text : '可关闭',
itemId : 'canclose',
checked : true,
hideOnClick : false,
handler : function(item) {
item.ownerCt.tabPanel.tab
.setClosable(item.checked);
}
},
'-',
{
text : '登录时自动打开',
itemId : 'autoopen',
checked : false,
hideOnClick : false,
handler : function(item) {
if (item.checked)
Jfok.system
.addModuleToAutoOpen(item.ownerCt.tabPanel.moduleName);
else
Jfok.system
.deleteModuleToAutoOpen(item.ownerCt.tabPanel.moduleName);
}
},
'-',
{
xtype : 'fieldcontainer',
items : {
xtype : 'numberfield',
fieldLabel : '最多打开Tab数',
itemId : 'maxtab',
width : 156,
value : 8,
maxValue : 20,
minValue : 3,
listeners1 : {
change : function(field,
newValue, oldValue) {
Jfok.system
.setMaxTab(newValue);
}
}
}
} ],
listeners : {
beforemenu : function(menu, tabPanel) {
// 此插件有bug,需要加入这个参数
menu.tabPanel = tabPanel;
if (tabPanel.tab.reorderable) {
menu.down('#canclose').setChecked(
tabPanel.tab.closable);
menu.down('#canclose').enable();
} else {
menu.down('#canclose').setChecked(
false);
menu.down('#canclose').disable();
}
// 如果是有parentFilter的模块,那么自动打开的菜单条隐掉
// ,上面的'-'也隐掉
menu.down('#autoopen').setVisible(
!tabPanel.parentModuleName);
menu
.down('#autoopen')
.previousSibling()
.setVisible(
!tabPanel.parentModuleName);
menu.down('#autoopen')
.setChecked(false);// Jfok.system
// .isModuleAutoOpen(tabPanel.moduleName));
menu.down('#maxtab').setValue(8);// Jfok.system.getMaxTab());
}
}
}, Ext.create('Ext.ux.TabReorderer') ],
})
折叠菜单的js
/**
* 折叠菜单实现
*/
Ext.define('webapp.view.main.layout.AccordionMainMenu', {
extend : 'Ext.panel.Panel',
alias : 'widget.mainmenuaccordion',
title : '系统菜单',
glyph : 0xf0c9,
layout : {
type : 'accordion',
animate : true
},
viewModel : 'main',
initComponent : function() {
this.items = [];
var menus = this.getViewModel().get('systemMenu');
for ( var i in menus) {
var menugroup = menus[i];
var accpanel = {
menuAccordion : true,
xtype : 'panel',
title : menugroup.text,
bodyStyle : {
padding : '10px'
},
layout : 'fit',
dockedItems : [ {
dock : 'left',
xtype : 'toolbar',
items : []
} ],
glyph : menugroup.glyph
};
for ( var j in menugroup.items) {
var menumodule = menugroup.items[j];
accpanel.dockedItems[0].items.push({
moduleName:menumodule.module,
xtype : 'buttontransparent',
text : this.addSpace(menumodule.text, 12),
glyph : menumodule.glyph,
handler : 'onMainMenuClick'
});
}
this.items.push(accpanel);
}
this.callParent(arguments);
},
addSpace : function(text, len) {
console.log(text.length);
var result = text;
for ( var i = text.length; i < len; i++) {
result += ' ';
}
return result;
}
});
Module.js
/**
* 一个模块的主控界面的容器,用来安放各个模块控件以及协调他们之间的关系
*/
Ext.define('webapp.view.module.Module', {
extend : 'Ext.panel.Panel',
alias : 'widget.modulepanel',
requires : [ 'webapp.view.module.ModuleController',
'webapp.view.module.ModuleModel',
'webapp.view.module.factory.ModelFactory' ],
uses : [ 'webapp.view.module.region.Navigate',
'webapp.view.module.region.Grid', 'webapp.view.module.user.Grid',
'webapp.view.module.region.WorkerGrid',
'webapp.view.module.grid.Problem',
'webapp.view.module.grid.Shared', 'webapp.view.module.grid.Role',
'webapp.view.module.grid.Authority',
'webapp.view.module.grid.Resource' ],
referenceHolder : true,
controller : 'module',
bind : {
title : '{tf_title}' // 这个绑定是有效的,可以根据ModuleModel中的值来设置title
},
layout : 'border', // 模块采用border布局
initComponent : function() {
// 从MainModel中取得当前模块的定义数据,包括字段和各种设置的信息
var mainmodel = this.up('app-main').getViewModel();
this.module = mainmodel.getModuleDefine(this.moduleName);
var viewmodel = new Ext.create('webapp.view.module.ModuleModel', {
// 将该模块的定义信息传递给本模块的viewModel
module : this.module
});
this.setViewModel(viewmodel);
this.glyph = this.getViewModel().get('tf_glyph'); // 由于上面的glyph的bind无效,因此需要在这里加入glyph的设置
this.model = webapp.view.module.factory.ModelFactory
.getModelByModule(this.module);
this.items = [ {
xtype : this.moduleName, // 模块的grid显示区域
region : 'center'
//store : this.store
} ]
this.callParent();
}
})
ModuleModel.js
Ext.define('webapp.view.module.ModuleModel', {
extend : 'Ext.app.ViewModel',
alias : 'viewmodel.module',
constructor : function() {
Ext.log('module constructor');
// 这一句是关键,如果没有的话,this还没有初始化完成,下面的Ext.apply(me.data,....)这句就会出错
this.callParent(arguments);
// 取得MainModel.js中取得的这个模块的的初始化信息
Ext.apply(this.data, this.module)
},
// 在开发过程中我先用设定好的值放于data中,等以后自定义的时候,data里的值都是从后台取得的
// 所有数据库里的字段,我都以tf_开头,只是为了表示这是从后台读取过来的
data : {
tf_moduleId : null, // 模块ID号:一个数字的ID号,可以根据此ID号的顺序将相同分组的模块放在一块。
tf_ModuleGroup : null,// 模块分组:模块分到哪个组里,比如说业务模块1、业务模块2、系统设置、系统管理等。
tf_moduleName : null, // 模块标识:系统中唯一的模块的标识
tf_title : null,// 模块名称:能够描述此模块信息的名称。
tf_glyph : null, // 图标字符值
tf_shortname : null,// 模块简称:如果名称过长,有些地方可以用简称来代替。
tf_englishName : null,// 模块英文名称:万一要制作英文版,可以用英文名称。
tf_englishShortName : null, // 模块英文简称:可以用作生成编码字段。
tf_description : null,// 模块描述:
tf_remark : null,
// 备注:
// 模块的grid方案,可以定义多个方案
tf_gridSchemes : [],
// 模块的form方案,可以定义多个方案
tf_formSchemes : [],
selectedNames : '' // 选中的记录的names显示在title上
},
formulas : {
// 模块grid方案的选择Combo是否显示
gridSchemeHidden : function(get) {
return this.get('tf_gridSchemes').length <= 1;
}
},
// 根据字段id,找到字段相应的定义
getFieldDefine : function(fieldId) {
var result = null;
Ext.Array.each(this.data.tf_fields, function(field) {
if (field.tf_fieldId == fieldId) {
result = field;
return false;
}
});
return result;
}
})
ModuleController.js
Ext.define('webapp.view.module.ModuleController', {
extend : 'Ext.app.ViewController',
requires : [ 'Ext.MessageBox', 'Ext.window.Toast' ],
alias : 'controller.module',
init : function() {
console.log('modulecontroller.init')
}
})
ModelFactory.js
/**
* 根据module的数据来生成模块的model
*/
Ext
.define(
'webapp.view.module.factory.ModelFactory',
{
statics : {
getModelByModule : function(module) {
var model;
//在define之前需要判断model是否已经定义过,否则会报错
if(!Ext.isDefined('webapp.view.model.'+module.tf_moduleName)){
model= Ext
.define(
'webapp.view.model.'
+ module.tf_moduleName,
{
extend : 'Ext.data.Model',
module : module,
idProperty : module.tf_primaryKey,
nameFields : module.tf_nameFields,
titleTpl : module.tf_titleTpl,
titleTemplate : null,
fields : this.getFields(module),
proxy : {
type : 'rest',
batchActions : true,
extraParams : {
moduleName : module.tf_moduleName
},
api : {
// 在这里加rest/是因为在web.xml中
// <url-pattern>/rest/*</url-pattern>这一句,spring会根据rest
// 后面的参数去进行匹配
//read : 'rest/module/fetchdata.do',
// update : 'rest/module/update.do',
// create : 'rest/module/create.do',
// destroy : 'rest/module/remove.do'
},
actionMethods : {
create : 'POST',
read : 'GET',
update : 'PUT',
destroy : 'DELETE'
},
reader : {
type : 'json',
root : 'records',
totalProperty : 'totalCount'
},
writer : {
type : 'json',
writeRecordId : true,
writeAllFields : false
// 没有修改过的字段不加入到update和delete的json中去
},
listeners : {
exception : function(
proxy,
response,
operation) {
// 将出错信息加到proxy中去,传递到store的sync中显示出错信息,显示后将此属性删除
proxy.errorInfo = Ext
.decode(
response.responseText,
true);
// 如果出错信息解析出错,则加入一个缺省的
if (!proxy.errorInfo)
proxy.errorInfo = {
resultCode : -1,
errorMessage : '未知原因:'
+ response.responseText
}
}
}
},
getTitleTpl : function() {
if (!this.titleTemplate) {
if (this.titleTpl)
this.titleTemplate = new Ext.Template(
this.titleTpl);
else
this.titleTemplate = new Ext.Template(
'{'
+ this.nameFields
+ '}');
}
return this.titleTemplate
.apply(this
.getData())
},
// 此条记录是否可以修改
canEdit : function() {
if (this.module.tf_hasAuditing
&& this
.get('tf_auditinged'))
return false;
if (this.module.tf_hasApprove
&& this
.get('tf_shNowCount') > 0)
return false;
return true;
},
// 此条记录是否可以进行操作
canOperate : function() {
if (this.module.tf_hasAuditing
&& this
.get('tf_auditinged'))
return false;
return true;
},
// 此条记录是否可以删除
canDelete : function() {
if (this.module.tf_hasAuditing
&& this
.get('tf_auditinged'))
return {
canDelete : false,
message : '【'
+ this
.getTitleTpl()
+ '】已进行过审核,不允许进行删除操作!'
};
if (this.module.tf_hasApprove
&& this
.get('tf_shNowCount') > 0)
return {
canDelete : false,
message : '【'
+ this
.getTitleTpl()
+ '】正在审批或已经审批完成,不允许进行删除操作!'
};
return true;
},
// 取得主键值
getIdValue : function() {
return this
.get(this.idProperty);
},
// 取得当前记录的名字字段
getNameValue : function() {
if (this.nameFields)
return this
.get(this.nameFields);
else
return null;
}
});
}
return model;
},
// String("String"), Boolean("Boolean"),
// Integer("Integer"),
// Date("Date"), Double("Double"), Float("Float");
// Percent
getFields : function(module) {
var fields = [];
for ( var i in module.tf_fields) {
var fd = module.tf_fields[i];
var field = {
name : fd.tf_fieldName,
title : fd.tf_title,
type : this.getTypeByStr(fd.tf_fieldType)
};
if (field.type == 'string') {
field.useNull = true;
field.serialize = this.convertToNull;
}
if (fd.tf_fieldType == 'Date') {
field.dateWriteFormat = 'Y-m-d';
field.dateReadFormat = 'Y-m-d';
}
if (fd.tf_fieldType == 'Datetime')
field.dateReadFormat = 'Y-m-d H:i:s';
field.tf_haveAttachment = fd.tf_haveAttachment;
fields.push(field);
}
return fields;
},
getTypeByStr : function(str) {
console.log(str);
switch (str) {
case 'String':
return 'string';
case 'Boolean':
return 'boolean';
case 'Integer':
return 'int';
case 'Date':
return 'date';
case 'Datetime':
return 'date';
case 'Double':
case 'Money':
case 'Percent':
return 'float';
default:
return 'string';
}
},
// 如果是空字符串,返回null
convertToNull : function(v) {
return v ? v : null;
}
}
});
下面就是一个展示表格的js,实现都差不多就不一一列举了,以用户管理的表格为例
Ext.define('webapp.view.module.user.Grid', {
extend : 'Ext.grid.Panel',
alias : 'widget.userMg',
uses : [ 'webapp.view.module.region.GridToolbar' ],
bind : {
title : '{tf_title}' // 数据绑定到ModuleModel中的tf_title
},
dockedItems :{
xtype : 'gridtoolbar', // 按钮toolbar
dock : 'top',
grid : this,
store:this.myStore
},
// 自定义字段的还没有做,先放几个固定的
columns : [ {
dataIndex : 'id',
text : '用户ID',
width : 250
}, {
dataIndex : 'userName',
text : '用户姓名'
}, {
dataIndex : 'email',
text : '用户邮箱'
} , {
dataIndex : 'createDate',
text : '创建时间'
}, {
dataIndex : 'createId',
text : '创建ID'
} , {
dataIndex : 'status',
text : '状态'
} ],
})
// var myStore = Ext.create('Ext.data.Store', {
// model: 'User',
// proxy: {
// type: 'ajax',
// url: '/user/list.do',
// reader: {
// type: 'json',
// rootProperty: 'root'
// }
// },
// autoLoad: true
// });
接下来就是一部分java代码的实现
Module.java 用于动态生成点击导航栏菜单是生成项目的Module
/**
* 模块实体
*
*/
@Entity
@Table(name = "t_module")
@SuppressWarnings("serial")
@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
public class Module extends BaseEntity {
/** */
private static final long serialVersionUID = 1L;
@Id
private Integer tf_moduleId;
private String tf_ModuleGroup;
private String tf_moduleName;
private String tf_title;
private String tf_glyph;
private String tf_shortName;
public Integer getTf_moduleId() {
return tf_moduleId;
}
public void setTf_moduleId(Integer tf_moduleId) {
this.tf_moduleId = tf_moduleId;
}
public String getTf_ModuleGroup() {
return tf_ModuleGroup;
}
public void setTf_ModuleGroup(String tf_ModuleGroup) {
this.tf_ModuleGroup = tf_ModuleGroup;
}
public String getTf_moduleName() {
return tf_moduleName;
}
public void setTf_moduleName(String tf_moduleName) {
this.tf_moduleName = tf_moduleName;
}
public String getTf_title() {
return tf_title;
}
public void setTf_title(String tf_title) {
this.tf_title = tf_title;
}
public String getTf_glyph() {
return tf_glyph;
}
public void setTf_glyph(String tf_glyph) {
this.tf_glyph = tf_glyph;
}
public String getTf_shortName() {
return tf_shortName;
}
public void setTf_shortName(String tf_shortName) {
this.tf_shortName = tf_shortName;
}
}
ApplicationController控制器,用于加载Module数据
@Controller
public class ApplicationController {
@Resource(name = "applicationService")
private ApplicationService applicationService;
private Map jsonMap = new HashMap();
@RequestMapping("/application.do")
@ResponseBody
public Map<String, List<Module>> findModules() {
jsonMap.put("tf_Modules", applicationService.findAll());
return jsonMap;
}
public Map getJsonMap() {
return jsonMap;
}
public void setJsonMap(Map jsonMap) {
this.jsonMap = jsonMap;
}
}
ApplicationService
public interface ApplicationService {
/**
* @return
*/
List<Module> findAll();
}
ApplicationServiceImpl
@Service("applicationService")
@Transactional
public class ApplicationServiceImpl implements ApplicationService{
@Resource(name="applicationDao")
private ApplicationDao applicationDao;
/**
* @return
* @see com.pms.service.ApplicationService#findAll()
*/
@Override
public List<Module> findAll() {
// TODO Auto-generated method stub
return applicationDao.findAll();
}
}
ApplicationDao
@Repository("applicationDao")
public class ApplicationDao extends BaseDao<Module> {
public List<Module> findAll() {
return findByhql(" from Module where 1=1 ");
}
}
BaseDao
public class BaseDao<E extends BaseEntity> {
@PersistenceContext
private EntityManager entityManager;
public EntityManager getEntityManager() {
return entityManager;
}
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
/**
* 添加
*
* @param entity
* @return
*/
public E save(E entity) {
if (entity != null) {
entityManager.persist(entity);
}
return entity;
}
/**
* 更新
*
* @param entity
* @return
*/
public E update(E entity) {
entity = entityManager.merge(entity);
return entity;
}
/**
* 删除
*
* @param entity
*/
public void delete(E entity) {
entityManager.remove(entity);
}
/**
* 根据ID查询
*
* @param entityClass
* @param id
* @return
*/
public E findById(Class<E> entityClass, Integer id) {
return entityManager.find(entityClass, id);
}
/**
* 根据Hql查询
*
* @param hql
* @return
*/
public List<E> findByhql(String hql) {
Query query = entityManager.createQuery(hql);
return query.getResultList();
}
}
目前就写到这个程度了,由于本人也是一个码农,只有抽时间继续完成其他功能,权限打算使用Shiro实现,而且对Ext也是似懂非懂,需要边学边做,而且这次使用SpringMVC也是初次尝试,因为开发项目用的都是SSH,之所以用SpringMVC就是出于学习的目的。
最后需要感谢:点击打开链接 的作者,因为这个项目的实现是参照该作者的讲解实现,而且有些代码也是基于作者的代码进行了一些改动