Jason Rudolph 关于Groovy的新教程:Grails + EJB Step by Step (增加关系)

本文是一篇关于Grails框架下的关系管理教程,介绍了如何通过简单的步骤实现员工与计算机之间的关联管理,包括展示、编辑和删除等功能。
本文转引自http://www.infoq.com/cn/articles/grails-ejb-tutorial
作者 Jason Rudolph 译者 胡键
这是grails很好的一个入门教程,对比JAVA应用可以省略大量的代码
下面是最关键的关系管理部分


步骤5 —— 增加关系管理
关于关系管理,我们对应用有哪些期望?嗯,要我说,我们应该能……

查看分配给某个员工的所有计算机。
查看单个计算机的细节(包括它的分配状况)。
能增加、修改和删除计算机(包括它的分配状况)。
准备好了吗?让我们开始吧。

在员工页列出计算机没有什么意义,因此让我们把这列移除。打开grails-app/views/employeeBean/list.gsp,并移除该列。现在,刷新浏览器,验证修改。
【附件1】

接下来,点击显示(Show),查看员工的细节。

【附件2】
最少,我们需要整理显示每个计算机的文本。但是,可能我们根本就不愿直接在这个页面上看到计算机。与其在该页显示计算机,不如包含一个指向该员工的计算机列表的链接。

打开该页模板(即,grails-app/views/employeeBean/show.gsp),移除显示当前员工计算机列表的行。接着增加以下行,链接到显示该员工的计算机列表的单独页面。
[code]
<tr class="prop">
<td colspan="2" align="left" class="name">
<g:link controller='computerBean' action='showComputersByEmployee' id='${employeeBean.id}' >Show Computers</g:link>
</td></tr>
[/code]
此处,我们使用了Grails标签库。link标签将产生指向ComputerBeanController的链接,并调用一个我们需要定义的新动作,showComputersByEmployee。该链接还包含了所请求员工的ID。

让我们刷新浏览器,看看变化。


很好,我们得到链接了。现在,我们需要为链接定义一个新动作。在编辑器中打开grailsapp/controllers/ComputerBeanController.groovy,因为新动作将通过员工查找计算机,我们首先需要增加引用EmployeeBean类的import语句。

import com.jasonrudolph.ejb3example.entity.EmployeeBean
接着,我们增加新动作。
[code]
def showComputersByEmployee = {
render(view:'list', model:[ computerBeanList:
ComputerBean.findAllByEmployeeBean(EmployeeBean.get(params.id)) ])
}
[/code]
这个动作让我们好好见识了一下Groovy(和Grails)的能力,通过简单的几行代码,你的表现力究竟有多大。在以上几行代码中,我们告诉Grails,任何showComputersByEmployee的调用应该......

使用params.id从request中获得员工
使用EmployeeBean#get方法获得员工ID对应的员工
使用ComputerBean#findAllByEmployeeBean方法找出与员工相关的所有计算机
将结果放入名为computerBeanList的对象
展现(render)视图,在一个名为list的模板中,使用computerBeanList对象作为模型。
记得曾在EmployeeBean中定义get方法,以及ComputerBean中定义findAllByEmployeeBean方法吗?没有?答对了。这些方法只是Grails为你的领域对象所提供的众多动态方法的一小部分而已。之后,我们将更多的探讨这些条目。现在,我们准备点击显示计算机链接了。


我们越来越接近完工了。我们仍然需要修改Employee Bean列中的文本。我们需要在此显示些更让人明白点儿的东西。

同样,我们可能更愿意标出这些计算机所属的员工。我们当前重用了list模板(作为ComputerBean的脚手架代码的一部分产生),而那个模板最初是为了列出所有计算机而设计的。另一方面,我们总能定义一个单独的模板,它用于显示计算机的子集,或能使list模板更动态一些以支持两个场景。就现在而言,我们将去掉这个特性,将其作为“有则更好”,而非必要的特性。

我们应该完成了管理员工所需的所有改变。现在,我们只需整理计算机管理的特性。

