美文网首页
NHIbernate学习总结

NHIbernate学习总结

作者: 徐曼曼_b287 | 来源:发表于2020-03-31 09:55 被阅读0次

    什么是NHIbernate?

    Nhibernate是一个ORM工具

    ORM就是一种把数据库的数据结构,通过映射文件描述其关系,将程序中的对象与数据库关联起来的技术,方便我们在程序中,通过操作对象的方式对数据库进行增增删改查操作
    而NHibernate就是帮助实现这种技术的工具

    市面上这种工具还有很多:比如SQLSugar、EF、Dapper

    EF:vs自带,使用方便,开发效率高,通过创建对应的实体对象,在dbcontext中添加实体与数据库表的映射,就可以实现对数据库的增删改查,但性能一般

    NHibernate:开源、免费、批量读写等特点,个人感觉入门门槛比较高,基本上就是配置又配置,操作流程就是配置、创建持久化类、创建持久化类的映射文件,在映射文件中,配置一对一、一对多、多对多等表关系

    SqlSugar:开源、国人开发、面向.net平台、支持.net core

    Dapper:轻量、速度快、多数据库支持

    NHibernate如何使用?

    NHibernate在我看来就是配置+实体+映射

    配置:

    • 添加引用:使用第三方工具的第一步都是先通过nuget或者手动下载的形式,先将目标工具引用到项目中。
    • 为NHibernate配置数据库连接信息,在web.config中添加配置元素:
      <configSections> -- 添加配置节点名称;
      <hibernate-configuration> -- 里面写具体的信息,例如数据库连接字符串
      dialect(方言)-- 是必须设置的,用于匹配当前使用的数据库SQL脚本上的差异
      Mapping – 声明了持久化类即映射文件所在的应用程序集


      web.config

    除了这种方式,还可以<hibernate-configuration>的内容单独配置到hibernate.cfg.xml中

    实体:

    创建简单的.net对象类,使用get,set属性来访问数据成员

    public class Person
    {
        public virtual int Id { get; set; }
        public virtual string Name { get; set; }
    }
    

    配置映射:

    创建了类后,还需要创建映射文件:**.hbm.xml,将类和数据库表及字段关联起来,映射文件和实体通常是成对出现的

    <?xml version="1.0" encoding="utf-8" ?>
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="DemoEntity" assembly="DemoEntity">
      <class name="Person" table="T_Persons" lazy="false">
        <id name="Id" column="Id" type="Int32">
          <generator class="native" />
        </id>
        <property name="Name" access="property" type="String">
          <column name="Name" />
        </property>
      </class>
    </hibernate-mapping>
    

    映射文件中的元素与映实体中的属性一一对应

    property :对应实体类中的属性名;id:表示唯一标识;column:属性对应的表的列名;

    使用:

    做完上面准备工作之后,就可以开始通过ISession从数据库中存取数据了。

    ISession从ISessionFactory中创建,ISessionFactory是什么呢?

    我们可以把它当做存放数据库的工厂,我们需要操作一个数据库,则通过在工厂中创建一个实例来获取一个数据库

    ISessionFactory sessionFactory = new Configuration().Configure().BuildSessionFactory();

    ISessionFactory 通常只被初始化一次,通常会先实现一个帮助类:NHibernateHelper

            private const string CurrentSessionKey = "nhibernate.current_session";
            private static readonly ISessionFactory sessionFactory;
    
            static NHibernateHelper()
            {
                sessionFactory = new Configuration().Configure().BuildSessionFactory();
            }
    
            public static ISession GetCurrentSession()
            {
                HttpContext context = HttpContext.Current;
                ISession currentSession = context.Items[CurrentSessionKey] as ISession;
    
                if (currentSession == null)
                {
                    currentSession = sessionFactory.OpenSession();
                    context.Items[CurrentSessionKey] = currentSession;
                }
    
                return currentSession;
            }
    

    以下是保存命令:

    using (isession = NHibernateHelper.GetCurrentSession())
    {
           using (var trans = isession.BeginTransaction())
           {
                  var p=new Person();
                  p.Name="xxx";
                  isession.Save(pmodel);
                  trans.Commit();
           }
    }
    

    查询出列表数据:

    using (isession = NHibernateHelper.GetCurrentSession())
     {
                  ICriteria crit = isession.CreateCriteria(typeof(Person));
                  IList<Person> plist = crit.List<Person>();
                  return View(plist.ToArray());
    }
    

    或者根据id获取:

    var pnew = isession.Get<Person>(model.Id);

    又或者使用CreateSQLQuery直接执行SQL语句:

    var curhouseholders = isession.CreateSQLQuery(string.Format(@"select * from householder where name like '%{0}%'", model.Name)).AddEntity(typeof(HouseHolder));

    Var HouseHolders = curhouseholders.List<HouseHolder>();

    AddEntity()方法可以使CreateSQLQuery()返回值按照指定类型转化为HouseHolder.

    当不使用AddEntity()方法时,curhouseholders.List<HouseHolder>()会失效

    注:
    1. 创建的映射文件,属性要改成嵌入资源,否则会报错

    2. Nhibernate为了延迟加载,要求数据库产生映射的类中所有的公开成员(public/protected)都是virtual

    3.<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="DemoEntity" assembly="DemoEntity">

    这里namespace 实体所在命名空间、assembly 实体所在程序集,填写好了之后,class元素的name属性就可以直接填写类名了

    关联关系

    关联关系是实体类与实体类之间的结构关系,分别为

    一对一:<one-to-one>、多对一:<many-to-one>、多对多:<many-to-many>

    多对一关系为例:多个狗子对应一个主人,表结构:
    T_Persons表:Id,Name; T_Dogs表:Id,Name,PersonId

    inverse="true" 代表反转,把控制权交给另一方

    Person实例

     public class Person
    {
            public virtual int Id { get; set; }
            public virtual string Name { get; set; }
            public virtual IList<Dog> DogList { get; set; }
     }
    

    Person.hbm.xml

    <?xml version="1.0" encoding="utf-8" ?>
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"  namespace="DemoEntity" assembly="DemoEntity">
        <class name="Person" table="T_Persons" lazy="false">
            <id name="Id" column="Id" type="Int32">
                <generator class="native" />
            </id>
            <property name="Name" access="property" type="String">
                <column name="Name" />
            <bag name="DogList" inverse="true" generic="true" table="T_Dogs" lazy="true">
                <key column="Id" />
                <one-to-many class="Dog" not-found="ignore"/>
            </bag>
        </class>
    </hibernate-mapping>
    

    Dog实例

        public class Dog
        {
            public virtual int Id { get; set; }
            public virtual string Name { get; set; }
            public virtual int? PersonId { get; set; }
            public virtual Person CurrentPerson { get; set; }
        }
    

    Dog.hbm.xml

    <?xml version="1.0" encoding="utf-8" ?>
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" >
        <class name="DemoEntity.Dog,DemoEntity" table="T_Dogs" lazy="false">
            <id name="Id" column="Id">
                <generator class="identity"/>
            </id>
            <property name="Name" access="property" type="String">
                <column name="Name" />
            </property>
            <many-to-one name="CurrentPerson" column="PersonId" class="DemoEntity.Person,DemoEntity" not-found="ignore"></many-to-one>
        </class>
    </hibernate-mapping>
    

    代码实现,这时添加狗子的同时,将主人的Id也写进去:

            public ActionResult Add(Dog dmodel)
            {
                using (isession = NHibernateHelper.GetCurrentSession())
                {
                    using (var trans = isession.BeginTransaction())
                    {
                        var ownner = new Person() { Name = dmodel.Name + "主人", Age = 1, Sex = 1 ,CreateDateTime=DateTime.Now};
                        dmodel.CurrentPerson = ownner;
                        isession.Save(ownner);
                        isession.Save(dmodel);
                        trans.Commit();
                    }
                }
                return Json(new AjaxResult { Status = "ok" });
            }
    

    多对多关系:学生和家长是多对多关系,一个学生可以对应多个家长,一个家长也可以对应多个学生,表格:

    Student表:Id,Name;Householder:Id,Name;StudentHouseholder:Id,StudentId,HouseholderId

    代码如下:
    Student实体

        public class Student
        {
            public virtual int Id { get; set; }
            public virtual string Name { get; set; }
            public virtual IList<HouseHolder> HouseHolders { get; set; }
        }
    

    Student.hbm.xml

    <?xml version="1.0" encoding="utf-8" ?>
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"  namespace="DemoEntity" assembly="DemoEntity">
        <class name="Student" table="Student" lazy="true">
            <id name="Id" column="Id" type="Int32">
                <generator class="native" />
            </id>
            <property name="Name" access="property" type="String">
                <column name="Name" />
            </property>
            <bag name="HouseHolders"  table="StudentHouseHolder" cascade="save-update" lazy="false">
                <key column="StudentId" />
                <many-to-many class="HouseHolder" column="HouseHolderId" not-found="ignore"/>
            </bag>
        </class>
    </hibernate-mapping>
    

    HouseHolder实体

        public class HouseHolder
        {
            public virtual int Id { get; set; }
            public virtual string Name { get; set; }
            public virtual IList<Student> Students { get; set; }
        }
    

    HouseHolder.hbm.xml

    <?xml version="1.0" encoding="utf-8" ?>
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"  namespace="DemoEntity" assembly="DemoEntity">
        <class name="HouseHolder" table="HouseHolder" lazy="true">
            <id name="Id" column="Id" type="Int32">
                <generator class="native" />
            </id>
            <property name="Name" access="property" type="String">
                <column name="Name" />
            </property>
            <bag name="Students" table="StudentHouseHolder" lazy="true" inverse="true">
                <key column="HouseHolderId" />
                <many-to-many class="Student" column="StudentId" not-found="ignore"/>
            </bag>
        </class>
    </hibernate-mapping>
    

    cascade="save-update" :表示级联,只在保存或更新的时候执行,这样就在添加学生的时候可以自动添加学生家长,并将他们的联系添加到中间表

    还有他的的几个值:all|none|save-update|delete;如果设置:all,则在你删除的时候,会帮你把你爸妈也删了

    学生表设置cascade的同事家长表也要设置inverse="true",代表控制权交由对方

    如果不设置cascade,在保存学生的同时也要保存家长,否则会提示在设置cascade之前,保存临时实例

    代码如下:

             public ActionResult Add(Student pmodel)
            {
                using (isession = NHibernateHelper.GetCurrentSession())
                {
                    using (var trans = isession.BeginTransaction())
                    {
                        var householder = new HouseHolder { Name = pmodel.Name + "爸" };
                        var curhouseholder1 = new HouseHolder { Name = pmodel.Name + "妈" };
    
                        pmodel.HouseHolders = new List<HouseHolder> { householder, curhouseholder1 };
                        //isession.Save(householder); 设置级联,家长信息自动保存
                        isession.Save(curhouseholder1);
    
                        isession.Save(pmodel);
    
                        trans.Commit();
                    }
                }
                return Json(new AjaxResult { Status = "ok" });
            }
    

    多对多关系还可以拆解为两个多对一关系,中间表与学生表,中间表与家长表都是多对一的关系

    相关文章

      网友评论

          本文标题:NHIbernate学习总结

          本文链接:https://www.haomeiwen.com/subject/nzcluhtx.html