J2EE--Hibernate基础笔记

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

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

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

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

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

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

J2EE--Hibernate基础笔记_第1张图片

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

J2EE--Hibernate基础笔记_第2张图片

其中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,然后我们自行在数据库中创建对应的数据库和表即可,上面已经给出语法了。

J2EE--Hibernate基础笔记_第3张图片

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

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

/****************************************************************
第一,读取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

有时间会写一写。

 

 

 

你可能感兴趣的:(Hibernate)