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