既然我们就在这儿,让我们整理一下计算机list模板。替换Employee Bean列的当前文本,改为显示员工的网络ID。打开grails-app/views/computerBean/list.gsp。找到在展现Employee Bean列文本的Groovy脚本…… ${it.employeeBean}
……将它改为显示员工的网络ID。

${it.employeeBean.networkId}
刷新浏览器,让我们看看它的样子。(Employee列在Brand列和Model列之间显得有些不合适,所以我调换了一下它们的位置。不愿这样做也可以。)


list模板完成了,现在该show模板了。

点击显示(Show)链接,并访问我们需要改变的页面。


看起来,我们只需改变员工链接的文本就行了。对此,我们完全赞同。那么,打开grailsapp/views/computerBean/show.gsp,并找到展现当前链接文本的那段脚本。

${computerBean?.employeeBean}
就象我们为list模板所做的那样,改变代码以显示员工的网络ID。

${computerBean?.employeeBean.networkId}
让我们再次刷新浏览器,并验证我们的改变。(同样,Employee行在Brand行和Model行之间显得有些不合适。因此,只要觉得合适,你可以随意重新调整这些行。)


让我们转到编辑(edit)功能。


我们着手查看这儿的一个主题。我们需要改变选择框,以提供一组网络ID的列表。在grails-app/views/computerBean/edit.gsp中找到<g:select>标签,把它修理成以下内容:
[code]
<g:select optionKey="id"
from="${com.jasonrudolph.ejb3example.entity.EmployeeBean.list()}"
name='employeeId'
optionValue='networkId'
value='${computerBean.employeeBean?.id}'></g:select>
[/code]
通过给标签增加optionValue参数,选择框中的文本会更具有含义。


现在,视图被修正了,但是更新(update)功能还需要除了视图之外的一点努力。我们同样需要增强控制器(即ComputerBeanController.groovy)。如果用户改变关联了计算机的员工,我们需要确保正确地持久化这些关联的变化。换句话说,我们需要从当前的员工去除关联,而将它分配给新的员工。这个增强型的更新方法需要一点额外的代码行。
[code]
def update = {
def computerBean = ComputerBean.get( params.id )
if(computerBean) {
if (computerBean.employeeBean) {
computerBean.employeeBean.computers.remove(computerBean)
}
computerBean.properties = params
def employeeBean = EmployeeBean.get(params.employeeId)
employeeBean.computers.add(computerBean)
computerBean.employeeBean = employeeBean
if(computerBean.save()) {
redirect(action:show,id:computerBean.id)
}
else {
render(view:'edit',model:[computerBean:computerBean])
}
}
else {
flash.message = "ComputerBean not found with id ${params.id}"
redirect(action:edit,id:params.id)
}
}
[/code]
保存你的改变,我们准备试验它了。让我们改变这台计算机的品牌——现在是联想(Lenovo)了——并将它重新分配给John Doe。


当然,我们也需要能够给我们的库存增加新的计算机。因此,让我们点击新建计算机(New ComputerBean)。


我们经过上次更改编辑(Edit)页之后,我们已具有很好的资格来整理这一页。我们需要对选择框做些相同的调整。打开grails-app/views/computerBean/create.gsp,调整<g:select>标签,并刷新你的浏览器。
[code]
<g:select optionKey="id"
from="${com.jasonrudolph.ejb3example.entity.EmployeeBean.list()}"
name='employeeId' optionValue='networkId'
value='${computerBean.employeeBean?.id}'></g:select>
[/code]
正如我们看到的编辑(edit)功能,我们需要对控制器进行轻微的增强。当我们创建新计算机时,我们需要在保存它之前分配给一个员工。编辑ComputerBeanController.groovy,以包含这个被更新的保存(save)方法。
[code]
def save = {
def computerBean = new ComputerBean()
computerBean.properties = params
def employeeBean = EmployeeBean.get(params.employeeId)
employeeBean.computers.add(computerBean)
computerBean.employeeBean = employeeBean
if(computerBean.save()) {
redirect(action:show,id:computerBean.id)
}
else {
render(view:'create',model:[computerBean:computerBean])
}
}[/code]
回到浏览器,我们准备创建一个新计算机了。填写空的域,并创建。


