一个NHibernate的BUG
一、背景 我们现在做的项目,用NHibernate实现数据访问层。 访问数据时,有的数据库表是确定的:有明确的表名、字段名。这时候按照常规的方法处理即可:建立数据库表到类的映射,使用HQL读写数据库。 但有的数据访问,所针对的数据库表是不确定的,在运行阶
一、背景
我们现在做的项目,用NHibernate实现数据访问层。
访问数据时,有的数据库表是确定的:有明确的表名、字段名。这时候按照常规的方法处理即可:建立数据库表到类的映射,使用HQL读写数据库。
但有的数据访问,所针对的数据库表是不确定的,在运行阶段确定访问哪些数据库表的哪些字段。数据库表和字段都不确定,自然没办法建议O-R映射,只好构造SQL语句了。
既然已经用了NHibernate,我们利用SQL访问数据库时,也仍然使用NHibernate。主要是想利用它管理的Session,还有对分页查询的支持:可以指定开始行,还有所需要的总行数。
就因为贪这个便宜,出问题了。
二、错误
使用SQL(而不是HQL)访问数据库,而且加上访问范围(开始行或总行数),有时候会出现奇怪的问题:有的字段,在数据库中明明有值,但就是读不出来。
例如,有一个数据库表,表的定义大致是:MyTable(Id, Name, FromPoint)。
现在需要查询其中的前10条记录,利用下面的SQL语句:
select Id, Name, FromPoint from MyTable
创建好SQL查询后,设置查询范围:
... var query = session.CreateSQLQuery(sql); query.SetFirstResult(0); query.SetMaxResults(10); ...
对于执行结果,期望的是,每条记录有三个字段。但实际上,只返回前两个字段的值,第三个字段,FromPoint的值,没有返回。
查看NHibernate的日志,所生成的SQL是:
select Id, Name from (select Id, Name, FromPoint from MyTable) where rownum<=10
这实在令人费解。
三、原因
在网上搜索,找不到原因。只好祭出最后的杀手锏:跟踪源代码。
结论是:NHibernate在解析SQL语句时有问题,导致过滤掉了不该过滤掉的列。
具体地说,在类 NHibernate.Dialect.Dialect的方法 ExtractColumnOrAliasNames 中有如下代码:
if (token.StartsWithCaseInsensitive("select")) continue; if (token.StartsWithCaseInsensitive("distinct")) continue; if (token.StartsWithCaseInsensitive(",")) continue; if (token.StartsWithCaseInsensitive("from")) break;
这段代码的本意,是不将select、distinct等SQL保留字作为列,而且一旦遇到from保留字,就意味着列结束。
问题在于,它用了StartsWith,而不是整词判断,从而误伤了以这些关键字开头的字段。而且一旦有以from开始的字段,后面的字段都被过滤掉了。
四、办法
出问题的方法 ExtractColumnOrAliasNames 是 static internal 的,没有修改机会。我们只好绕道走:自行加上rownum的过滤条件。
本来要借助NHibernate实现跨数据库,我还一直告诫小伙伴们避免使用Oracle、SQL Server等数据库管理系统特定的SQL语法来着。
不少程序员会本能地想到一个解决方法:既然是开源的,而且错误原因找到了,拿过来修改好,编译一个新版本用就OK。我对此明确表示不赞成,一方面,这会脱离NHibernate主线版本的发展,另一方面,也给组件的引用带来不便:我们正在用Spring.NET管理NHibernate,build一个自己的版本,要设置一堆元信息,想想就头大。
五、范围
就我目前所知,该BUG出现的情景如下:
使用原生SQL访问数据库;设置了FirstResult、MaxResults等查询结果范围;最早的引入版本不详,最新的版本中,从源代码上判断,此问题仍然存在;我们使用的是Oracle数据库,其它数据库管理系统不详。 
Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

Video Face Swap
Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas

Kongsi kaedah pembungkusan projek PyCharm yang mudah dan mudah difahami Dengan populariti Python, semakin ramai pembangun menggunakan PyCharm sebagai alat utama untuk pembangunan Python. PyCharm ialah persekitaran pembangunan bersepadu yang berkuasa yang menyediakan banyak fungsi mudah untuk membantu kami meningkatkan kecekapan pembangunan. Salah satu fungsi penting ialah pembungkusan projek. Artikel ini akan memperkenalkan cara untuk membungkus projek dalam PyCharm dengan cara yang mudah dan mudah difahami, dan memberikan contoh kod khusus. Mengapa projek pakej? Dibangunkan dalam Python

Teorem terakhir Fermat, akan ditakluki oleh AI? Dan bahagian yang paling bermakna dari keseluruhannya ialah Teorem Terakhir Fermat, yang akan diselesaikan oleh AI, dengan tepat untuk membuktikan bahawa AI tidak berguna. Suatu ketika dahulu, matematik tergolong dalam alam kecerdasan manusia yang tulen kini, wilayah ini dihuraikan dan diinjak oleh algoritma canggih. Imej Teorem Terakhir Fermat ialah teka-teki "terkenal" yang telah membingungkan ahli matematik selama berabad-abad. Ia telah terbukti pada tahun 1993, dan kini ahli matematik mempunyai rancangan besar: untuk mencipta semula bukti menggunakan komputer. Mereka berharap bahawa sebarang ralat logik dalam versi bukti ini boleh disemak oleh komputer. Alamat projek: https://github.com/riccardobrasca/flt

