NHIbernate学习总结

2020-03-31  本文已影响0人  徐曼曼_b287

什么是NHIbernate?

Nhibernate是一个ORM工具

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

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

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

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

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

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

NHibernate如何使用?

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

配置:

除了这种方式,还可以<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" });
        }

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

上一篇下一篇

猜你喜欢

热点阅读