颠覆软件

关注 : 架构与设计,敏捷,快速开发,项目管理,执行力,SSH,RoR

MiddleGen怪问题,生成的hbm.xml文件的数据类型和数据库类型不一致

Filed under: hibernate — Alex at 2:32 pm on Friday, February 24, 2006

keyword:MySql字段,Hibernate session,MiddleGen

一.MySql字段敏感

这几天怪问题真是不少,这不刚建的一个数据库的表用MiddleGen批量生成hbm.xml文件居然和数据库的数据类型不一致.
MySql建表语句如下:

drop table if exists book;

/*==============================================================*/
/* Table: book                                                  */
/*==============================================================*/
create table book
(
id                             
int                            not null,
name                           
varchar(100),
author                         
varchar(100),
date                           date,
price                          
int,
primary key (id)
)
comment
=“Book table”
type 
= InnoDB;
生成的hbm.xml文件如下:

<?xml version=”1.0″?>
<!DOCTYPE hibernate-mapping PUBLIC
“-//Hibernate/Hibernate Mapping DTD 2.0//EN”
“http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd” 
>

<hibernate-mapping>
<!–
Created by the Middlegen Hibernate plugin 2.1

http://boss.bekk.no/boss/middlegen/
http://www.hibernate.org/
–>

<class
name=”net.foxlog.prj.Book”
table
=”book”
>
<meta attribute=”class-description” inherit=”false”>
@hibernate.class
table=”book”
</meta>

<id
name=”id”
type
=”java.lang.Long”
column
=”id”
>
<meta attribute=”field-description”>
@hibernate.id
generator-class=”assigned”
type=”java.lang.Long”
column=”id”

</meta>
<generator class=”assigned” />
</id>

<property
name=”name”
type
=”java.lang.String”
column
=”name”
length
=”100″
>
<meta attribute=”field-description”>
@hibernate.property
column=”name”
length=”100″
</meta>
</property>
<property
name=”author”
type
=”java.lang.String”
column
=”author”
length
=”100″
>
<meta attribute=”field-description”>
@hibernate.property
column=”author”
length=”100″
</meta>
</property>
<property
name=”date”
type
=”java.sql.Date”
column
=”date”
length
=”10″
>
<meta attribute=”field-description”>
@hibernate.property
column=”date”
length=”10″
</meta>
</property>
<property
name=”price”
type
=”java.lang.String”
column
=”price”
length
=”10″
>
<meta attribute=”field-description”>
@hibernate.property
column=”price”
length=”10″
</meta>
</property>

<!– Associations –>

</class>
</hibernate-mapping>

注意到没有,id的类型变成了Long型了,而price居然变成了String了,晕啊.

各位碰到过这个问题么?

最后还是找到问题所在了,实际上是建表有问题,问题就出在字段的名称上,把id改为ID,price改为PRICE就没问题了!  MySql对id和price敏感? 不得而知,目前看来好像是这样.只是提醒我以后建表养成一个习惯,都用大写的就没问题了.
没想到一次测试中随便建的一个表发现了这么个有趣的事情  :)

二.Hibernate的session关闭问题
用hibernate的工具类获得session有没有碰到过session is closed的错误提示? 我又幸运的碰到这个问题了,呵呵,我怎么有那么多问题啊,晕了,我看来是问题先生了,我的一个同事上次也跟我说过这个事情,后来他没有正面解决这个,绕过去了,他用Spring去替自己解决了,呵呵,也够狠的.不过问题实际上是获得session的时候需要增加一个判断. 即 session.isOpen() == false;

DBUtil.java代码如下:

/**
* 返回一个可用的数据库Session连接
@return Hibernate中对数据库的Session连接
@throws HibernateException
*/
public static Session currentSession() throws HibernateException
{
Session s 
= (Session) session.get();
// Open a new Session, if this Thread has none yet
        if (null==|| s.isOpen()==false)//注意这里
{
= sessionFactory.openSession();
session.set(s);
}
return s;
}

