zoukankan      html  css  js  c++  java
  • Hibernate

    个人总结:

    对数据库操作的半成品,封装基本的dml操作,增删改查都实现了很简单的方法,稍微复杂点的可以使用hql语句实现

    使用框架步骤:

    一、新建一个项目

    ---------  是不是web都无所谓,hibernate只是对数据库的操作

    二、添加hibernate框架jar包

     

    三、Hibernate.cfg.xml

    <!DOCTYPEhibernate-configurationPUBLIC
    
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    
    "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
    
     
    
    <hibernate-configuration>
    
    <session-factory>
    
     
    
        <!-- 在控制台打印hibernate语句 -->
    
        <propertyname="show_sql">true</property>
    
        <!-- 格式化hibernate语句,没有这句话输出的hibernate语句是一整条 -->
    
        <propertyname="format_sql">true</property>
    
        <!-- 数据库名 -->
    
        <propertyname="myeclipse.connection.profile">orcl</property>
    
    <!-- oracle数据库驱动 -->
    
    <propertyname="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
    
    <!-- oracle数据库url -->
    
    <propertyname="hibernate.connection.url">jdbc:oracle:thin:@127.0.0.1:1521:orcl</property>
    
    <!-- 数据库的登陆用户名 -->
    
    <propertyname="hibernate.connection.username">scott</property>
    
    <!-- 数据库的登陆密码 -->
    
    <propertyname="hibernate.connection.password">scott</property>
    
    <!-- 方言:为每一种数据库提供适配器,方便转换 -->
    
    <propertyname="hibernate.dialect">org.hibernate.dialect.OracleDialect</property>
    
     
    
    <!-- 注解方式加载实体类的映射 -->
    
    <!-- <mapping class="entities.User"/> -->
    
     
    
    <!-- xml方式把实体类的映射文件加载进来 -->
    
    <mappingresource="entities/User.hbm.xml"/>
    
    <mappingresource="entities/Group.hbm.xml"/>
    
    <mappingresource="entities/Manager.hbm.xml"/>
    
    <mappingresource="entities/Role.hbm.xml"/>
    
    </session-factory>
    
    </hibernate-configuration>

    四、实体类以及实体类对应的映射文件

    实体类映射到数据表

    1、通过xml文件映射

             实体类建好,建User.hbm.xml文件

             在hibernate.cfg.xml中映射xml

      <mapping resource="com/xxx/hibernate/User.hbm.xml"/>

    2、通过注解方式映射

             在实体类上直接通过注解标明与其相关的数据表

             在hibernate.cfg.xml中映射xml

    <mapping class="com.xxx.hibernate.User"/>

    Xml映射文件:

    <?xmlversion="1.0"?>
    
    <!DOCTYPEhibernate-mappingPUBLIC
    
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    
     
    
    <hibernate-mapping>
    
        <classname="entities.Manager"table="tbl_manager">
    
            <id name="id">
    
              <column name="id"/>
            <generatorclass="increment"></generator>
    
           </id>
    
    
        <propertyname="managername"></property>
    
        </class>
    
     
    
    </hibernate-mapping>

    五、测试

    //管理hibernate配置信息
    
    Configuration cfg = new Configuration().configure(); 
    
    //获得SessionFactory对象以创建session对象
    
    sessionFactory = cfg.buildSessionFactory(); 
    
    session = sessionFactory.openSession();      
    
    //开启事务 
    
    transaction = session.beginTransaction();
    
     
    
    //dml操作
    
    Role role = new Role();
    
    role.setRolename("monkey");
    
    session.save(role);
    
     
    
    //提交事务 
    
    transaction.commit();
    
    //结束本次操作
    
    if(session != null){ 
    
        if(session.isOpen()){ 
    
           //关闭session 
    
           session.close(); 
    
        }
    
    } 

     

     


     

     

    hiberate的持久化操作:

    增session.save(user)

    删session.delete(user)

    改session.update(user)

    查session.get(...)    均可正常使用,当查询对象不存在在数据库里时,get 返回null

        session.load(...)                                                                                 load返回objectNotFoundException

     

        异常信息:org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [com.geeksss.HibernateStudy.entity.Users#10]

     

    当使用Session的get()方法时,如果加载的数据不存在,get()方法会返回一个null;但是使用load()方法,若加载的数据不存在,则会抛出异常。

     

    load()方法有点麻烦的地方是会出很多异常,相比而言get()就简单多了

     


     

    hibernate配置相关的类

    参考文章:http://www.cnblogs.com/LonelyShadow/p/6006328.html

     

    @BeforeClass
    
        public static void before(){
    
           //管理hibernate配置信息
    
           Configuration cfg = new Configuration().configure(); 
    
           //获得SessionFactory对象以创建session对象
    
           sessionFactory = cfg.buildSessionFactory(); 
    
           session = sessionFactory.openSession();
    
          
    
           //开启事务 
    
           transaction = session.beginTransaction(); 
    
        }
    
    Configuration是Hibernate的入口,在新建一个Configuration的实例时(构造),Hibernate会在CLASSPATH环境变量中查找hibernate.properties文件。
    
      如果该文件存在,则将文件的内容加载到内容中,如果不存在,则抛出例外。
    
     .configure() 方法默认会在CLASSPATH环境变量下面寻找hibernate.cfg.xml文件



     

    关联映射:

    单向一对多-----》通过一端查所有多端

     参考文章:http://blog.csdn.net/yifei12315/article/details/6985022

             一端group上包含 集合 set<user> 属性

              多端user上包含 groupid 外键

          xml中  一端group -----》

    <set name="users"  inverse="true" lazy="false">

             <key column="groupid"></key><!--指定“多”的一端的外键,与“一”端得主键相关联-->

             <one-to-many class="entities.User"/><!--指定了“多”端对应的类-->

    </set>

                多端user -------》

             <property name="groupid"></property>

    单向多对一--------》在多端上查所有,顺便查了一端的

             一端不做处理

             多端  private Group group; 要包含多端类的属性

             xml 多端

             <many-to-one name="group" class="entities.Group">

             <column name="groupid"></column>//多端的外键

    </many-to-one>

            

           

    双向多对一/双向一对多

    把上面那两个单向的合在一起

             一端group上包含 集合 set<user> 属性

             多端  private Group group; 要包含多端类的属性

     xml  一端group

             <set name="users"  inverse="true" lazy="false" cascade="all" outer-join="true">

                       <key column="groupid" foreign-key="id"></key><!-- 指定“多”的一端的外键,与“一”端得主键相关联   -->

                       <one-to-many class="entities.User"/><!-- 指定了“多”端对应的类   -->

             </set>

     xml  多端

             <many-to-one name="group" class="entities.Group" outer-join="true">

             <column name="groupid"></column>

    </many-to-one>

    测试的时候要注意输出,因为两边都能用所以要格外注意是不是输出多了

    测试group的时候

              group类 toString 加上 this.getUsers() 输出 ,user类 去掉  this.getGroup().toString()

    测试user的时候跟以上相反

              user类加上 this.getGroup().toString() , group类 toString 去掉 this.getUsers() 输出

    单向一对一

    分主键关联和外键关联,我用外键关联

    补充:这个是单向一对一关系,只能从从manager端查找group

    Group 和Manager 一对一关系,manager表中含有groupid 外键对应 group 表中的ID主键

    Group类是正常属性

    Manager类中含有group类型的对象

    映射文件如下:

    Group.hbm.xml-------普通映射文件

    Manager.hbm.xml

    <!-- 单向一对一关系,只能从manager端查找group -->

    <!-- unique=true 指明这是一端 -->

    <many-to-onename="group"unique="true"class="entities.Group">

    <columnname="groupid"></column>

    </many-to-one>以上这种方法只能用于从manager端查找group

    http://www.cnblogs.com/whgk/p/6128395.html

    双向一对一

    Group 和Manager 一对一关系,manager表中含有groupid 外键对应 group 表中的ID主键

    Group类 中含有manager类型的对象

    Manager类中含有group类型的对象

    可以从manager查group,也可以从group查manager

    有外键的那一边 manager映射文件

    <!-- 一对一关系,有外键的那边,不管单双向,这边都这么写 -->

    <!-- unique=true 指明这是一端 -->

    <many-to-onename="group"unique="true"class="entities.Group">

        <columnname="groupid"></column>

    </many-to-one>

    外键映射的那一边 group映射文件

    <!-- 双向一对一 -->

    <!-- 要注意property-ref这个属性,很重要,关键的地方就在这里。

    property-ref:指定关联类的属性名,这个属性将会和本类的主键相对应。如果没有指定,会使用对方关联类的主键来跟本类的主键比较,这里要注意不是关联表中的外键字段名。如果不指定这个属性,那么一对一默认会使用主键去做对比。相当于原本我们是可以通过本类的主键去和关联类的外键比较,然后来找到对应记录的,但是这里一对一中没有column属性,所以该方法行不通,因此就想出了这种办法,不跟外键比,也不能跟主键比(因为不是主键关系),那么就跟关联表中的一个属性比,也就是我们这个manager类中的group属性,为什么找得到呢,因为从manager类能找到group属性,那么manager中的group中就会有对应的值,我们跟该值比,也就能找到对应的manager了。class:manager所在的类,这个也可以不写,hibernate会自动帮我们找到

      -->

    <one-to-onename="manager"property-ref="group"class="entities.Manager">

    </one-to-one>

            

    多对多

    http://blog.csdn.net/zavens/article/details/7897580

    多端对多端配置基本相同  ,user和role 要有中间表 user_role

             user类     private Set<Role> roles;

             role类     private Set<User> users;

    xml 配置

     user   <!-- 多对多关系 -->

                                <!-- 通过user的ID去Role里面找role的ID放到"roles"里去 -->

                       <set name="roles" table="user_role">

                                <!-- and user_role.userid=? 是这个意思,在user_role里面找userID-->

                                <key column="userid"></key>

                                <!-- manytomany 这一句里的column和class的意思是    user_role.roleid=tbl_role.id-->

                                <!-- 用Role类里的id去找上面table里的roleid -->

                                <many-to-many column="roleid" class="entities.Role"></many-to-many>

                       </set>

     role <!-- 多对多关系 -->

                       <set name="users" table="user_role">

                                <key column="roleid"></key><!-- 通过role的ID去User里面找user的ID放到users里去 -->

                                <many-to-many column="userid" class="entities.User"></many-to-many>

                       </set>

    插入:

    user = session.get(User.class,new Integer("3"));

    role = session.get(Role.class, new Integer("1"));

    user.getRoles().add(role);

    role = session.get(Role.class, new Integer("2"));

    user.getRoles().add(role);

    role = session.get(Role.class, new Integer("3"));

    user.getRoles().add(role);

              

    session.save(user);


    Hql语句:

    基本类似于SQL语句,用findAll(“from User”)就可以直接查出user表中所有数据

    这里的User 是 跟表对应的 实体类名

    Q.setString(0,”123”); 设置参数值


     

    注解:

    实体类的注解:

    @Entity
    
    @Table(name = "tbl_user")
    
    publicclass User {
    
        @Id//主键 
    
        @GeneratedValue(strategy=GenerationType.AUTO)
    
        privateintid;
    
       
    
        @Column(name="username")
    
        private String username;
    
       
    
        @Column(name="userpassword")
    
        private String userpassword;

     

    异常错误信息整理:

    1、序列不存在

    Hibernate: select hibernate_sequence.nextval from dual

    七月 25, 2017 9:00:31 上午 org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions

    WARN: SQL Error: 2289, SQLState: 42000

    七月 25, 2017 9:00:31 上午 org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions

    ERROR: ORA-02289: 序列不存在

    org.hibernate.exception.SQLGrammarException: could not extract ResultSet

    解决方案:

    1.导致这个问题的一个原因是,没有用dba的身份连接数据库。在使用scott账户进行nextval操作的时候出现这个错误。

    2.Sequence  是oracle 的 主键增长策略,  在设置这个表里面的ID 做主键的时候不用特别指定Sequence ,  只用设置像这样就行了.

    <id name="id" type="java.lang.Integer">

    <column name="id" />

    <generator class="increment"></generator>

    </id>

    3.Hibernate: select hibernate_sequence.nextval from dual找不到序列解决办法

    在hibernate.cfg.xml配置文件中增加<property name="hbm2ddl.auto">update</property>

    问题解决。

    2、jar包

    org.hibernate.HibernateException: HHH000142: Javassist Enhancementfailed: com.s118.user.entity.User

    原因: hibernate和struts2的包冲突

    解决方案:

    把struts2的javassist-3.11.0.GA.jar删除

    3、反射获取实体类对象

    org.hibernate.MappingException: Could not get constructor fororg.hibernate.persister.entity.SingleTableEntityPersister

    只知道是反射获取实体类对象时出了错。

    错误原因:

    (1)实体类的属性对象没有设置setter或者getter。

     http://stackoverflow.com/questions/18042247/could-not-get-constructor-for-org-hibernate-persister-entity-singletableentitype

    (2) 没有导入javassist的jar文件  (javassist-3.15.0-GA.jar什么的)

    http://blog.csdn.net/xiaochangwei789/article/details/7712725

    (3)映射问题

    我的实体类中的属性对象名和映射文件的property name不一致。

    我这次出的错是先导包的时候导的是javassist-3.4.GA.jar报了第一个错,然后把javassist删了报第二个错,后面换成javassist-3.20.0-GA.jar就不报错了

    4、java.lang.StackOverflowError      

    原因:多对多或者一对多的时候输出set集合那里冲突了,不能重复

    5、主键约束

    Caused by: org.hibernate.HibernateException: identifier of an instance of .[类名]. is alterde from [数字] to [数字]

    原因:是由于在一个事务中更新了主键,而主键是不能被更新的

    6、session创建出错

    org.hibernate.HibernateException: No CurrentSessionContext configured!

    原因:当前没有可用的session,换成seesionFactory.openSession()

    -------------------------------------------------------------------------------------------------------------------------------------------------------------- 白云苍狗时光飞,嘻嘻哈哈一生追。哈!
  • 相关阅读:
    Nginx日志定时切割脚本
    阿里大于短信接口
    阿里云Linux系统挂载数据盘
    阿里云 OSS+CDN
    值得一学的几条谷歌搜索技巧
    【转】makefile语法规则
    【转】GCC使用简介
    网络编程中常见地址结构与转换(IPv4/IPv6)
    【转】adns解析库——域名解析实例(C++、linux)
    【转】什么是自动化测试
  • 原文地址:https://www.cnblogs.com/sangong/p/10812302.html
Copyright © 2011-2022 走看看