首页 > 代码库 > NHibernate动态扩展表
NHibernate动态扩展表
NHibernate动态扩展属性小记
http://www.infoq.com/articles/hibernate-custom-fields 的NHibernate实现因为动态扩展表需要修改hbm.xml文件,所以hbm.xml文件必须放在可编辑的路径中。
- hibernate.cfg.xml中添加节点
1 <property name="hbm2ddl.auto">update</property>
- 假设我有一张表Contract,hbm文件如下
1 <?xml version="1.0" encoding="utf-8" ?> 2 <hibernate-mapping 3 xmlns="urn:nhibernate-mapping-2.2" 4 assembly="Test" 5 namespace="Test.DynamicEntityTest" 6 auto-import="true" 7 default-access="property" 8 default-cascade="none" 9 default-lazy="true">10 11 <class name="Contract" table="contract">12 <id name="Id" column="id">13 <generator class="native" />14 </id>15 16 <property name="Name" column="name" type="string" />17 18 <dynamic-component insert="true" name="CustomProperties" optimistic-lock="true" unique="false" update="true">19 </dynamic-component>20 21 </class>22 </hibernate-mapping>
- 对应类为
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Web; 5 6 namespace Test.DynamicEntityTest 7 { 8 public class Contract : CustomizableEntity 9 {10 public virtual int Id { get; set; }11 public virtual string Name { get; set; }12 }13 }
- Contract类继承自CustomizeableEntity
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Web; 5 6 namespace Test.DynamicEntityTest 7 { 8 public abstract class CustomizableEntity 9 {10 private IDictionary<string, object> customProperties;11 12 public virtual IDictionary<string, object> CustomProperties13 {14 get15 {16 if (customProperties == null)17 {18 customProperties = new Dictionary<string, object>();19 }20 return customProperties;21 }22 set23 {24 this.customProperties = value;25 }26 }27 28 public virtual object GetValueOfCustomField(string name)29 {30 return CustomProperties[name];31 }32 33 public virtual void SetValueOfCustomField(string name, object value)34 {35 CustomProperties[name] = value;36 }37 }38 }
- 我们再创建一个HibernateUtil,添加了从我们指定的目录读取hbm.xml文件
1 using NHibernate; 2 using NHibernate.Cfg; 3 using NHibernate.Cfg.MappingSchema; 4 using NHibernate.Mapping; 5 using System; 6 using System.Collections.Generic; 7 using System.IO; 8 using System.Linq; 9 using System.Text; 10 using System.Xml; 11 12 namespace Test.DynamicEntityTest 13 { 14 public class HibernateUtil 15 { 16 private static HibernateUtil instance; 17 private Configuration configuration; 18 private ISessionFactory sessionFactory; 19 private ISession session; 20 21 public static HibernateUtil Instance 22 { 23 get 24 { 25 if (instance == null) 26 { 27 instance = new HibernateUtil(); 28 } 29 return instance; 30 } 31 } 32 33 private ISessionFactory SessionFactory 34 { 35 get 36 { 37 if (sessionFactory == null) 38 { 39 var config = Configuration.Configure(); 40 41 var dir = new DirectoryInfo("hbm"); 42 foreach (var file in dir.GetFiles("*.hbm.xml")) 43 { 44 var typeName = file.Name.Substring(0, file.Name.IndexOf(‘.‘)); 45 var namedDocument = config.LoadMappingDocument(new XmlTextReader(file.FullName), null); 46 config.AddDeserializedMapping(namedDocument.Document, namedDocument.Name); 47 } 48 49 sessionFactory = config.BuildSessionFactory(); 50 } 51 return sessionFactory; 52 } 53 } 54 55 private Configuration Configuration 56 { 57 get 58 { 59 if (configuration == null) 60 { 61 configuration = new Configuration(); 62 } 63 return configuration; 64 } 65 } 66 67 public ISession CurrentSession 68 { 69 get 70 { 71 if (session == null) 72 { 73 session = SessionFactory.OpenSession(); 74 } 75 return session; 76 } 77 } 78 79 public void Reset() 80 { 81 if (session != null) 82 { 83 session.Flush(); 84 if (session.IsOpen) 85 { 86 session.Close(); 87 } 88 } 89 90 if (sessionFactory != null) 91 { 92 sessionFactory.Close(); 93 } 94 95 this.configuration = null; 96 this.sessionFactory = null; 97 this.session = null; 98 } 99 100 public PersistentClass getClassMapping(Type entityClass)101 {102 return Configuration.GetClassMapping(entityClass);103 }104 }105 }
- 还有CustomEntityManager用于添加自定义属性
1 using NHibernate.Cfg; 2 using NHibernate.Mapping; 3 using System; 4 using System.Collections.Generic; 5 using System.Linq; 6 using System.Text; 7 8 namespace Test.DynamicEntityTest 9 {10 public class CustomizableEntityManager11 {12 private Component customProperties;13 public Type EntityType { get; private set; }14 15 public CustomizableEntityManager(Type entityType)16 {17 this.EntityType = entityType;18 }19 20 public Component CustomProperties21 {22 get23 {24 if (customProperties == null)25 {26 var property = PersistentClass.GetProperty("CustomProperties");27 customProperties = (Component)property.Value;28 }29 30 return customProperties;31 }32 }33 34 public void AddCustomFields(string[] names)35 {36 foreach (var name in names)37 {38 InnerAddCustomField(name);39 }40 UpdateMapping();41 }42 43 public void AddCustomField(string name)44 {45 InnerAddCustomField(name);46 UpdateMapping();47 }48 49 private void InnerAddCustomField(string name)50 {51 var simpleValue = http://www.mamicode.com/new SimpleValue();52 simpleValue.AddColumn(new Column(name));53 simpleValue.TypeName = typeof(string).Name;54 55 var persistentClass = PersistentClass;56 simpleValue.Table = persistentClass.Table;57 58 var property = new Property();59 property.Name = name;60 property.Value =http://www.mamicode.com/ simpleValue;61 CustomProperties.AddProperty(property);62 }63 64 private void UpdateMapping()65 {66 MappingManager.UpdateClassMapping(this);67 HibernateUtil.Instance.Reset();68 }69 70 private PersistentClass PersistentClass71 {72 get73 {74 return HibernateUtil.Instance.getClassMapping(this.EntityType);75 }76 }77 }78 }
- 最后是MappingManager,用来修改hbm.xml文件
1 using NHibernate.Mapping; 2 using System; 3 using System.Collections.Generic; 4 using System.Linq; 5 using System.Reflection; 6 using System.Text; 7 using System.Xml; 8 using System.Xml.Linq; 9 10 namespace Test.DynamicEntityTest11 {12 public class MappingManager13 {14 private static const string DYNAMIC_COMPONENT_TAG = "dynamic-component";15 16 public static void UpdateClassMapping(CustomizableEntityManager entityManager)17 {18 var session = HibernateUtil.Instance.CurrentSession;19 var entityType = entityManager.EntityType;20 var fileName = string.Format("hbm/{0}.hbm.xml", entityType.Name);21 var xDocument = new XmlDocument();22 xDocument.Load(fileName);23 24 var dynamicElements = xDocument.DocumentElement.GetElementsByTagName(DYNAMIC_COMPONENT_TAG);25 XmlElement dynamicElement = null;26 if (dynamicElements.Count > 0)27 {28 dynamicElements[0].InnerXml = string.Empty;29 dynamicElement = dynamicElements[0] as XmlElement;30 }31 32 foreach (var property in entityManager.CustomProperties.PropertyIterator)33 {34 var newElement = CreatePropertyElement(xDocument,dynamicElement.NamespaceURI, property);35 dynamicElement.AppendChild(newElement);36 }37 38 Console.WriteLine(xDocument.OuterXml);39 xDocument.Save(fileName);40 }41 42 private static XmlElement CreatePropertyElement(XmlDocument document,string parentNamespace, NHibernate.Mapping.Property property)43 {44 var element = document.CreateElement("property", parentNamespace);45 46 element.SetAttribute("name", property.Name);47 element.SetAttribute("column", ((Column)property.ColumnIterator.First()).Name);48 element.SetAttribute("type", property.Type.ReturnedClass.Name);49 element.SetAttribute("not-null", "false");50 return element;51 }52 }53 }
- 现在是测试代码
1 using System; 2 using Test.DynamicEntityTest; 3 4 namespace Test 5 { 6 public class Program 7 { 8 static void Main(params string[] args) 9 {10 CustomEntityTest();11 Console.Read();12 }13 14 static void CustomEntityTest()15 {16 var fieldName = "email";17 var value = http://www.mamicode.com/"alex@test.com";18 var session = HibernateUtil.Instance.CurrentSession;19 var contactEntityManager = new CustomizableEntityManager(typeof(Contract));20 contactEntityManager.AddCustomField(fieldName);21 22 session = HibernateUtil.Instance.CurrentSession;23 var trans = session.BeginTransaction();24 try25 {26 //add27 var contact = new Contract();28 contact.Name = "Contact Name";29 contact.SetValueOfCustomField(fieldName, value);30 var id = session.Save(contact);31 32 //get33 contact = session.Get<Contract>(id);34 var contactValue =http://www.mamicode.com/ contact.GetValueOfCustomField(fieldName);35 Console.WriteLine("Value: " + contactValue);36 37 //update38 contact.SetValueOfCustomField(fieldName, "test@test.com");39 session.SaveOrUpdate(contact);40 41 //delete42 session.Delete(contact);43 44 trans.Commit();45 }46 catch (Exception ex)47 {48 trans.Rollback();49 Console.WriteLine(ex.ToString());50 }51 }52 }53 }
Over!
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。