奇怪,hibernate-extensions生成的POJO没有equals和hashCode方法

Filed under: hibernate — Alex at 2:33 pm on Friday, February 17, 2006

到网上搜索了半天都说什么要在hbm.xml文件里写什么implements equals,但是心想如果都在这个里面手工写那还有什么方便之处啊.

原因终于找到,原来是高版本不行,我用的是2.1.2,而2.0.2则没问题,确切的说把hibernate-tools.jar换为2.0.2的即可

附配置说明:
不需要记复杂的命令,只要一次配置好Middlegen-Hibernate-r5目录下的build.xml文件即可,以后则需要运行
ant

ant hbm2java即可
注:前者生成数据库对应的所有hbm.xml文件,后者生成hbm.xml对应的所有POJO

build.xml配置如下:

<?xml version=”1.0″?>

<!–
This is a testing platform for the middlegen hibernate plugin. It is a stripped
down version of the samples application. At the moment it is only concerned
with the generation of the mapping documents so that various tests etc can be
done on the generated package.

David Channon

The DOCTYPE declaration declares the location of product-specific parts of the
Ant build file. You can change the values of these declarations to point to
other available files. This gives you an opportunity to choose what database.

Note that this syntax has nothing to do with Ant or Middlegen. This
is the standard way defined by w3c to dynamically include external
files in an XML document. Any decent XML parser will do the include
transparently. Try to open this file in Internet Explorer and see
for yourself.
–>

<!DOCTYPE project [
<!ENTITY database SYSTEM "file:./config/database/mysql.xml"
>
]>

<project name=”Middlegen Hibernate” default=”all” basedir=”.”>

<!– project name=”Middlegen Hibernate” default=”all” basedir=”.” –>

<property file=”${basedir}/build.properties”/>
<property name=”name” value=”bona”/>

<property name=”myPackage” value=”cn.com.chinagc.cpms.model.po”/>

<!– This was added because we were several people (in a course) deploying to same app server>
<property environment=”env”/>
<property name=”unique.name”                    value=”${name}.${env.COMPUTERNAME}”/
–>

<property name=”gui”                            value=”false”/>

<property name=”unique.name”                    value=”${name}”/>

<property name=”appxml.src.file”                value=”${basedir}/src/application.xml”/>
<property name=”lib.dir”                        value=”${basedir}/lib”/>
<property name=”src.dir”                        value=”${basedir}/src”/>
<property name=”java.src.dir”                   value=”${src.dir}/java”/>
<property name=”web.src.dir”                    value=”${src.dir}/web”/>

<property name=”build.dir”                      value=”${basedir}/build”/>
<property name=”build.java.dir”                 value=”${build.dir}/java”/>
<property name=”build.gen-src.dir”              value=”${build.dir}/gen-src”/>
<property name=”build.classes.dir”              value=”${build.dir}/classes”/>

&database;

<!– define the datasource.jndi.name in case the imported ejb file doesn’t –>
<property name=”datasource.jndi.name”           value=”${name}/datasource”/>

<path id=”lib.class.path”>
<pathelement path=”${database.driver.classpath}”/>
<fileset dir=”${lib.dir}”>
<include name=”*.jar”/>
</fileset>
<!– The middlegen jars –>
<!–fileset dir=”${basedir}/..”–>
<fileset dir=”${basedir}/middlegen-lib”>
<include name=”*.jar”/>
</fileset>
</path>

<target name=”init”>
<available property=”xdoclet1.2+” classname=”xdoclet.modules.hibernate.HibernateDocletTask” classpathref=”lib.class.path”/>
</target>

<!– =================================================================== –>
<!– Fails if XDoclet 1.2.x is not on classpath                          –>
<!– =================================================================== –>
<target name=”fail-if-no-xdoclet-1.2″ unless=”xdoclet1.2+”>
<fail>
You must download several jar files before you can build Middlegen.
</fail>
</target>