Tajuk: Ketahui lebih lanjut tentang PyCharm: Cara yang cekap untuk memadamkan projek Dalam beberapa tahun kebelakangan ini, Python, sebagai bahasa pengaturcaraan yang berkuasa dan fleksibel, telah digemari oleh semakin ramai pembangun. Dalam pembangunan projek Python, adalah penting untuk memilih persekitaran pembangunan bersepadu yang cekap. Sebagai persekitaran pembangunan bersepadu yang berkuasa, PyCharm menyediakan pembangun Python dengan banyak fungsi dan alatan yang mudah, termasuk memadamkan direktori projek dengan cepat dan cekap. Berikut akan memberi tumpuan kepada cara menggunakan padam dalam PyCharm

PyCharm ialah persekitaran pembangunan bersepadu Python yang berkuasa yang menyediakan pelbagai alatan pembangunan dan konfigurasi persekitaran, membolehkan pembangun menulis dan menyahpepijat kod dengan lebih cekap. Dalam proses menggunakan PyCharm untuk pembangunan projek Python, kadangkala kita perlu membungkus projek ke dalam fail EXE boleh laku untuk dijalankan pada komputer yang tidak mempunyai persekitaran Python yang dipasang. Artikel ini akan memperkenalkan cara menggunakan PyCharm untuk menukar projek kepada fail EXE boleh laku dan memberikan contoh kod khusus. kepala

Apakah yang dimaksudkan dengan pepijat permainan? Semasa proses bermain permainan, kami sering menghadapi beberapa ralat atau masalah yang tidak dijangka, seperti watak tersekat, tugas tidak dapat diteruskan, skrin berkelip, dsb. Fenomena abnormal ini dipanggil pepijat permainan, iaitu, kesalahan atau kesilapan dalam permainan. Dalam artikel ini, kami akan meneroka maksud pepijat permainan dan kesannya terhadap pemain dan pembangun. Pepijat permainan merujuk kepada ralat yang berlaku semasa pembangunan atau pengendalian permainan, menyebabkan permainan gagal berjalan seperti biasa atau berkelakuan di luar jangkaan. Kesilapan ini mungkin disebabkan oleh

Cara Membuat Senarai Runcit pada iPhone dalam iOS17 Mencipta Senarai Runcit dalam apl Peringatan adalah sangat mudah. Anda hanya menambah senarai dan mengisinya dengan item anda. Apl ini secara automatik mengisih item anda ke dalam kategori, dan anda juga boleh bekerjasama dengan pasangan anda atau rakan kongsi rata untuk membuat senarai barang yang anda perlu beli dari kedai. Berikut ialah langkah penuh untuk melakukan ini: Langkah 1: Hidupkan Peringatan iCloud Walaupun kedengaran pelik, Apple berkata anda perlu mendayakan peringatan daripada iCloud untuk mencipta Senarai Runcit pada iOS17. Berikut ialah langkah untuknya: Pergi ke apl Tetapan pada iPhone anda dan ketik [nama anda]. Seterusnya, pilih i

Memandangkan persidangan WWDC Apple 2024 mencapai kesimpulan yang berjaya, bukan sahaja macos15 diumumkan, tetapi kemas kini sistem iOS18 baharu Apple paling menarik perhatian Walaupun terdapat banyak ciri baharu, sebagai versi pertama iOS18 Apple, orang ramai pasti tertanya-tanya sama ada ia adalah perlu untuk menaik taraf Apple iOS18, apakah jenis pepijat yang terdapat dalam keluaran terbaru Apple iOS18? Selepas penilaian penggunaan sebenar, berikut ialah ringkasan pepijat Apple iOS18, mari kita lihat. Pada masa ini, ramai pengguna iPhone tergesa-gesa untuk menaik taraf kepada iOS18 Namun, pelbagai pepijat sistem menyebabkan orang tidak selesa. Sesetengah penulis blog berkata bahawa anda harus berhati-hati semasa menaik taraf kepada iOS18 kerana "terdapat banyak pepijat." Blogger itu berkata bahawa jika iPhone anda adalah

Microsoft menjemput ahli projek WindowsInsider dalam saluran Canary dan Dev untuk menguji dan mengalami aplikasi Paint baharu Nombor versi terkini ialah 11.2306.30.0. Ciri baharu yang paling penting dalam kemas kini versi ini ialah fungsi potong satu klik. Pengguna hanya perlu mengklik sekali untuk menghapuskan latar belakang secara automatik dan menyerlahkan badan utama gambar, menjadikannya lebih mudah untuk pengguna melakukan operasi seterusnya. Seluruh langkah adalah sangat mudah. Pengguna mengimport gambar dalam aplikasi susun atur baharu, dan kemudian mengklik butang "movebackground" pada bar alat untuk memadamkan latar belakang dalam gambar latar belakang.
