hibernate

作者: guideEmotion | 来源:发表于2019-06-02 16:00 被阅读0次

一 创建项目

  1. idea创建一个hibernate项目。

    image.png
  2. 参考https://blog.csdn.net/qq_29216083/article/details/70194056。通过表自动生成实体类和配置文件

  3. 添加junit,参考:https://blog.csdn.net/traitor_4/article/details/80168695

二 配置介绍

hibernate.cfg.xml

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <property name="connection.url">jdbc:mysql://localhost:3306/hibernateds?useUnicode=true&amp;characterEncoding=utf-8</property>
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>

        <property name="connection.username">root</property>
        <property name="connection.password">123456</property>
        <property name="current_session_context_class">thread</property>
        <property name="show_sql">true</property>
        <property name="hbm2ddl.auto">update</property>

        <mapping class="com.zyc.UserEntity"/>
        <mapping resource="com/zyc/UserEntity.hbm.xml"/>
        <!-- <property name="connection.username"/> -->
        <!-- <property name="connection.password"/> -->

        <!-- DB schema will be updated if needed -->
        <!-- <property name="hbm2ddl.auto">update</property> -->
    </session-factory>
</hibernate-configuration>

cfg.xml和.hbm.xml的区别

  • hibernate.cfg.xml 配置文件提供链接数据库的基本信息
    账号 密码 驱动 数据库ip 端口
  • Product.hbm.xml 提供对象与表的映射关系
    对应哪个表? 什么属性,对应什么字段

三 CRUD

插入

    @Test
    public void batchInsert(){

        for (int i = 0; i < 10; i++) {
            UserEntity user = new UserEntity();
            user.setId(i+1);
            user.setName("李维民"+i);
            user.setAge(45+i);
            user.setAdress("广东");
            user.setMobile("1101"+i);
            session.save(user);
        }

    }

对象状态

实体类对象在Hibernate中有3种状态:分别是瞬时,持久和脱管

  • 瞬时 指的是没有和hibernate发生任何关系,在数据库中也没有对应的记录,一旦JVM结束,这个对象也就消失了
  • 持久 指得是一个对象和hibernate发生联系,有对应的session,并且在数据库中有对应的一条记录
  • 脱管 指的是一个对象虽然在数据库中有对应的一条记录,但是它所对应的session已经关闭了

查询

    @Test
    public void get(){
        UserEntity user = session.get(UserEntity.class,2);
        UserEntity user2 = (UserEntity) session.load(UserEntity.class, 3);
        System.out.println(user.getAge());
        System.out.println(user2.getAge());

    }

//执行输出
//Hibernate: select userentity0_...
//46
//Hibernate: select userentity0_...
//47

注意
不要用debug去执行,因为debug时可以看到对象属性值,所以看不到延迟加载的现象


load和get的区别

  1. load方式是延迟加载,只有属性被访问的时候才会调用sql语句;get方式是非延迟加载,无论后面的代码是否会访问到属性,马上执行sql语句
  2. id不存在时。get方式会返回null ;load方式会抛出异常

删除

    @Test
    public void delete(){
        UserEntity user = session.get(UserEntity.class,8);
        System.out.println(user);
        session.delete(user);

    }

修改

    @Test
    public void update(){
        UserEntity user = session.get(UserEntity.class,9);
        user.setAdress("东山");
        session.update(user);

    }

四 查询方式

hql

HQL(Hibernate Query Language)是hibernate专门用于查询数据的语句,有别于SQL,HQL 更接近于面向对象的思维方式。

    @Test
    public void hql(){
        String hql ="from UserEntity where id>3";
        Query query = session.createQuery(hql);
        List<UserEntity> list=  query.list();
        for(UserEntity user:list){
            System.out.println(user.getId());
        }


    }

Criteria

与HQL和SQL的区别是Criteria 完全是 面向对象的方式在进行数据查询,将不再看到有sql语句的痕迹

查询步骤

  1. 通过session的createCriteria创建一个Criteria 对象
  2. Criteria.add 增加约束。 在本例中增加一个对name的模糊查询(like)
  3. 调用list()方法返回查询结果的集合

在hibernate5.10版本中已经不推荐该种方式了。参考:https://blog.csdn.net/blue__fisher/article/details/78885143

    @Test
    public void criteria(){
        Criteria criteria = session.createCriteria(UserEntity.class);
        criteria.add(Restrictions.gt("id",2));
        criteria.add(Restrictions.eq("adress","东山"));

        List<UserEntity> list=  criteria.list();
        for(UserEntity user:list){
            System.out.println(user.getId());
        }
    }