<!– =================================================================== –>
<!– Create tables                                                       –>
<!– =================================================================== –>
<target
name=”create-tables”
depends
=”init,fail-if-no-xdoclet-1.2,check-driver-present,panic-if-driver-not-present”
description
=”Create tables”
>
<echo>Creating tables using URL ${database.url}</echo>
<sql
classpath=”${database.driver.classpath}”
driver
=”${database.driver}”
url
=”${database.url}”
userid
=”${database.userid}”
password
=”${database.password}”
src
=”${database.script.file}”
print
=”true”
output
=”result.txt”
/>
</target>
<target name=”check-driver-present”>
<available file=”${database.driver.file}” type=”file” property=”driver.present”/>
</target>
<target name=”panic-if-driver-not-present” unless=”driver.present”>
<fail>
The JDBC driver you have specified by including one of the files in ${basedir}/config/database
doesn’t exist. You have to download this driver separately and put it in ${database.driver.file}
Please make sure you’re using a version that is equal or superior to the one we looked for.
If you name the driver jar file differently, please update the database.driver.file property
in the ${basedir}/config/database/xxx.xml file accordingly.
</fail>
</target>

<!– =================================================================== –>
<!– Run Middlegen                                                       –>
<!– =================================================================== –>
<target
name=”middlegen”
description
=”Run Middlegen”
unless
=”middlegen.skip”
depends
=”init,fail-if-no-xdoclet-1.2,check-driver-present,panic-if-driver-not-present”
>
<mkdir dir=”${build.gen-src.dir}”/>

<echo message=”Class path = ${basedir}”/>
<taskdef
name=”middlegen”
classname
=”middlegen.MiddlegenTask”
classpathref
=”lib.class.path”
/>

<middlegen
appname=”${name}”
prefsdir
=”${src.dir}”
gui
=”${gui}”
databaseurl
=”${database.url}”
initialContextFactory
=”${java.naming.factory.initial}”
providerURL
=”${java.naming.provider.url}”
datasourceJNDIName
=”${datasource.jndi.name}”
driver
=”${database.driver}”
username
=”${database.userid}”
password
=”${database.password}”
schema
=”${database.schema}”
catalog
=”${database.catalog}”
>

<!–
We can specify what tables we want Data generated for.
If none are specified, Data will be generated for all tables.
Comment out the <table> elements if you want to generate for all tables.
Also note that table names are CASE SENSITIVE for certain databases,
so on e.g. Oracle you should specify table names in upper case.
–>
<!–table generate=”true” name=”flights” pktable=”flights_pk”/>
<table name=”reservations”/
–>

<!–
If you want m:n relations, they must be specified like this.
Note that tables declare in multiple locations must all have
the same value of the generate attribute.
–>
<!–many2many>
<tablea generate=”true” name=”persons”/>
<jointable name=”reservations” generate=”false”/>
<tableb generate=”true” name=”flights”/>
</many2many
–>

<!– Plugins - Only Hibernate Plugin has been included with this special distribution  –>

<!–
If you want to generate XDoclet markup for hbm2java to include in the POJOs then
set genXDocletTags to true. Also, composite keys are generated as external classes which is
recommended. If you wish to keep them internal then set genIntergratedCompositeKeys to true.
Since r4 the ability to customise the selection of JavaTypes is now provided. The is a
recommended type mapper provided as shown. It is optional - if not provided then Middlegen
itself will select the Java mapping (as it did previously).
These settings are optional thus if they are not define here values default to false.
–>
<hibernate
destination=”${build.gen-src.dir}”
package
=”${myPackage}”
genXDocletTags
=”true”
genIntergratedCompositeKeys
=”false”
javaTypeMapper
=”middlegen.plugins.hibernate.HibernateJavaTypeMapper”
/>

</middlegen>

<mkdir dir=”${build.classes.dir}”/>
</target>

