免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
簡單實現(xiàn)Hibernate分表的select,insert,delete及所有操作
簡單實現(xiàn)Hibernate分表的select,insert,delete及所有操作
關(guān)鍵字: 分表
作者:caocao(網(wǎng)絡(luò)隱士),http://www.caocao.name,http://www.caocao.mobi
轉(zhuǎn)載請注明來源:http://www.javaeye.com/topic/142404
由于項目需要隱士最近在.Net下面搞NHibernate來實現(xiàn)分表操作,參考了大量資料和JavaEye論壇上火熱的討論(這里謝過各位高人),結(jié)合對NHibernate代碼的研讀,隱士找到了一個簡單的實現(xiàn)方式,由于NHibernate和Hibernate同宗同源,隱士覺得這個簡單的實現(xiàn)方式同樣可以適用于Java環(huán)境里的Hibernate,所以下面的代碼是C#的。如果管理員覺得不適合發(fā)在Java版,請轉(zhuǎn).Net版。
先討論一下論壇上討論過的已有做法:
1、用JDBC直接開搞,出處:http://www.javaeye.com/topic/133832
如果直接搞,就沒有必要用Hibernate了。隱士要找的是在NHibernate框架下實現(xiàn)分表的所有操作。
2、對每個表建模,出處:http://www.javaeye.com/topic/133832
如果是幾十張表,建幾十個模,累死,代碼還很不好寫,將來的維護也是個大問題。如果要增加一張表,代碼可能要改死。
3、直接構(gòu)造select來實現(xiàn)讀取,出處:http://www.javaeye.com/topic/29514
僅僅實現(xiàn)了select,而且必須把表名寫死,沒有實現(xiàn)其它操作,也不利于開發(fā)和維護。
4、Hibernate 3.0里面的dynamic models可能可以實現(xiàn),出處:http://www.javaeye.com/topic/13167
這個沒有研究過,加上NHibernate還沒有跟上Hibernate 3.0,所以沒有該功能,也無法研究。
再討論一下隱士的幾個思路:
1、實現(xiàn)MultiTablesEntityPersister
在hbm.xml的class里可以指定persister來加載自己實現(xiàn)的persister,是不是可以實現(xiàn)MultiTablesEntityPersister來掌控全局呢?經(jīng)過隱士大量試驗表明幾乎不可能,Hibernate認準了一個class對應(yīng)一張table,大量代碼在AbstractEntityPersister里寫死了,如果要實現(xiàn)分表需求,基本相當于要重寫小半個Hibernate。隱士決定另找出路。
2、實現(xiàn)SessionFactory,Session,Table
如果可以通過繼承實現(xiàn)SessionFactory,Session,Table來實現(xiàn)分表需求,那也不錯。經(jīng)隱士研究源碼,發(fā)現(xiàn)沒有希望,接口都定死了,一些關(guān)鍵部分被seal,private,internal了,類似Java里的final,private,anonymous。除非改NHibernate源碼,這是隱士所不希望的,這樣改開源的源碼實在是不應(yīng)該。
幾個思路都被否決后,隱士轉(zhuǎn)向拿Configuration開刀,畢竟hbm.xml里的配置是在Configuration里解析的。一陣分析后發(fā)現(xiàn)Configuration把解析工作外包給HbmBinder,在HbmBinder里隱士找到了這句:
Java代碼 
tableName = mappings.NamingStrategy.TableName(tableNode.Value);
哈哈,這句就是萬惡之源了,原來可以通過Configuration.SetNamingStrategy(INamingStrategy namingStrategy)來注入我們自己的命名規(guī)范。隱士想到此處眼前豁然開朗,只要在Configuration.BuildSessionFactory前注入NamingStrategy,搞出來的SessionFactory就對分表這件事根本不知道,而且對于特定的class只認特定的table。不過也帶來一個副作用,就是有多少個分表,就要準備多少個SessionFacotry,再想想未必是副作用,SessionFactory維持的緩存就不會跨表打架,可以說這個想法是解決得很不錯的。
接著隱士動手開始試驗,以下代碼基于NHibernate-1.2.0.GA,MySQL 5.0,不過對于Java的Hibernate幾乎可以原封不動拿來用,這步留待看官們自己做了。
隱士隨便寫了個系統(tǒng)負載表,里面放幾個字段。這表也有實際意義,比如有一臺機器用來集中監(jiān)控幾十臺機器,監(jiān)控數(shù)據(jù)都放在一張表里會慢死的,一臺機器一張表,干凈。
Java代碼 
CREATE TABLE IF NOT EXISTS `system_1_loads` (
`loggingDate` datetime NOT NULL default '2006-01-01 00:00:00',
`cpuUsage` float NOT NULL default '0',
`memoryUsage` float NOT NULL default '0',
`bytesReceivedPerSecond` int(32) default '0',
`bytesSentPerSecond` int(32) default '0',
PRIMARY KEY  (`loggingDate`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
... system_2_loads ... system_3_loads ... ... system_10_loads
hibernate.cfg.xml照常規(guī)配置,一點都不需要改動,這里隱士不貼了。
SystemLoadDO.cs照常規(guī)寫。
Java代碼 
namespace DBPartitionTest
{
public class SystemLoadDO
{
#region Member Variables
protected DateTime _loggingDate;
protected float _cpuUsage;
protected float _memoryUsage;
protected int _bytesReceivedPerSecond;
protected int _bytesSentPerSecond;
#endregion
...
}
}
SystemLoadDO.hbm.xml照常規(guī)寫,注意class節(jié)點里的table,隱士寫了system_{0}_loads,看官說了,這個不能用呀,不要緊,反正后面會被NamingStrategy給替換掉。
Java代碼 
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="DBPartitionTest" assembly="DBPartitionTest">
<class name="SystemLoadDO" table="system_{0}_loads">
<id name="LoggingDate" type="DateTime" unsaved-value="2006-01-01 00:00:00">
<column name="loggingDate" sql-type="datetime" not-null="true" unique="true" index="PRIMARY"/>
<generator class="assigned" />
</id>
<property name="CpuUsage" type="float">
<column name="cpuUsage" sql-type="float" not-null="true" />
</property>
<property name="MemoryUsage" type="float">
<column name="memoryUsage" sql-type="float" not-null="true" />
</property>
<property name="BytesReceivedPerSecond" type="Int32">
<column name="bytesReceivedPerSecond" sql-type="int" not-null="false" />
</property>
<property name="BytesSentPerSecond" type="Int32">
<column name="bytesSentPerSecond" sql-type="int" not-null="false" />
</property>
</class>
</hibernate-mapping>
PartitionNamingStrategy.cs這個抽象類實現(xiàn)了接口INamingStrategy,它的構(gòu)造函數(shù)接受一個數(shù)字索引,通過改寫方法TableName來實現(xiàn)替換表名的工作,其他還是留給DefaultNamingStrategy。
Java代碼 
namespace DBPartitionTest
{
public abstract class PartitionNamingStrategy : INamingStrategy
{
private int index;
public int Index
{
get { return index; }
}
private string partitionTableName;
public string PartitionTableName
{
get { return partitionTableName; }
}
public abstract string PartitionTableFormat { get;}
public PartitionNamingStrategy(int index)
{
this.index = index;
this.partitionTableName = string.Format(PartitionTableFormat, index); // 根據(jù)索引構(gòu)造新的表名
}
#region INamingStrategy
public string ClassToTableName(string className)
{
return DefaultNamingStrategy.Instance.ClassToTableName(className);
}
public string PropertyToColumnName(string propertyName)
{
return DefaultNamingStrategy.Instance.PropertyToColumnName(propertyName);
}
public string TableName(string tableName)
{
if (PartitionTableFormat.Equals(tableName)) // 這句來實現(xiàn)表名替換
return PartitionTableName;
return DefaultNamingStrategy.Instance.TableName(tableName);
}
public string ColumnName(string columnName)
{
return DefaultNamingStrategy.Instance.ColumnName(columnName);
}
public string PropertyToTableName(string className, string propertyName)
{
return DefaultNamingStrategy.Instance.PropertyToTableName(className, propertyName);
}
#endregion
}
}
SystemLoadsNamingStrategy.cs是PartitionNamingStrategy的實現(xiàn)類,只需要實現(xiàn)屬性PartitionTableFormat,注意這里必須返回和SystemLoadDO.hbm.xml里一樣的串。實際項目里可以不必把這個串寫死在代碼里,Java這里就太簡單了,直接Spring里配一個Bean就搞定了,隱士這里只是驗證想法。
Java代碼 
namespace DBPartitionTest
{
public class SystemLoadsNamingStrategy : PartitionNamingStrategy
{
public SystemLoadsNamingStrategy(int index)
: base(index)
{
}
public override string PartitionTableFormat
{
get { return "system_{0}_loads"; }
}
}
}
Program.cs是程序入口,這段代碼生成了10個Configuration,10個Configuration創(chuàng)建了10個SessionFactory,每個SessionFactory互不干擾,自己認自己的分表操作,運行結(jié)果太長隱士就不附了。這里具體幾張表也可以做在配置文件里,這樣增加表、減少表可以做到不改代碼。
Java代碼 
namespace DBPartitionTest
{
public class Program
{
public static void Test()
{
for (int i = 1; i < 11; ++i)
{
Configuration configuration = new Configuration().SetNamingStrategy(new SystemLoadsNamingStrategy(i)).Configure();
ISessionFactory sessionFactory = configuration.BuildSessionFactory();
ISession session = null;
try
{
session = sessionFactory.OpenSession();
SystemLoadDO systemLoadDO = new SystemLoadDO();
systemLoadDO.LoggingDate = DateTime.Now;
systemLoadDO.CpuUsage = 80;
systemLoadDO.MemoryUsage = 70;
Console.WriteLine(systemLoadDO.LoggingDate.ToString());
session.Save(systemLoadDO);
session.Flush();
ICriteria criteria = session.CreateCriteria(typeof(SystemLoadDO));
criteria.AddOrder(Order.Desc("LoggingDate"));
criteria.SetFirstResult(0);
criteria.SetMaxResults(1);
systemLoadDO = criteria.UniqueResult<SystemLoadDO>();
Console.WriteLine(systemLoadDO.LoggingDate.ToString());
systemLoadDO.BytesReceivedPerSecond = 1024;
session.Flush();
session.Delete(systemLoadDO);
session.Flush();
}
catch (Exception e)
{
Console.WriteLine(e.InnerException);
Console.WriteLine(e.StackTrace);
Console.WriteLine(e.Message);
}
finally
{
if (session != null)
session.Close();
}
}
}
static void Main(string[] args)
{
Test();
}
}
}
總結(jié)一下,這個方法的優(yōu)點是秉承了Hibernate的設(shè)計思路,沒有修改Hibernate源碼,而且是通過Hibernate所允許的方式來進行操作,可以說拿到SessionFactory后所有操作都是和不分表一樣的,而且DO實例通過不同的SessionFactory保存、刪除就可實現(xiàn)跨表復(fù)制、刪除。由于SessionFactory不一樣,所以緩存維護也沒有影響。唯一的缺點就是要維護和分表數(shù)量一樣的SessionFactory,貌似也就是多寫幾行代碼而已。
隱士這里說完了,希望大家一起討論。
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Spring、Hibernate和范型
Eclipse快速上手Hibernate--5.組件映射
Hibernate Annotations 實戰(zhàn)
Eclipse下Hibernate入門
Hibernate 工具類
一個用myeclipse開發(fā)hibernate的入門例子 - 我愛JAVA - BlogJ...
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服