通过数据库数据构建树结构(一)
在本教程中,我们将向我们介绍如何通过数据库中的数据动态地构建树结构。我们将使用 NetBeans IDE 6.0 构建一个由两个页面组成的应用程序,其中第一页包含一个 JSF 1.2 ( Woodstock ) 树组件。接下来,我们将用数据库中的人物姓名填充树结构的一级节点,然
在本教程中,我们将向我们介绍如何通过数据库中的数据动态地构建树结构。我们将使用NetBeans IDE 6.0构建一个由两个页面组成的应用程序,其中第一页包含一个JSF 1.2(Woodstock)树组件。接下来,我们将用数据库中的人物姓名填充树结构的一级节点,然后用此人的行程信息来填充二级节点。TRIP节点将链接到第二个页面,其中显示该行程的详细信息。
目录
- |
设计主页 |
- |
连接数据库 |
- |
通过数据库表构建树结构 |
- |
添加详细信息页 |
- |
添加代码 |
- |
定义页面导航 |
- |
更多功能:将Action方法与树节点绑定 |
- |
关于树节点选择的注意事项 |
本教程将涉及以下技术和资源
JavaServer Faces组件/ |
|
Travel数据库 |
|
要利用NetBeans IDE 6.0的Java EE 5的性能,我们需要一个与Java EE 5规范完全兼容的应用服务器,比如说Sun Java System Application Server 9(GlassFish项目)。
本教程适用于GlassFish V2应用服务器。如果我们使用的是其他服务器,请参阅发行说明 和常见问题解答 了解各类问题和解决途径。有关所支持的服务器和Java EE平台的详细信息,请参阅发行说明。
设计主页
首先,我们将构建一个包含树组件和TRIP数据库表的主页。
- 创建一个新的Visual Web JSF应用程序项目,将其命名为DatabaseTree,然后启动Viual Web JSF框架。
- 从组件面板的Basic部分拖动一个树组件到页面上,键入“Travel信息”,然后按回车键。在“属性”窗口中,将id属性设置为displayTree,将clientSide属性设置为True。
当clientSide属性为True时,每个子节点(无论展开与否)都将发送给客户机,但它们只有在父节点展开时才可见。当clientSide为False时,仅呈现那些展开的父节点的子节点。
- 选择Tree Node 1,单击鼠标右键,然后从弹出菜单中选择“删除”。
在本应用程序中,我们将通过编程填充树中的节点,因此不需要初始化由IDE创建的树节点。如果未移除该节点,则JSP标记属性中设置的值将优先于运行时设置,并且页面将显示节点。
- 从组件面板拖动一个“消息组”组件到页面的边缘位置,如页面的右上角。
连接数据库
接下来,将该页与Travel数据源中的数据库表相连接,然后使用查询编辑器修改用于检索数据的SQL查询,使游客的姓名按字母顺序显示,旅行日期按时间顺序显示。
- 打开“服务”窗口,展开数据库节点,然后验证是否已连接到Travel数据库。
如果Travel数据库的jdbc节点标记显示为断开,并且无法展开该节点,则表明IDE未连接到该数据库。要连接Travel数据库,请右键单击Travel数据库的jdbc节点,然后从弹出菜单中选择“连接”。如果出现“连接”对话框,在输入travel作为口令,选中“在此期间记住密码”,然后单击“确定”按钮。
注:如果我们使用的是Apache Tomcat应用服务器,请将derbyClient.jar文件复制到
-
展开Travel数据库的jdbc节点,然后展开“表”节点
- 将“TRIP”节点拖放到可视编辑器中。
导航窗口净土在页面1部分显示“tripDataProvider”节点,在“SessionBean1”部分显示“tripRowSet”节点。
- 在导航窗口中,展开“SessionBean1”节点,右键单击“tripRowSet”节点,然后选择“编辑SQL语句”。
在编辑区域将显示带有TRIP表格图的查询编辑器。
- 从“服务”窗口拖出“行程 > 表 > 人员”节点,并将其放置在查询编辑器中的“TRIP”表图的旁边,如图3所示。
此时将出现另一个表图,且两个表图之间有链接或连接。
- 在“PERSON”表中,取消选中PERSONID复选框。
- 在查询编辑器的“设计网格”中,找到“TRAVEL.PERSON”表中的“NAME”行。单击“排序类型”单元格,然后从下拉列表中选择“升序”。
此操作将使数据库表中的名字按姓氏的字母顺序排列。
- 找到“TRAVEL.TRIP”表中的“DEPDATE”行。单击“排序类型”单元格,然后从下拉列表中选择“升序”。
此操作将行程日期按照从早到晚的顺序排列。
通过数据库表构建树结构
现在,我们已经在存储停息中添加了一个请求bean属性,可供应用程序的中两个页面使用。然后,我将在<span>prerender()</span>
方法中添加代码,用于通过TRIP和PERSON数据库表动态地构建树组件。
- 打开页面1,使导航窗口可见。在导航窗口中,右键单击“RequestBean1”节点,然后选择“编辑Java源代码”。
- 在“public class RequestBean1 extends AbstractRequestBean”构建函数中声明属性,如下所示:
<font><span>private Integer personId;</span><span><p></p></span></font>
- 在Java编辑器中单击鼠标右键,选择“重构 > 封装”字段。
- 在“封装字段”对话框中,选择创建getter和setter方法,如下图所示。确保变量声明中字段可见性为“私有”,存取器可见性是“公有”,然后单击“重构”按钮。
-
在Java编辑器中打开页面1,然后找到
<span><font>prerender</font></span>
方法。用以下粗体显示的代码替换<span>prerender</span>
<span>方法的主体部分</span>
<span>:</span>
代码示例1:页面1的<span>prerender</span>方法 |
<span><font><span> </span>public void prerender() {<strong><p></p></strong></font></span> ログイン後にコピー <strong><span><font><span> </span>// If the Request Bean's personId is set, then<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>// we just came back from the Trip page<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>// and had displayed a selected trip.<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>// We use the personId later to determine whether<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>// to expand a person's node<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>Integer expandedPersonId = getRequestBean1().getPersonId();<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>try {<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>// Set up the variables we will need<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>Integer currentPersonId = new Integer(-1);<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span><span> </span>// If nbrChildren is not 0 then this is a<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>// postback and we have our tree already<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>int nbrChildren = displayTree.getChildCount();<p></p></font></span></strong> ログイン後にコピー <strong><span><p><font> </font></p></span></strong> ログイン後にコピー ログイン後にコピー ログイン後にコピー <strong><span><font><span> </span>if (nbrChildren == 0) {<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>// List of outer (person) nodes<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span><span> </span>List outerChildren = displayTree.getChildren();<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>// Erase previous contents<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>outerChildren.clear();<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>// List of inner (trip) nodes<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>List innerChildren = null;<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>// Execute the SQL query<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>tripDataProvider.refresh();<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>// Iterate over the rows of the result set.<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>// Every time we encounter a new person, add first level node.<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>// Add second level trip nodes to the parent person node.<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>boolean hasNext = tripDataProvider.cursorFirst();<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>while (hasNext) {<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>Integer newPersonId =<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>(Integer) tripDataProvider.getValue(<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>"TRIP.PERSONID");<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>if (!newPersonId.equals(currentPersonId)) {<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>currentPersonId = newPersonId;<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>TreeNode personNode = new TreeNode();<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>personNode.setId("person" + newPersonId.toString());<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>personNode.setText(<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>(String)tripDataProvider.getValue(<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>"PERSON.NAME"));<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>// If the request bean passed a person id,<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span><span> </span>// expand that person's node<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>personNode.setExpanded(newPersonId.equals<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>(expandedPersonId));<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>outerChildren.add(personNode);<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>innerChildren = personNode.getChildren();<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>}<p></p></font></span></strong> ログイン後にコピー <strong><span><p><font> </font></p></span></strong> ログイン後にコピー ログイン後にコピー ログイン後にコピー <strong><span><font><span> </span>// Create a new trip node<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>TreeNode tripNode = new TreeNode();<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>tripNode.setId("trip" +<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>tripDataProvider.getValue("TRIP.TRIPID").toString());<p></p></font></span></strong> ログイン後にコピー ログイン後にコピー <strong><span><font><span> </span>tripNode.setText(<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>tripDataProvider.getValue("TRIP.DEPDATE").toString());<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>tripNode.setUrl("/faces/Trip.jsp?tripId=" +<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>tripDataProvider.getValue("TRIP.TRIPID").toString());<p></p></font></span></strong> ログイン後にコピー ログイン後にコピー <strong><span><font><span> </span>innerChildren.add(tripNode);<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>hasNext = tripDataProvider.cursorNext();<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>}<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>}<p></p></font></span></strong> ログイン後にコピー <strong><span><p><font> </font></p></span></strong> ログイン後にコピー ログイン後にコピー ログイン後にコピー <strong><span><font><span> </span>} catch (Exception ex) {<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span>log("Exception gathering tree data", ex);<p></p></font></span></strong> ログイン後にコピー <strong><span><font><span> </span><span> </span>error("Exception gathering tree data: " + ex);<p></p></font></span></strong> ログイン後にコピー <font><strong><span><span> </span>} </span></strong><span><p></p></span></font> ログイン後にコピー <span><font><span> </span>}<p></p></font></span> ログイン後にコピー <span><font><span> </span><p></p></font></span> ログイン後にコピー |
此代码读取按照personId排序的行程记录。对于每个personId,此代码会在树结构中创建一个新的一级节点。然后,为每一个与该personId关联的行程创建一个二级节点(嵌套节点)。最后,将二级行程节点与<span>tripNode_action</span>
方法(稍后在本部分中创建)绑定在一起。
-
在源代码中单击鼠标右键,然后从弹出菜单中选择Fix Imports修复“无法找到类”的错误。在“Fix All Imports”对话框中,请确保
<span>java.util.List</span>
出现在列出的字段中,然后单击“确定”按钮。 - 运行项目。
Web浏览器将打开并显示一个树组件,其中每个一级节点显示人名,如下图所示。展开节点可显示此人的旅行日期。请注意,人名按姓氏的字母顺序显示,日期按时间顺序显示。在下一节中,我们将添加一些代码,以便用户在单击Trip节点时导航至第二页。第二个页面将显示用户所选行程的详细信息。
添加详细信息页
现在,我们需要为应用程序添加第二个页面,如下图所示。此页使用“属性表单”组件动态地显示用户在第一页上所选行程的详细信息。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









夏の雨の後には、美しく魔法のような特別な天気の風景、虹がよく見られます。これも写真撮影ではなかなか出会えない光景で、とてもフォトジェニックです。虹が現れるにはいくつかの条件があります。まず、空気中に十分な水滴があること、そして、低い角度から太陽が当たることです。そのため、雨が上がった午後が最も虹が見えやすいのです。ただし、虹の発生は天候や光などの条件に大きく左右されるため、一般に虹の持続時間は短く、見頃や撮影に最適な時間はさらに短くなります。では、虹に遭遇したとき、どうすれば虹を適切に記録し、高品質の写真を撮ることができるでしょうか? 1. 虹を探す 上記の条件に加えて、虹は通常、太陽光の方向に現れます。つまり、太陽が西から東に輝いている場合、虹は東に現れやすくなります。

先週、社内の辞任と社外からの批判が相次ぐ中、OpenAIは内外のトラブルに見舞われた。 - 未亡人姉妹への侵害が世界中で白熱した議論を巻き起こした - 「覇権条項」に署名した従業員が次々と暴露 - ネットユーザーがウルトラマンの「」をリストアップ噂の払拭: Vox が入手した漏洩情報と文書によると、アルトマンを含む OpenAI の上級幹部はこれらの株式回収条項をよく認識しており、承認しました。さらに、OpenAI には、AI セキュリティという深刻かつ緊急の課題が直面しています。最近、最も著名な従業員2名を含むセキュリティ関連従業員5名が退職し、「Super Alignment」チームが解散したことで、OpenAIのセキュリティ問題が再び注目を集めている。フォーチュン誌は OpenA を報じた。

Apple の最新リリースの iOS18、iPadOS18、および macOS Sequoia システムでは、さまざまな理由で紛失または破損した写真やビデオをユーザーが簡単に回復できるように設計された重要な機能が写真アプリケーションに追加されました。この新機能では、写真アプリのツール セクションに「Recovered」というアルバムが導入され、ユーザーがデバイス上に写真ライブラリに含まれていない写真やビデオがある場合に自動的に表示されます。 「Recovered」アルバムの登場により、データベースの破損、カメラ アプリケーションが写真ライブラリに正しく保存されない、または写真ライブラリを管理するサードパーティ アプリケーションによって失われた写真やビデオに対する解決策が提供されます。ユーザーはいくつかの簡単な手順を実行するだけで済みます

MySQLi を使用して PHP でデータベース接続を確立する方法: MySQLi 拡張機能を含める (require_once) 接続関数を作成する (functionconnect_to_db) 接続関数を呼び出す ($conn=connect_to_db()) クエリを実行する ($result=$conn->query()) 閉じる接続 ( $conn->close())

PHP でデータベース接続エラーを処理するには、次の手順を使用できます。 mysqli_connect_errno() を使用してエラー コードを取得します。 mysqli_connect_error() を使用してエラー メッセージを取得します。これらのエラー メッセージをキャプチャしてログに記録することで、データベース接続の問題を簡単に特定して解決でき、アプリケーションをスムーズに実行できるようになります。

2024 年は AI 携帯電話元年です。AI スマート テクノロジーにより、携帯電話はますます効率的かつ便利に使用できるようになります。最近、今年の初めにリリースされたGalaxy S24シリーズは、生成AIエクスペリエンスを再び改善しました。以下で詳細な機能の紹介を見てみましょう。 1. 生成 AI は Samsung Galaxy S24 シリーズを強力に強化します。Galaxy S24 シリーズは、Galaxy AI によって強化され、多くのインテリジェント アプリケーションをもたらします。これらの機能は Samsung One UI6.1 と緊密に統合されており、ユーザーはいつでも便利なインテリジェントなエクスペリエンスを得ることができ、パフォーマンスが大幅に向上します。携帯電話の効率と使いやすさ。 Galaxy S24 シリーズで先駆けて開発されたサークルアンド検索機能は、長押しするだけで実現できる機能です。

70B モデルでは、数秒で 1,000 個のトークンを生成でき、これはほぼ 4,000 文字に相当します。研究者らは Llama3 を微調整し、高速化アルゴリズムを導入しました。ネイティブ バージョンと比較して、速度は 13 倍高速になりました。速いだけでなく、コード書き換えタスクのパフォーマンスは GPT-4o をも上回ります。この成果は、人気の AI プログラミング成果物 Cursor を開発したチーム、anysphere によるもので、OpenAI も投資に参加しました。有名な高速推論アクセラレーション フレームワークである Groq では、70BLlama3 の推論速度は 1 秒あたり 300 トークンを超える程度であることを知っておく必要があります。 Cursor の速度により、ほぼ瞬時に完全なコード ファイル編集を実現すると言えます。カースと言うと良い奴だと言う人もいる

仮想市場の拡大は仮想通貨の流通と不可分であり、当然仮想通貨の送金問題とも不可分である。一般的な転送エラーはアドレス コピー エラーで、もう 1 つのエラーはチェーン選択エラーです。仮想通貨を間違ったチェーンに転送することは依然として厄介な問題ですが、初心者は転送操作の経験が浅いため、間違ったチェーンを転送してしまうことがよくあります。間違ったリンクはサードパーティのプラットフォームを通じて取得できますが、成功しない可能性があります。次に、編集者が仮想資産をより適切に管理するために役立つ詳細を説明します。間違った仮想通貨チェーンを取り戻すには?間違ったチェーンに転送された仮想通貨を取得するプロセスは複雑で困難な場合がありますが、転送詳細を確認し、取引所またはウォレットプロバイダーに連絡し、互換性のあるウォレットに秘密キーをインポートし、クロスチェーンブリッジツールを使用することで、