<!– =================================================================== –>
<!– Compile business logic (hibernate)                                        –>
<!– =================================================================== –>
<target name=”compile-hibernate” depends=”middlegen” description=”Compile hibernate Business Domain Model”>
<javac
srcdir=”${build.gen-src.dir}”
destdir
=”${build.classes.dir}”
classpathref
=”lib.class.path”
>
<include name=”**/hibernate/**/*”/>
</javac>
</target>

<!– =================================================================== –>
<!– Run hbm2java    depends=”middlegen”                                 –>
<!– =================================================================== –>
<target name=”hbm2java” description=”Generate .java from .hbm files.”>
<taskdef
name=”hbm2java”
classname
=”net.sf.hibernate.tool.hbm2java.Hbm2JavaTask”
classpathref
=”lib.class.path”
/>

<hbm2java output=”${build.gen-src.dir}”>
<fileset dir=”${build.gen-src.dir}”>
<include name=”**/*.hbm.xml”/>
</fileset>
</hbm2java>
</target>

<!– =================================================================== –>
<!– Build everything                                                    –>
<!– =================================================================== –>
<target name=”all” description=”Build everything” depends=”compile-hibernate”/>

<!– =================================================================== –>
<!– Clean everything                                                    –>
<!– =================================================================== –>
<target name=”clean” description=”Clean all generated stuff”>
<delete dir=”${build.dir}”/>
</target>

<!– =================================================================== –>
<!– Brings up the hsqldb admin tool                                     –>
<!– =================================================================== –>
<target name=”hsqldb-gui” description=”Brings up the hsqldb admin tool”>
<property name=”database.urlparams” value=”?user=${database.userid}&amp;password=${database.password}”/>
<java
classname=”org.hsqldb.util.DatabaseManager”
fork
=”yes”
classpath
=”${lib.dir}/hsqldb-1.7.1.jar;${database.driver.classpath}”
failonerror
=”true”
>
<arg value=”-url”/>
<arg value=”${database.url}${database.urlparams}”/>
<arg value=”-driver”/>
<arg value=”${database.driver}”/>
</java>
</target>

<!– ==================================================================== –>
<!– Validate the generated xml mapping documents                         –>
<!– ==================================================================== –>
<target name=”validate”>
<xmlvalidate failonerror=”no” lenient=”no” warn=”yes”>
<fileset dir=”${build.gen-src.dir}/airline/hibernate” includes=”*.xml” />
</xmlvalidate>
</target>

</project>

记得把2.0.2下面的hibernate-tools.jar文件拷贝到Middlegen-Hibernate-r5\lib下
,当然config下面的数据库配置文件也要设置为你自己的环境

如果你不想用ant来自动化做也可以通过dos命令行的方式来执行,命令如下:
hbm2java c:\sample\org\hibernate\sample\*.xml –output=c:\sample\
,前提是要设置下hibernate-extensions-2.1.2\tools\bin下的setenv.dat文件

log4j配置

Filed under: java开发技术 — Alex at 2:38 pm on Thursday, February 16, 2006

log4j配置,原来以为需要程序种写config,实际上不用,只要提供配置文件放到classpath下即可,示例配置如下:

### direct log messages to stdout ###
log4j.appender.stdout
=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target
=System.out
log4j.appender.stdout.layout
=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern
=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### direct messages to file hibernate.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File
=hibernate.log
log4j.appender.file.layout
=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern
=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### set log levels - for more verbose logging change ’info’ to ’debug’ ###

log4j.rootLogger=info,stdout,file

log4j.logger.net.sf.hibernate=info

### log just the SQL
#log4j.logger.net.sf.hibernate.SQL=debug

### log JDBC bind parameters ###
log4j.logger.net.sf.hibernate.type=info

### log schema export/update ###
log4j.logger.net.sf.hibernate.tool.hbm2ddl=debug

### log cache activity ###
#log4j.logger.net.sf.hibernate.cache=debug

### enable the following line if you want to track down connection ###
### leakages when using DriverManagerConnectionProvider ###
#log4j.logger.net.sf.hibernate.connection.DriverManagerConnectionProvider=trace