现在,Jane有一台崭新的膝上电脑了。

7. 最后,只剩下删除(delete)功能了。这次我们不需要改变任何模板。我们只需要给控制器增加一行。当我们在ComputerBeanController.groovy中删除一台计算机时,我们同样需要移除对应的计算机与员工的关联。以下的第四行代码负责这些。
[code]
def delete = {
def computerBean = ComputerBean.get( params.id )
if(computerBean) {
computerBean.employeeBean.getComputers().remove(computerBean)
computerBean.delete()
flash.message = "ComputerBean ${params.id} deleted."
redirect(action:list)
}
else {
flash.message = "ComputerBean not found with id ${params.id}"
redirect(action:list)
}
}[/code]
看起来Jane的新MacBook被回收了。我们应该删除它吗?


此时,我们完成它了!使用快捷的几步,我们现在已经有了一个功能完备的Web应用,它构建于我们的实体Bean上。当然,它还需一些打磨。但至少,作为一个可工作的原型,它已经足够了。尽管仍需改良,但它是个完全能发展成完美产品的一个原型。
基于数据驱动的 Koopman 算子的递归神经网络模型线性化,用于纳米定位系统的预测控制研究(Matlab代码实现)内容概要:本文围绕“基于数据驱动的Koopman算子的递归神经网络模型线性化”展开,旨在研究纳米定位系统的预测控制方法。通过结合数据驱动技术与Koopman算子理论,将非线性系统动态近似为高维线性系统,进而利用递归神经网络(RNN)建模并实现系统行为的精确预测。文中详细阐述了模型构建流程、线性化策略及在预测控制中的集成应用,并提供了完整的Matlab代码实现,便于科研人员复现实验、优化算法并拓展至其他精密控制系统。该方法有效提升了纳米级定位系统的控制精度与动态响应性能。; 适合人群:具备自动控制、机器学习或信号处理背景,熟悉Matlab编程,从事精密仪器控制、智能制造或先进控制算法研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①实现非线性动态系统的数据驱动线性化建模;②提升纳米定位平台的轨迹跟踪与预测控制性能;③为高精度控制系统提供可复现的Koopman-RNN融合解决方案; 阅读建议:建议结合Matlab代码逐段理解算法实现细节,重点关注Koopman观测矩阵构造、RNN训练流程与模型预测控制器(MPC)的集成方式,鼓励在实际硬件平台上验证并调整参数以适应具体应用场景。
提供了一套完整的基于51单片机的DDS(直接数字频率合成)信号波形发生器设计方案,适合电子爱好者、学生以及嵌入式开发人员学习和实践。该方案详细展示了如何利用51单片机(以AT89C52为例)结合AD9833 DDS芯片来生成正弦波、锯齿波、三角波等多种波形,并且支持通过LCD12864显示屏直观展示波形参数或状态。 内容概述 源码:包含完整的C语言编程代码,适用于51系列单片机,实现了DDS信号的生成逻辑。 仿真:提供了Proteus仿真文件,允许用户在软件环境中测试整个系统,无需硬件即可预览波形生成效果。 原理图:详细的电路原理图,指导用户如何连接单片机、DDS芯片及其他外围电路。 PCB设计:为高级用户准备,包含了PCB布局设计文件,便于制作电路板。 设计报告:详尽的设计文档,解释了项目背景、设计方案、电路设计思路、软硬件协同工作原理及测试结果分析。 主要特点 用户交互:通过按键控制波形类型和参数,增加了项目的互动性和实用性。 显示界面:LCD12864显示屏用于显示当前生成的波形类型和相关参数,提升了项目的可视化度。 教育价值:本资源非常适合教学和自学,覆盖了DDS技术基础、单片机编程和硬件设计多个方面。 使用指南 阅读设计报告:首先了解设计的整体框架和技术细节。 环境搭建:确保拥有支持51单片机的编译环境,如Keil MDK。 加载仿真:在Proteus中打开仿真文件,观察并理解系统的工作流程。 编译与烧录:将源码编译无误后,烧录至51单片机。 硬件组装:根据原理图和PCB设计制造或装配硬件。 请注意,本资源遵守CC 4.0 BY-SA版权协议,使用时请保留原作者信息及链接,尊重原创劳动成果。
【四轴飞行器的位移控制】控制四轴飞行器的姿态和位置设计内环和外环PID控制回路(Simulink仿真实现)内容概要:本文档详细介绍了基于Simulink仿真实现的四轴飞行器位移控制方法,重点在于设计内外环PID控制回路以实现对四轴飞行器姿态和位置的精确控制。文中阐述了控制系统的基本架构,内环负责稳定飞行器的姿态(如俯仰、滚转和偏航),外环则用于控制飞行器的空间位置和轨迹跟踪。通过Simulink搭建系统模型,实现控制算法的仿真验证,帮助理解飞行器动力学特性与PID控制器参数调节之间的关系,进而优化控制性能。; 适合人群:具备自动控制理论基础和Simulink使用经验的高校学生、科研人员及从事无人机控制系统的工程师;尤其适合开展飞行器控制、机器人导航等相关课题的研究者。; 使用场景及目标:①掌握四轴飞行器的动力学建模与控制原理;②学习内外环PID控制结构的设计与参数整定方法;③通过Simulink仿真验证控制策略的有效性,为实际飞行测试提供理论支持和技术储备;④应用于教学实验、科研项目或毕业设计中的控制系统开发。; 阅读建议:建议读者结合Simulink软件动手实践,逐步构建控制系统模型,重点关注PID参数对系统响应的影响,同时可扩展学习姿态传感器融合、轨迹规划等进阶内容,以全面提升飞行器控制系统的综合设计能力。
几十套表白源码,总有一套属于你(想看效果,请访问meidos.cn) 有爱心树、李峋同款动态爱心代码、爱心雨、六叶草、我们的回忆(超感人),还有HTML浪漫动态表白代码+音乐,等等 一生中女生总有很多属于她们自己的节日(比如恋爱纪念日、结婚纪念日、生日、情人节、女神节等等),在这些节日中向属于自己的女神展示几十套代码中的自己满意的那一套,让女神感动的稀里糊涂,源码可以改也可也不改(建议改,换成自己的语言比较好,让女神知道你用心了) 谁都有一个美好的憧憬,这么套源码,做个网站,一套设置为主页,其他设为分页也挺好的,让你们的爱情拥有一个自己独特的记忆的网站 几十套表白源码,总有一套属于你(想看效果,请访问meidos.cn) 有爱心树、李峋同款动态爱心代码、爱心雨、六叶草、我们的回忆(超感人),还有HTML浪漫动态表白代码+音乐,等等 一生中女生总有很多属于她们自己的节日(比如恋爱纪念日、结婚纪念日、生日、情人节、女神节等等),在这些节日中向属于自己的女神展示几十套代码中的自己满意的那一套,让女神感动的稀里糊涂,源码可以改也可也不改(建议改,换成自己的语言比较好,让女神知道你用心了) 谁都有一个美好的憧憬,这么套源码,做个网站,一套设置为主页,其他设为分页也挺好的,让你们的爱情拥有一个自己独特的记忆的网站 几十套表白源码,总有一套属于你(想看效果,请访问meidos.cn) 有爱心树、李峋同款动态爱心代码、爱心雨、六叶草、我们的回忆(超感人),还有HTML浪漫动态表白代码+音乐,等等 一生中女生总有很多属于她们自己的节日(比如恋爱纪念日、结婚纪念日、生日、情人节、女神节等等),在这些节日中向属于自己的女神展示几十套代码中的自己满意的那一套,让女神感动的稀里糊涂,源码可以改也可也不改(建议改,换成自己的语
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值