zoukankan      html  css  js  c++  java
  • J2EE--Hibernate基础笔记

    因为写的是基础内容,所以在这里,(映射集合、映射组件、复合主键和联合主键,jpa annotation,关联映射,hql等等实用内容)都不会提到~

    这里写的就是试用李刚《J2EE实战》那本书里的小demo的时候发生的错误。其实我发现这本书附带的例子真的是各种错误,实在是太水。

    所谓Hibernate,实际上就是:PO(持久化类) = POJO(普通、传统java对象) + 映射文件。

    下面直接给出书中提供的例子作为问题解析的驱动。

    首先我们在Eclipse下新建一个Dynamic Web Project。

    先把需要用到的jar包放入到/WebContent/WEB-INF/lib文件夹内,我们可以用Eclipse来加,不过我比较喜欢直接在文件夹中操作,复制粘贴即可,这些包我们可以在hibernate压缩包里面找到。

    然后在项目工程的src文件夹内新建和编写如下文件:

    其中hibernate.cfg.xml是标准的hibernate配置文件,web应用会首先搜索这个配置文件(其实是先搜索properties文件,搜不到再搜xml),News.hbm.xml文件是我们人为定义的配置文件,用来对应一个POJO类(普通Java类),从而进行数据库持久化操作。

    文件夹lee里面有两个类,一个类对应数据库表,一个类有主方法,用于测试。

    先看看POJO类:

    package lee;
    public class News
    {
        //ID,自增长列
        private int id;
        //标题
        private String title;
        //内容
        private String content;
        //下面是构造函数,以及getter方法和setter方法
        public News()
        {
        }
        public void setId(int id) 
        {
            this.id = id; 
        }
        public int getId()
        {
            return (this.id); 
        }
        public void setTitle(String title) 
        {
            this.title = title; 
        }
        public String getTitle() 
        {
            return (this.title); 
        }
        public void setContent(String content)
        {
            this.content = content; 
        }
        public String getContent()
        {
            return (this.content); 
        }
    }
    View Code

    可见,一点持久化操作都不用写,只是一个普通的JavaBean。

    那它是怎么对应到数据库的,关键就在于上面两个配置文件的配置,首先看看News.hbm.xml的配置:

    <?xml version="1.0" encoding="gb2312"?>
    <!DOCTYPE hibernate-mapping PUBLIC 
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    
    <hibernate-mapping package="lee">
            <!--   一个类,对应一个表 -->
        <class name="News" table="news_table">
                    <!--表的主键,自增长ID-->
            <id name="id">
                <generator class="identity"/>
            </id>
                    <!-- 两个普通属性 -->
            <property name="title"/>
            <property name="content"/>
        </class>
    </hibernate-mapping>
    View Code

    然后,配置hibernate.cfg.xml文件,在文件内将News.hbm.xml的配置内容映射进来:

    <?xml version="1.0" encoding="GBK"?>
    
    <!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
    
    <hibernate-configuration>
        <session-factory>
            <!-- 数据库驱动,众所周知 -->
            <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
            <!-- 数据库名 -->
            <property name="connection.url">jdbc:mysql://localhost/hibernate</property>
            <!-- 连接数据库所用的用户名 -->
            <property name="connection.username">nero</property>
            <!-- 密码 -->
            <property name="connection.password">123456</property>
            <!-- 最大连接数 -->
            <property name="hibernate.c3p0.max_size">20</property>
            <!-- 最小连接数-->
            <property name="hibernate.c3p0.min_size">1</property>
            <!-- 连接超时时长限制 -->
            <property name="hibernate.c3p0.timeout">5000</property>
            <!-- 指定缓冲池里的陈述数量限制 -->
            <property name="hibernate.c3p0.max_statements">100</property>
            <property name="hibernate.c3p0.idle_test_period">3000</property>
            <property name="hibernate.c3p0.acquire_increment">2</property>
            <property name="hibernate.c3p0.validate">true</property>
            <!-- 数据库方言 -->
            <property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
            <!-- 设置是否自动创建表   -->    
            <property name="hbm2ddl.auto">create</property>
         
            <!-- 映射所有配置文件-->
            <mapping resource="News.hbm.xml"/>
        </session-factory>
    </hibernate-configuration>
    View Code

    然后,在lee包里创建一个有main方法的主类进行测试:

    public class NewsManager
    {
        public static void main(String[] args) throws Exception
        {
            //自动加载hibernate.cfg.xml
            Configuration conf = new Configuration().configure();
            //通过Configuration对象获取工厂类对象SessionFactory
            SessionFactory sf = conf.buildSessionFactory();
            //获取Session
            Session sess = sf.openSession();
            //获取对话
            Transaction tx = sess.beginTransaction();
            //存储操作
            News n = new News();
            n.setTitle("test title");
            n.setContent("http://www.crazyjava.org");
            sess.save(n);
            //提交
            tx.commit();
            //关闭Session
            sess.close();
        }
    }
    View Code

    可见整个过程是非常简单易懂的,按部就班操作即可。至于想做查询操作什么的,用hql就可以了,这是hibernate提供的查询方式,基本语法规则和标准SQL是相差无几的。这篇笔记不写这个。

    看着好像是可以运行了,运行主类,报错。

    我们在News.hbm.xml配置文件中不是指定了类对应的数据库表名是'news_table'么,但是执行主类的时候报错如下:

    SEVERE: Table 'hibernate.news_table' doesn't exist

    也就说这个表不存在,后来呢,我用nero这个账户登录到mysql自行创建了题目要求的数据库和表还是不行,照样报同一个错。

    mysql>use hibernate;

    mysql>create table news_table (id integer not null auto_increment, title varchar(255), content varchar(255), primary key (id));

    编辑器它报错的时候还顺便把错误的sql语句给出来了,我看那个句子大部分是正确的,就直接把正确的部分复制粘贴创建了数据库,是可以正常创建的。

    问题记录如下:
    Jan 7, 2014 10:17:13 AM org.hibernate.tool.hbm2ddl.SchemaExport create
    SEVERE: Unsuccessful: create table news_table (id integer not null auto_increment, title varchar(255), content varchar(255), primary key (id)) type=InnoDB
    Jan 7, 2014 10:17:13 AM org.hibernate.tool.hbm2ddl.SchemaExport create
    SEVERE: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'type=InnoDB' at line 1
    Jan 7, 2014 10:17:13 AM org.hibernate.tool.hbm2ddl.SchemaExport execute

    可见,具体的问题就出现在粗体字那部分。这个我们没办法改的,因为这个是由hibernate底层自行通过脚本实现的。那怎么办?既然问题出在自动创建数据库,那就找到自动创建数据库的配置内容:

    去网上找了下关于属性"hbm2ddl.auto"的配置(当然也可以找hibernate自带的帮助文档,不过直觉觉得直接搜索更快),列出重点内容如下。
    它一般有四个属性:
    create : 会根据你的model类来生成表,但是每次运行都会删除上一次的表,重新生成表,哪怕2次没有任何改变
    create-drop : 根据model类生成表,但是sessionFactory一关闭,表就自动删除
    update : 最常用的属性,也根据model类生成表,即使表结构改变了,表中的行仍然存在,不会删除以前的行
    validate : 只会和数据库中的表进行比较,不会创建新表,但是会插入新值

    所以,因为hibernate它自己生成的脚本有错误,加上"hbm2ddl.auto"属性设置成了create,那么每次运行的时候先把表删除了,问题是hibernate的create表达式又是有错误的,所以每次测试都报错hibernate.news_table表不存在!实际上不是不存在,是被它反复删除。

    因此,把里面的属性值改成validate,然后我们自行在数据库中创建对应的数据库和表即可,上面已经给出语法了。

    更改完成后,我们再一次执行主类,成功运行后,看看控制台输出了什么信息。学习一个框架,我们不仅要知道怎么用,还要知道它具体是怎么运作的,底层是怎么实现的,对于做应用来说,可能我们不需要去实现底层的东西(效率差),但是知道这些东西对自己肯定是有利无害的,它会让你对这些框架理解得更深刻,运用也更自如。

    最后给出控制台的输出信息(当然,这个是成功运行的):

    /****************************************************************
    第一,读取jar类包
    Jan 7, 2014 10:22:32 AM org.hibernate.cfg.Environment <clinit>
    INFO: Hibernate 3.2.6
    Jan 7, 2014 10:22:32 AM org.hibernate.cfg.Environment <clinit>
    INFO: hibernate.properties not found
    Jan 7, 2014 10:22:32 AM org.hibernate.cfg.Environment buildBytecodeProvider
    INFO: Bytecode provider name : cglib
    Jan 7, 2014 10:22:32 AM org.hibernate.cfg.Environment <clinit>
    INFO: using JDK 1.4 java.sql.Timestamp handling
    *****************************************************************/
    
    
    /*******************************************************************
    第二,1、在第一步中没有找到properties文件,这个时候自动查找hibernate.cfg.xml配置文件
    2、将News.hbm.xml映射进来。然后,映射lee.News类和news_table表,这个时候还没有连接数据库,只是做简单的名字映射。
    3、加载数据库驱动,连接数据库;
    Jan 7, 2014 10:22:32 AM org.hibernate.cfg.Configuration configure
    INFO: configuring from resource: /hibernate.cfg.xml
    Jan 7, 2014 10:22:32 AM org.hibernate.cfg.Configuration getConfigurationInputStream
    INFO: Configuration resource: /hibernate.cfg.xml
    Jan 7, 2014 10:22:32 AM org.hibernate.cfg.Configuration addResource
    INFO: Reading mappings from resource : News.hbm.xml
    Jan 7, 2014 10:22:32 AM org.hibernate.cfg.HbmBinder bindRootPersistentClassCommonValues
    INFO: Mapping class: lee.News -> news_table
    Jan 7, 2014 10:22:32 AM org.hibernate.cfg.Configuration doConfigure
    INFO: Configured SessionFactory: null
    Jan 7, 2014 10:22:32 AM org.hibernate.connection.C3P0ConnectionProvider configure
    INFO: C3P0 using driver: com.mysql.jdbc.Driver at URL: jdbc:mysql://localhost/hibernate
    Jan 7, 2014 10:22:32 AM org.hibernate.connection.C3P0ConnectionProvider configure
    INFO: Connection properties: {user=nero, password=****}
    Jan 7, 2014 10:22:32 AM org.hibernate.connection.C3P0ConnectionProvider configure
    INFO: autocommit mode: false
    *********************************************************************/
    
    /***往下我们可以看到,其实大部分工作都是由SessionFactory工厂类来完成****/
    /***而最后三行,则由hbm2ddl.TableMetadata类进行操作,检测到数据库存在以后,对数据进行写入操作***/
    Jan 7, 2014 10:22:32 AM com.mchange.v2.log.MLog <clinit>
    INFO: MLog clients using java 1.4+ standard logging.
    Jan 7, 2014 10:22:32 AM com.mchange.v2.c3p0.C3P0Registry banner
    INFO: Initializing c3p0-0.9.1 [built 16-January-2007 14:46:42; debug? true; trace: 10]
    Jan 7, 2014 10:22:32 AM com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource getPoolManager
    INFO: Initializing c3p0 pool... com.mchange.v2.c3p0.PoolBackedDataSource@945bcac [ connectionPoolDataSource -> com.mchange.v2.c3p0.WrapperConnectionPoolDataSource@d9eed013 [ acquireIncrement -> 2, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, debugUnreturnedConnectionStackTraces -> false, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, identityToken -> z8kfsx8ztjvt8c8eui08|a98932, idleConnectionTestPeriod -> 3000, initialPoolSize -> 1, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 5000, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 20, maxStatements -> 100, maxStatementsPerConnection -> 0, minPoolSize -> 1, nestedDataSource -> com.mchange.v2.c3p0.DriverManagerDataSource@60480c6 [ description -> null, driverClass -> null, factoryClassLocation -> null, identityToken -> z8kfsx8ztjvt8c8eui08|1d1e730, jdbcUrl -> jdbc:mysql://localhost/hibernate, properties -> {user=******, password=******} ], preferredTestQuery -> null, propertyCycle -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, usesTraditionalReflectiveProxies -> false; userOverrides: {} ], dataSourceName -> null, factoryClassLocation -> null, identityToken -> z8kfsx8ztjvt8c8eui08|1b4a74b, numHelperThreads -> 3 ]
    Jan 7, 2014 10:22:32 AM org.hibernate.cfg.SettingsFactory buildSettings
    INFO: RDBMS: MySQL, version: 5.5.34-0ubuntu0.12.04.1
    Jan 7, 2014 10:22:32 AM org.hibernate.cfg.SettingsFactory buildSettings
    INFO: JDBC driver: MySQL-AB JDBC Driver, version: mysql-connector-java-5.1.6 ( Revision: ${svn.Revision} )
    Jan 7, 2014 10:22:32 AM org.hibernate.dialect.Dialect <init>
    INFO: Using dialect: org.hibernate.dialect.MySQLInnoDBDialect
    Jan 7, 2014 10:22:32 AM org.hibernate.transaction.TransactionFactoryFactory buildTransactionFactory
    INFO: Using default transaction strategy (direct JDBC transactions)
    Jan 7, 2014 10:22:32 AM org.hibernate.transaction.TransactionManagerLookupFactory getTransactionManagerLookup
    INFO: No TransactionManagerLookup configured (in JTA environment, use of read-write or transactional second-level cache is not recommended)
    Jan 7, 2014 10:22:32 AM org.hibernate.cfg.SettingsFactory buildSettings
    INFO: Automatic flush during beforeCompletion(): disabled
    Jan 7, 2014 10:22:32 AM org.hibernate.cfg.SettingsFactory buildSettings
    INFO: Automatic session close at end of transaction: disabled
    Jan 7, 2014 10:22:32 AM org.hibernate.cfg.SettingsFactory buildSettings
    INFO: JDBC batch size: 15
    Jan 7, 2014 10:22:32 AM org.hibernate.cfg.SettingsFactory buildSettings
    INFO: JDBC batch updates for versioned data: disabled
    Jan 7, 2014 10:22:32 AM org.hibernate.cfg.SettingsFactory buildSettings
    INFO: Scrollable result sets: enabled
    Jan 7, 2014 10:22:32 AM org.hibernate.cfg.SettingsFactory buildSettings
    INFO: JDBC3 getGeneratedKeys(): enabled
    Jan 7, 2014 10:22:32 AM org.hibernate.cfg.SettingsFactory buildSettings
    INFO: Connection release mode: auto
    Jan 7, 2014 10:22:32 AM org.hibernate.cfg.SettingsFactory buildSettings
    INFO: Maximum outer join fetch depth: 2
    Jan 7, 2014 10:22:32 AM org.hibernate.cfg.SettingsFactory buildSettings
    INFO: Default batch fetch size: 1
    Jan 7, 2014 10:22:32 AM org.hibernate.cfg.SettingsFactory buildSettings
    INFO: Generate SQL with comments: disabled
    Jan 7, 2014 10:22:32 AM org.hibernate.cfg.SettingsFactory buildSettings
    INFO: Order SQL updates by primary key: disabled
    Jan 7, 2014 10:22:32 AM org.hibernate.cfg.SettingsFactory buildSettings
    INFO: Order SQL inserts for batching: disabled
    Jan 7, 2014 10:22:32 AM org.hibernate.cfg.SettingsFactory createQueryTranslatorFactory
    INFO: Query translator: org.hibernate.hql.ast.ASTQueryTranslatorFactory
    Jan 7, 2014 10:22:32 AM org.hibernate.hql.ast.ASTQueryTranslatorFactory <init>
    INFO: Using ASTQueryTranslatorFactory
    Jan 7, 2014 10:22:32 AM org.hibernate.cfg.SettingsFactory buildSettings
    INFO: Query language substitutions: {}
    Jan 7, 2014 10:22:32 AM org.hibernate.cfg.SettingsFactory buildSettings
    INFO: JPA-QL strict compliance: disabled
    Jan 7, 2014 10:22:32 AM org.hibernate.cfg.SettingsFactory buildSettings
    INFO: Second-level cache: enabled
    Jan 7, 2014 10:22:32 AM org.hibernate.cfg.SettingsFactory buildSettings
    INFO: Query cache: disabled
    Jan 7, 2014 10:22:32 AM org.hibernate.cfg.SettingsFactory createCacheProvider
    INFO: Cache provider: org.hibernate.cache.NoCacheProvider
    Jan 7, 2014 10:22:32 AM org.hibernate.cfg.SettingsFactory buildSettings
    INFO: Optimize cache for minimal puts: disabled
    Jan 7, 2014 10:22:32 AM org.hibernate.cfg.SettingsFactory buildSettings
    INFO: Structured second-level cache entries: disabled
    Jan 7, 2014 10:22:32 AM org.hibernate.cfg.SettingsFactory buildSettings
    INFO: Statistics: disabled
    Jan 7, 2014 10:22:32 AM org.hibernate.cfg.SettingsFactory buildSettings
    INFO: Deleted entity synthetic identifier rollback: disabled
    Jan 7, 2014 10:22:32 AM org.hibernate.cfg.SettingsFactory buildSettings
    INFO: Default entity-mode: pojo
    Jan 7, 2014 10:22:32 AM org.hibernate.cfg.SettingsFactory buildSettings
    INFO: Named query checking : enabled
    Jan 7, 2014 10:22:32 AM org.hibernate.impl.SessionFactoryImpl <init>
    INFO: building session factory
    Jan 7, 2014 10:22:33 AM org.hibernate.impl.SessionFactoryObjectFactory addInstance
    INFO: Not binding factory to JNDI, no JNDI name configured
    Jan 7, 2014 10:22:33 AM org.hibernate.tool.hbm2ddl.SchemaValidator validate
    INFO: Running schema validator
    Jan 7, 2014 10:22:33 AM org.hibernate.tool.hbm2ddl.SchemaValidator validate
    INFO: fetching database metadata
    Jan 7, 2014 10:22:33 AM org.hibernate.tool.hbm2ddl.TableMetadata <init>
    INFO: table found: hibernate.news_table
    Jan 7, 2014 10:22:33 AM org.hibernate.tool.hbm2ddl.TableMetadata <init>
    INFO: columns: [content, id, title]
    View Code

    那我们如果操作的是有复合主键的数据库(两个或多个数据库关联)怎么办?分析上面的问题,这个是hibernate它自己提供的jar类包里面的实现出现了错误,所以你可以更换为新版本的类包试试,另一种方法就自行去设计两个(或多个)数据库的关联关系,当然这种方式是比较原始的。

    没有所谓的哪种更好,看具体情况而定。

    hibernate基础学习笔记暂时就是这些。实际上在企业应用中似乎jpa应用得更多,因为管理一个文件就可以了。

    jpa = POJO + @Annotation

    有时间会写一写。

  • 相关阅读:
    mysql 按出现次数排序
    拼接sql
    java 操作 excel
    jQuery ui 利用 datepicker插件实现开始日期(minDate)和结束日期(maxDate)
    android压力测试命令monkey详解
    java css
    iss 默认上传大小为30 M
    PHP自动生成后台导航网址的最佳方法
    PHP 文件上传的综合实例
    php字符串首字母转换大小写的实例
  • 原文地址:https://www.cnblogs.com/nerohwang/p/3508808.html
Copyright © 2011-2022 走看看