标准sql

    @Test
    public void sql(){

        String sql = "select * from user where name like '%李维民3%'";

        Query q= session.createSQLQuery(sql);
        List<Object[]> list= q.list();
        for (Object[] os : list) {
            for (Object filed: os) {
                System.out.print(filed+"\t");
            }
            System.out.println();
        }
    }

        //自己常用的方式,转成一个map
        @SuppressWarnings("unchecked")
        List<Map<String,Object>> zslist = (List<Map<String,Object>>)baseDao.sqlQuery(zssql)
                                        .addScalar("id",StandardBasicTypes.STRING)
                                        .addScalar("parentId",StandardBasicTypes.STRING)
                                        .addScalar("name",StandardBasicTypes.STRING)
                                        .addScalar("zs",StandardBasicTypes.INTEGER)
                                        .addScalar("bmd",StandardBasicTypes.INTEGER)
                                        .setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).list();
  

五 关系

xml配置

  1. [xml配置版]双向一对多和双向多对多、级联、inverse:https://www.cnblogs.com/gdwkong/p/8337081.html
  2. [xml配置版]单向多对一、单向一对多、双向一对多:https://blog.csdn.net/qq_36748278/article/details/78035244
  3. [xml配置版]一对一关系映射详解:https://www.cnblogs.com/whgk/p/6128395.html

注解版

https://www.cnblogs.com/printN/p/6408818.html

六 注解

主键生成注解

    @Id
    @Column(name = "id")
    @GeneratedValue(strategy=GenerationType.AUTO)


    @Id
    @Column(name = "id")
    @GeneratedValue(generator = "uuidGener")
    @GenericGenerator(name = "uuidGener", strategy="uuid")

参考:https://blog.csdn.net/qq193423571/article/details/76371372

集合映射,关联关系映射

参考:https://blog.csdn.net/qq_29829081/article/details/51055535

联合主键、继承映射

参考:

@MappedSuperclass

参考:https://www.cnblogs.com/zqyanywn/p/7753596.html

七 个人理解

7.1 关系注解和级联的关系?

我认为关系注解和级联是两个独立的概念,但级联时的部分行为又和关系有关。

  • 关系注解:个人认为主要是便于orm框架在查询时,发现对象和对象是关联关系。告诉orm框架如何将两个有关联的对象(数据库中就是不同表之间的记录)直接一起查询并组合起来,减少程序员的开发工作
  • 级联:有级联更新、删除等等。也是为了减少代码,让多个有关联的对象在持久化其中一个时,连带着把其他的也一起持久化。

7.2 更新级联时的行为特点?

  • 当我们使用关系注解时。默认级联关系是none.即不会级联保存。
  • 只有当我们设置了级联关系,orm框架才会帮我级联操作
  • hibernate为了保证每次更新的级联不出错,会先将之前所有关联的记录的关联字段设置为null


    image.png

7.3 开启了级联就一定会级联吗?

是!
但关系能否正确映射到数据库就不一定了!!!
这主要看你开启了级联的一方是否维护关系,如果不维护。那关系就不会正确的映射到数据库中

7.4 一对多由哪一方维护?

个人经验:还是由一的一方维护比较方便。

虽然大部分教学视频里都说双向一对多时,由一的一方维护关系会减少不必要的sql(这个结论时对的)。但我在实际开发中发现,由一的一方维护有个优点:我们只需要将多的一方放入或移出集合,就可以控制两方是否有关联(这个还是方便啊

7.5 @JoinColumn注解啥情况?

在一对多关系中,无论注解在哪。name对应的列肯定在多的一方。不写,hibernate还会生成中间表
在一对一关系中,注解在哪个类中,name对应的列就在该类对应的表中

7.5 @ElementCollection

该注解如果和@Embedded修饰的类结合使用。那么@Embedded修饰的类对应的表就没有主键。每次我们更新时(保存不用,第一次插入删空气吗?),外面那个类时,都会把之前所有集合表中有关的记录删除,重新插入一份。

image.png

7.6 外键维护和级联也是两个独立的概念

只要记住,只要不是显示的用了inverse(再注解中对应mappedby)的一方,hibernate都会维护外键关系


参考

  1. http://how2j.cn/k/hibernate/hibernate-tutorial/31.html#nowhere

相关文章

网友评论

      本文标题:hibernate

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