|
该帖已经被评为精华帖
|
|
|---|---|
| 作者 | 正文 |
|
时间:2004-10-28
在Java对象里面, 偶们知道一个良好的命名规范会采用大写单词的首字母, 比如订单项这个对象, 偶们会起名为OrderItem, 这样很容易就看出来这个对象是由Order和Item 2个单词组成的, 断词就很容易了, 而属性也是如此, 比如maxPrice, totalPrice等等.
但是如果按照同样的命名规范运到数据库的时候, 由于很多数据库对于表名, 字段名是大小写不敏感的, 所以最常见的策略是加下划线作为断词的依据: OrderItem -> order_item maxPrice -> max_price 这样运用Hibernate的时候, 偶们就得手工在mapping文件里面指明: <class name="OrderItem" table="order_item"> <property name="maxPrice" column="max_price"/> 每个mapping关系都得手工这样写, 是不是很不爽? 现在来介绍一下net.sf.hibernate.cfg.NamingStrategy的用处, 看看它是怎么修理这个问题的, 代码如下: [code:1] import net.sf.hibernate.cfg.NamingStrategy; import net.sf.hibernate.util.StringHelper; /** * An improved naming strategy that prefers embedded underscores to mixed case * names, base on DefaultNamingStrategy and ImprovedNamingStrategy * */ public class UnderscoreNamingStrategy implements NamingStrategy { public static final NamingStrategy INSTANCE = new UnderscoreNamingStrategy(); protected UnderscoreNamingStrategy() { } public String classToTableName(String className) { return addUnderscores(StringHelper.unqualify(className)); } public String propertyToColumnName(String propertyName) { return addUnderscores(StringHelper.unqualify(propertyName)); } public String tableName(String tableName) { return tableName; } public String columnName(String columnName) { return columnName; } public String propertyToTableName(String className, String propertyName) { return classToTableName(className) + '_' + propertyToColumnName(propertyName); } private String addUnderscores(String name) { StringBuffer buf = new StringBuffer(name.replace('.', '_')); for (int i = 1; i < buf.length() - 1; i++) { if ('_' != buf.charAt(i - 1) && Character.isUpperCase(buf.charAt(i)) && !Character.isUpperCase(buf.charAt(i + 1))) { buf.insert(i++, '_'); } } return buf.toString().toLowerCase(); } } [/code:1] 在初始化配置的时候, 把这个NamingStrategy加上: [code:1] Configuration config = new Configuration(); config.setNamingStrategy(UnderscoreNamingStrategy.INSTANCE); [/code:1] 这样mapping文件就变得简单多了: <class name="OrderItem"> <property name="maxPrice"/> NamingStrategy还可以用在其他方面, 比如有些数据库设计规范统一要求Table前面加上模块名称 (如, 属于Order模块的统一加上ORDER_ ), 比如还有些恶心规范统一要求表名和字段名采用4码缩写 (如, OrderItem -> orde_item, maxPrice -> max_pric), 这些都是NamingStrategy可以解决的脏活累活. 声明:JavaEye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
|
|
| 返回顶楼 | |
|
时间:2004-10-30
谢谢!
楼主的文章让我了解了NamingStrategy 并且专门查看相关的代码 |
|
| 返回顶楼 | |
|
时间:2004-11-15
我照楼主的方法试了一下,可是发现UnderscoreNamingStrategy.INSTANCE并没有起作用,我的passWord,数据库里是pass_word,运行提示:
Caused by: java.sql.SQLException: [Microsoft][SQLServer 2000 Driver for JDBC][SQLServer]列名 'passWord' 无效。 能否告诉什么原因呢?谢谢! |
|
| 返回顶楼 | |
|
时间:2004-11-15
把你的相关代码贴出来......
|
|
| 返回顶楼 | |
|
时间:2005-01-24
我在spring里试了一下
[code:1]<bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean"> <property name="dataSource"> <ref local="dataSource"/> </property> <property name="mappingResources"> <list> <value>com/wl/dao/hibernate/model/FgglParent.hbm.xml</value> <value>com/wl/dao/hibernate/model/FgglChilds.hbm.xml</value> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">${hibernate.dialect}</prop> <prop key="hibernate.cache.provider_class">net.sf.ehcache.hibernate.Provider</prop> <prop key="hibernate.show_sql">true</prop> </props> </property> <property name="namingStrategy"><ref bean="nameStrategy"/></property> </bean> <!-- Hibernate NamingStrategy--> <bean id="namingStrategy" class="net.sf.hibernate.cfg.ImprovedNamingStrategy"/>[/code:1] 在这个 <bean id="namingStrategy" class="net.sf.hibernate.cfg.ImprovedNamingStrategy"/> 里我实验了用ImprovedNamingStrategy或者楼主的UnderscoreNamingStrategy 都会得到spring 的包错: org.springframework.beans.factory.BeanDefinitionStoreException: Error registering bean with name 'namingStrategy' defined in class path resource [applicationContext.xml]: Validation of bean definition with name failed; nested exception is org.springframework.beans.factory.support.BeanDefinitionValidationException: No public constructor in class [class net.sf.hibernate.cfg.ImprovedNamingStrategy] org.springframework.beans.factory.support.BeanDefinitionValidationException: No public constructor in class [class net.sf.hibernate.cfg.ImprovedNamingStrategy] at org.springframework.beans.factory.support.RootBeanDefinition.validate(RootBeanDefinition.java:334) at org.springframework.beans.factory.support.DefaultListableBeanFactory.registerBeanDefinition(DefaultListableBeanFactory.java:210) at org.springframework.beans.factory.xml.DefaultXmlBeanDefinitionParser.registerBeanDefinition(DefaultXmlBeanDefinitionParser.java:188) at org.springframework.beans.factory.xml.DefaultXmlBeanDefinitionParser.registerBeanDefinitions(DefaultXmlBeanDefinitionParser.java:155) at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.registerBeanDefinitions(XmlBeanDefinitionReader.java:161) at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:127) at org.springframework.context.support.AbstractXmlApplicationContext.loadBeanDefinitions(AbstractXmlApplicationContext.java:125) at org.springframework.context.support.AbstractXmlApplicationContext.refreshBeanFactory(AbstractXmlApplicationContext.java:65) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:226) at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:58) at com.wl.test.dao.hibernate.TestDAOToSpring.setUp(TestDAOToSpring.java:15) at junit.framework.TestCase.runBare(TestCase.java:125) at junit.framework.TestResult$1.protect(TestResult.java:106) at junit.framework.TestResult.runProtected(TestResult.java:124) at junit.framework.TestResult.run(TestResult.java:109) at junit.framework.TestCase.run(TestCase.java:118) at junit.framework.TestSuite.runTest(TestSuite.java:208) at junit.framework.TestSuite.run(TestSuite.java:203) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:421) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:305) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:186) ---------------------------------------------------------------------- org.springframework.beans.factory.support.BeanDefinitionValidationException: No public constructor in class [class net.sf.hibernate.cfg.ImprovedNamingStrategy] spring要求要public的构造方法才可以吗? |
|
| 返回顶楼 | |
|
时间:2005-01-25
看到ReadOnly提到不爽,想起一个问题。
如果pojo放得比较深,如com.xxx.wap.Book,在写hql的时候要把类的完整package+classname写进去,如"select book.name from com.xxx.wap.Book book",也是N不爽。有没有办法给他一个alias什么的,精简为"select book.name from Book book"?(不过自己感觉希望好像不大。。。。) |
|
| 返回顶楼 | |
|
时间:2005-01-25
引用 在写hql的时候要把类的完整package+classname写进去
不需要,只写类的classname就可以了。除非你关掉auto-import,你才需要写packagename |
|
| 返回顶楼 | |
|
时间:2005-01-25
doninox 写道 spring要求要public的构造方法才可以吗?
Yes, 你可以写一个Class extends org.springframework.orm.hibernate.LocalSessionFactoryBean 复写newConfiguration方法: [code:1] protected Configuration newConfiguration() throws HibernateException { Configuration config = new Configuration(); config.setNamingStrategy(UnderscoreNamingStrategy.INSTANCE); return config; } [/code:1] |
|
| 返回顶楼 | |
|
时间:2005-01-25
明白了 谢谢!
|
|
| 返回顶楼 | |
|
时间:2005-03-14
可以在xdoclet生成.hbm.xml时也使用NamingStrategy嘛?不知道各位如果用了NamingStrategy后,*.hbm.xml怎么生成,特别是[code:1]<property
name="postalCode" type="java.lang.String" update="true" column="postalCode" insert="true" length="45" />[/code:1] 类似上面这种情况,数据库中的列名其实是postal_code。 |
|
| 返回顶楼 | |











