编辑“︁
Low Level Database Access
”︁
跳转到导航
跳转到搜索
警告:
您没有登录。如果您进行任何编辑,您的IP地址会公开展示。如果您
登录
或
创建账号
,您的编辑会以您的用户名署名,此外还有其他益处。
反垃圾检查。
不要
加入这个!
{{Navigation for Marauroa Top|Internals}} {{Navigation for Marauroa Developers}} {{Database Access}} __TOC__ 本文介绍了Marauroa内部如何访问数据库以及如何添加自己的表. Marauroa数据库的表结构请参阅 [[Marauroa Database Structure]]. 你也许需要先看一下 [[High Level Database Access]] . 它说明了从程序代码访问数据库的高级API. == 数据库抽象 == 低级数据库访问代码封装在DAO类中。 只有这些类使用JDBC将SQL查询发送到数据库. 通过以下位置获取DBTransaction对象来启动事务 [http://stendhal.game-host.org/hudson/job/marauroa_HEAD/javadoc/marauroa/server/db/TransactionPool.html TransactionPool]. 然后使用 [http://stendhal.game-host.org/hudson/job/marauroa_HEAD/javadoc/marauroa/server/db/DBTransaction.html DBTransaction] 对象的方法与数据库交谈. 请注意,许多方法都希望将参数映射作为第二个参数. 这使您可以在SQL语句中用 <nowiki>[variables]</nowiki> 无需担心转义输入参数以防止SQL注入攻击. 但是,DBTransaction本身不执行SQL语句。 它在内部将它们转发到DatabaseAdapter的子类。 这是一个非常小的抽象层,用于隐藏不同数据库系统使用的SQL方言. [[Image:Classdiagram_database_access.png]] == 编写你自己的 DAO == 编写自己的DAO类时,请遵循以下规则 * 使用 <nowiki>[variables]</nowiki> 传送不受信任的数据,因为它将被自动转义以防止SQL注入攻击 * 在DAORegistry (see next section) 中注册你的类,而不是直接调用构造函数 * 使用 dbTransaction.getLastInsertId() 而不是 "select @@identity" 并在相关插入内容后直接调用 * 尝试避免使用数据库系统特定的代码(特别注意通常支持的SQL函数) * 为所有方法提供两个签名: 一个以DBTransaction作为第一个参数,另一个没有。 第二个应该只是获取事务本身,调用第一个,然后提交/回滚事务 == 扩展已有的 DAO == DAO类永远不能直接实例化。 相反,您应该(并且marauroa确实)使用DAORegistry。 这使您可以编写marauroa提供的DAO的子类并进行注册。 如果您熟悉Spring,这是一个类似的概念。 但是没有所有大量的xml配置文件,参数注入和接口,只有一个实现. 假设您想用SomeGameCharacterDAO类将CharacterDAO子类化: <source lang="java"> public class SomeGameCharacterDAO extends CharacterDAO { ... </source> 您只需要简单地注册为 <source lang="java"> DAORegistry.get().register(CharacterDAO.class, new SomeGameCharacterDAO()); </source> 注意:在注册调用中,第一个参数是您要替换的父类. == Adding support for another database system == Marauroa尝试严格遵循SQL标准。 但是,不可能编写适用于所有通用数据库系统的SQL语句,因为每个数据库系统都有自己的方言。 幸运的是只有微小的差异. 例如 MySQL 要求 "create table" 语句以 "TYPE=InnoDB" 结束. Marauroa 使用 [http://stendhal.game-host.org/hudson/job/marauroa_HEAD/javadoc/marauroa/server/db/adapter/DatabaseAdapter.html DatabaseAdapter] 接口在隐藏这些差异. 已经为此接口提供了一个默认实现,即 [http://stendhal.game-host.org/hudson/job/marauroa_HEAD/javadoc/marauroa/server/db/adapter/AbstractDatabaseAdapter.html AbstractDatabaseAdapter] ([http://arianne.cvs.sf.net/viewvc/arianne/marauroa/src/marauroa/server/db/adapter/AbstractDatabaseAdapter.java?view=markup source]). And we provide a MySQLDatabaseAdapter ([http://arianne.cvs.sf.net/viewvc/arianne/marauroa/src/marauroa/server/db/adapter/MySQLDatabaseAdapter.java?view=markup source]) and a H2DatabaseAdapter ([http://arianne.cvs.sf.net/viewvc/arianne/marauroa/src/marauroa/server/db/adapter/H2DatabaseAdapter.java?view=markup source]), too. 请查阅这些java文件。 为其他数据库系统添加更多适配器应该非常容易。 注意:我们对接受这些适配器并将其添加到主要代码库非常感兴趣。 == 更新数据库结构 == 如果添加表和列,则最好在服务器启动时自动创建它们。 JDBCHelper类中的runSQLScript()方法可用于执行SQL脚本。 注意:应该使用“create table if not exists”代替简单的“create table”,以便可以在每个服务器启动时执行脚本,而不必担心表是否已经存在. 不幸的是,SQL中没有“如果不存在则创建列”子句。 因此,如果需要将列添加到现有表中,则需要自己进行检查. 以下示例显示了用于将新结果列添加到passwordChange表的代码。 在添加该列之前,仅记录成功的密码更改。 因此,结果列应初始化为1. <source lang="java"> if (!transaction.doesColumnExist("passwordChange", "result")) { transaction.execute("ALTER TABLE passwordChange ADD COLUMN (result TINYINT);", null); transaction.execute("UPDATE passwordChange SET result=1 WHERE result IS NULL", null); } </source> {{#breadcrumbs: [[Marauroa]] | [[Navigation for Marauroa Developers|Internals]] | [[Low Level Database Access|低级数据库访问]] }}
摘要:
请注意,所有对gamedev的贡献均可能会被其他贡献者编辑、修改或删除。如果您不希望您的文字作品被随意编辑,请不要在此提交。
您同时也向我们承诺,您提交的内容为您自己所创作,或是复制自公共领域或类似自由来源(详情请见
Gamedev:著作权
)。
未经许可,请勿提交受著作权保护的作品!
取消
编辑帮助
(在新窗口中打开)
该页面使用的模板:
Template:Br
(
编辑
)
Template:Database Access
(
编辑
)
Template:Navigation Menu Marauroa General
(
编辑
)
Template:Navigation Menu Marauroa Internals
(
编辑
)
Template:Navigation Menu Marauroa Users
(
编辑
)
Template:Navigation for Marauroa Developers
(
编辑
)
Template:Navigation for Marauroa Top
(
编辑
)
导航菜单
个人工具
未登录
讨论
贡献
创建账号
登录
命名空间
页面
讨论
不转换
不转换
简体
繁體
大陆简体
香港繁體
澳門繁體
大马简体
新加坡简体
臺灣正體
查看
阅读
编辑
查看历史
更多
搜索
导航
首页
最近更改
随机页面
MediaWiki帮助
工具
链入页面
相关更改
特殊页面
页面信息