eclipse上依据hibernate tools逆向生成PO(Domain Object)的过程-阿里云开发者社区

开发者社区> pandamonica> 正文

eclipse上依据hibernate tools逆向生成PO(Domain Object)的过程

简介: 使用eclipse开发一个基于java的maven的web项目,业务逻辑基于spring实现,数据库服务器采用mysql。我们项目的业务逻辑(面向对象)和数据(关系型数据库)之间,依靠hibernate进行映射、对应、使用和处理。
+关注继续查看

使用eclipse开发一个基于java的maven的web项目,业务逻辑基于spring实现,数据库服务器采用mysql。我们项目的业务逻辑(面向对象)和数据(关系型数据库)之间,依靠hibernate进行映射、对应、使用和处理。
hibernate的核心功能之一,就是在面向对象和关系型数据库之间建立转化和映射,让程序员用面向对象的方式看待关系型数据库。(让数据库对程序员透明)
开发过程中,为了保持二者的一致,需要进行Domain Object这种POJO的逆向生成。也就是依据mysql数据库中数据表,在eclipse这个IDE中,通过eclipse的Hibernate插件,生成Domain Object的java代码,这样就可确保二者保持一致。
eclipse上的配置操作如下所示:
在自己eclipse上market中确保install了jboss也就是hibernate的相关plugin
_
1---使用eclipse连接mysql

我们的开发环境中,mysql就部署在开发机本机,也就是说tomcat mysql eclipse三者都在同一台电脑上。
打开eclipse上的data source explorer窗口
_
_
_
最开始需要你自己新建一个Driver,也就是选一下你用的什么数据库,本地的jdbc jar文件,输入一下你以前事先,在mysql上配置好的url用户名密码之类的。
_
_
搞定以后,finish
_
可以看到我们的eclipse已经完全连接上了本地我们要是用的mysql中的test2数据库。

2---为eclipse上的web项目添加hibernate tools相关的配置文件
目的是让我们的web项目关联上mysql数据库,并且要通过hibernate tools进行关联。这一步最开始我遇到了麻烦,产生了报错,结果就是无法通过hibernate tools将web项目和mysql关联,好在我找到了原因,下面将整个过程详述一下。
在项目上右键,new,添加一个hibernate configuration file
_
_
下面Hibernate version这里需要注意,我们eclipse安装的JBoss的插件版本、pom中Hibernate的版本、本配置文件所使用的hibernate版本是否需要三者保持一致呢?答案是否定的。我们只需要保证pom中的版本和此处配置文件版本一致。
_
版本一致的鉴定方法如下图:pom与配置文件一致
screenshot
反而是eclipse的jboss插件和hibernate没有什么直接的版本关系
screenshot

_
_
_
_
点击finish以后,出现如下所示的报错:Reading schema error:Error calling Driver#connect
_
说实话这个报错英文字面意思比较清晰,但是实际对调试的指导意义为零,而且百度了一下也不知道怎么应对。
connect
最后我猜,应该是connector的问题
于是在上面几步connector那一步,修改了一下引用的jar文件
_
_
_
看,调通了。也就是说,我为我们的web项目添加一个hibernate tools配置文件,让web项目关联上了mysql数据库。

3--逆向生成java代码
_
_
_
_
_
_
_
_
_
然后点击run按钮
_
看,生成了很多java代码。有很多报错的原因,因为这个web项目是刚刚创建的maven web项目,还没有修改pom.xml文件,很多hibernate的jar包还没有导入。
但是逆向工程,已经成功生成了代码,哈哈
POM.xml修改如下

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>tsmi.com</groupId>
  <artifactId>tangtools</artifactId>
  <packaging>war</packaging>
  <version>0.0.1-SNAPSHOT</version>
  <name>tangtools Maven Webapp</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
        <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>5.2.11.Final</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate.javax.persistence</groupId>
        <artifactId>hibernate-jpa-2.0-api</artifactId>
        <version>1.0.1.Final</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate.common</groupId>
        <artifactId>hibernate-commons-annotations</artifactId>
        <version>5.0.1.Final</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-entitymanager</artifactId>
        <version>5.2.11.Final</version>
    </dependency>
  </dependencies>
  <build>
    <finalName>tangtools</finalName>
  </build>
</project>

_
在正式项目中,通过hibernate tools转化mysql对应的PO,最初效果如下:
_
结果很让人心痛,原因是target folder和package设置重复了,那么我们把关键步骤单独拿出来,看看应该怎样设置:
_
_
顺利生成PO文件以后,我们要将过去单独使用spring进行数据库连接和事务管理的配置文件修改为,spring+hibernate环境下的配置文件。另外过去采用dbcp的数据库封装,现在改用阿里巴巴的druid进行封装。过去直接将各种需要的参数用字符串的形式直接表现出来,现在将配置信息统一放置在properties文件中保存。
过去我们的spring的ApplicationContext.xml配置文件,就一个。
现在变成两个,并重新命名
mysqlHibernateContext.xml文件
mysqlHibernateContext.properties文件
如下所示:

<?xml version="1.0" encoding="UTF-8"?>  
<!-- 集成hibernate之后的Spring的applicationContext配置文件 -->
<!-- mysql dao和service层的Spring配置文件 -->
<beans xmlns="http://www.springframework.org/schema/beans"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop" 
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:util="http://www.springframework.org/schema/util"
    xmlns:jdbc="http://www.springframework.org/schema/jdbc" 
    xmlns:cache="http://www.springframework.org/schema/cache"
    
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        classpath:/org/springframework/beans/factory/xml/spring-beans.xsd     
        http://www.springframework.org/schema/context
        classpath:/org/springframework/context/config/spring-context.xsd
        http://www.springframework.org/schema/aop
        classpath:/org/springframework/aop/config/spring-aop.xsd
        http://www.springframework.org/schema/tx
        classpath:/org/springframework/transaction/config/spring-tx.xsd
        http://www.springframework.org/schema/jdbc
        classpath:/org/springframework/jdbc/config/spring-jdbc.xsd">     
        
    <context:component-scan base-package="com.tsmi.mysql.dao"/>
    <context:component-scan base-package="com.tsmi.mysql.service"/>
    <context:component-scan base-package="com.tsmi.mysql.web"/>
    <!--配置文件-->    
    <bean id="propertyConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
     <property name="locations">
         <list>       <value>classpath:/mysqlHibernateContext.properties</value>
         </list>
     </property>
    </bean>
        
    <!-- 配置mysql数据源, 阿里巴巴的druid-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
        destroy-method="close" 
        p:driverClassName="${jdbc.driver}"
        p:url="${jdbc.url}"
        p:username="${jdbc.username}"
        p:password="${jdbc.password}" 
        p:initialSize="${ds.initialSize}"
        p:minIdle="${ds.minIdle}"
        p:maxActive="${ds.maxActive}"
        p:maxWait="${ds.maxWait}"
        p:timeBetweenEvictionRunsMillis="${ds.timeBetweenEvictionRunsMillis}"
        p:minEvictableIdleTimeMillis="${ds.minEvictableIdleTimeMillis}"
        p:removeAbandoned="${ds.removeAbandoned}"
        p:removeAbandonedTimeout="${ds.removeAbandonedTimeout}"
        p:defaultAutoCommit="true" />
        
    <!-- spring为集成hibernate提供的LocalSessionFactoryBean -->    
    <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
       <property name="dataSource" ref="dataSource"/>
       <property name="hibernateProperties">
          <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.format_sql">true</prop>
          </props>
       </property>
       <property name="packagesToScan" value="com.tsmi.hibernate.entity"/>
    </bean>
    <!-- 配置事务管理器 -->
     <bean id="transactionmanager" class="org.springframework.orm.hibernate5.HibernateTransactionManager"> 
         <property name="sessionFactory" ref="sessionFactory"/>
    </bean> 
    
    <!-- 配置JdbcTemplate -->
    <bean id="jdbcTemplate" 
        class="org.springframework.jdbc.core.JdbcTemplate">
         <property name="dataSource" ref="dataSource"/>
    </bean>    
</beans> 

properties文件

#database connection
jdbc.dbType=mysql
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:6062/test2?characterEncoding=utf8&serverTimezone=UTC
jdbc.username=root
jdbc.password=哈哈哈哈

sys.singleOnline=false

#hibernate property

ds.initialSize=1
ds.minIdle=1
ds.maxActive=20
ds.maxWait=60000
ds.timeBetweenEvictionRunsMillis=60000
ds.minEvictableIdleTimeMillis=300000
ds.removeAbandoned=true
ds.removeAbandonedTimeout=180

上面的配置文件修改以后,运行eclipse上以前的test文件,可以测试代码顺利运行。
上述过程,通过hibernate tools生成PO以后,我们做了哪些操作呢?
1---在Spring配置文件中,加入hibernate的配置信息;
2---在Spring配置文件中,将dbcp替换为druid
3---将Spring配置文件中的字符串,换成了properties文件中的变量;
但是上述过程中,出现了很多个报错,当我运行testNG中的测试代码时,有很多报错,调试报错的过程无法复述,简要列举一下:
1---java.lang.ClassNotFoundException:org.dom4j.io.STAXEventReader
解决办法,从新,单独再次在pom.xml文件中导入dom4j
_
2---java.lang.NoClassDefFoundError: javassist/util/proxy/MethodFilter
解决办法:
_
3---org.hibernate.type.StringType cannot be cast to org.hibernate.type.VersionType
_
检验标准这个表中原来有个字段叫做version,必须把这个名字改了,我改成了如图所示的verno
然后重新用powerDesigner生成数据库文件导入mysql,也就是把mysql的表结构重新生成一下
4---cannot convert sessionfactoryimpl datasource
反正我就把powerDesigner中所有表都过滤了一遍,只要是属性字段,必须全部小写:比如QC这个字段,改为qc
5---bean property is not writeable or has an invalid setter method
说实话我压根不知道自己怎么调好的,最后我把applicationContext.xml文件中事务相关的配置,从spring的事务修改为hibernate,然后就好了,费解。
_
反正,最终test代码可以用了。

下面,截图演示一下从powerDesigner绘制uml图到mysql生成数据库表,到eclipse中形成po代码的过程:
_
打开powerDesigner
_
生成
_
生成*.sql文件
_
文件长这个样子
_
在phpmyadmin中创建一个空的名为test2的数据库
_
进入导入页面
_
_
_

完成导入后在mysql中生成数据表,然后我们使用Navicat for MySQL这个软件,从事先准备好的excel表导入一些数据给mysql中刚刚创建名为test2的数据库。
_
_
_
中间出了错误,原因是字段长度,这个我们以后再改好了。看看效果
_
现在有了数据库数据表,也有了部分数据,方便今后进行验证。我们去eclipse的hibernate tools看看。
回到eclipse,之前如何安装jboss tools,如何使用data source explorer和hibernate configuration的过程不再赘述,假设现在已经成功配置,那么我们直接来生成po代码:
_
_
_
生成了代码
刚刚生成出来po代码的时候,如果直接启动tomcat,会有报错如下所示:
_

INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQLDialect
十二月 19, 2017 5:23:10 下午 org.springframework.web.context.support.XmlWebApplicationContext refresh
警告: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in class path resource [mysqlHibernateContext.xml]: Invocation of init method failed; nested exception is java.lang.NoSuchMethodError: javax.persistence.JoinTable.indexes()[Ljavax/persistence/Index;
十二月 19, 2017 5:23:10 下午 com.alibaba.druid.pool.DruidDataSource info
信息: {dataSource-1} closed
十二月 19, 2017 5:23:10 下午 org.springframework.web.context.ContextLoader initWebApplicationContext
严重: Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in class path resource [mysqlHibernateContext.xml]: Invocation of init method failed; nested exception is java.lang.NoSuchMethodError: javax.persistence.JoinTable.indexes()[Ljavax/persistence/Index;
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1704)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory

Caused by: java.lang.NoSuchMethodError: javax.persistence.JoinTable.indexes()[Ljavax/persistence/Index;
    at org.hibernate.cfg.AnnotationBinder.bindJoinedTableAssociation(AnnotationBinder.java:2380)

十二月 19, 2017 5:23:10 下午 org.apache.catalina.core.StandardContext listenerStart
严重: Exception sending context initialized event to listener instance of class [org.springframework.web.context.ContextLoaderListener]
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in class path resource [mysqlHibernateContext.xml]: Invocation of init method failed; nested exception is java.lang.NoSuchMethodError: javax.persistence.JoinTable.indexes()[Ljavax/persistence/Index;


警告: The web application [RepositoryCheck] appears to have started a thread named [Abandoned connection cleanup thread] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
 java.lang.Object.wait(Native Method)
 java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
 com.mysql.jdbc.AbandonedConnectionCleanupThread.run(AbandonedConnectionCleanupThread.java:64)
 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
 java.lang.Thread.run(Thread.java:748)

百度了一下java nosuchmethoderror javax persistence table indexes按照里面介绍的方法修改java代码如下图
_
验证,至少修改并停止使用@Table这个标签,改用@Entity标签以后,可以顺利启动Tomcat服务器。
但是上述解决问题的方法是十分残酷的,因为@Table标签代表的是mysql的表名,@Entity标签代表的是java代码的类名
比如
_
我们最初进行uml设计的时候命名的是mysql中的表的名字,后面hibernate tools生成po名字的时候我们都没有进行人工干预,现在PO生成了以后,你让我手动把所有java代码里的类名由自动生成的PO名,手动改成与uml中一样的数据库名字?这个工作量太大,而且太不科学。
参考蒋锋的POM.xml文件,修改hibernate对应依赖的版本,试试看。修改后hibernate相关的部分如下所示:

 <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>5.2.3.Final</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate.javax.persistence</groupId>
        <artifactId>hibernate-jpa-2.1-api</artifactId>
        <version>1.0.0.Final</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-entitymanager</artifactId>
        <version>5.2.3.Final</version>
    </dependency>
    <dependency>
        <groupId>org.jboss.logging</groupId>
        <artifactId>jboss-logging</artifactId>
        <version>3.3.0.Final</version>
    </dependency>
        <dependency>
        <groupId>org.hibernate.common</groupId>
        <artifactId>hibernate-commons-annotations</artifactId>
        <version>5.0.1.Final</version>
    </dependency>

修改以后update projects
奇迹发生了如下图
_
不再报错,那么我们可以继续了。
回到文章的开头,我们为什么要在eclipse上通过jboss插件依据mysql的数据库的结构(数据表、字段等信息)生成java端的PO代码呢?答案是:为了保持数据库表和PO代码(关系型数据库与面向对象的类)之间的一致性。

我们回顾一下,在纯粹使用Spring(spring JDBC)编码的阶段,我们的DAO层代码文件中,注入(@Autowired)了JdbcTemplate类的实例去操纵的是手写的domain object。这些DO不需要采用@标注,他们只是很普通的POJO。我们也不需要在Spring配置文件中特别的去扫描他们。因为Spring JDBC的核心其实只是对Java JDBC的封装,它完成的工作只是执行SQL语句,将返回值保存入比如ArrayList这类java容器,容器中每一个元素都是DO,也就是我们自定义的java类。
从上述描述我们可以看到,单纯使用Spring JDBC访问数据库的时候,Domain层的POJO不需要被注册的。
但是我们改用Hibernate访问数据库以后,必须在Spring的配置文件中明确配置两个内容:
1.Hiberante
2.PO代码的文件夹(让Spring扫描这个文件夹)

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
阿里云服务器怎么设置密码?怎么停机?怎么重启服务器?
如果在创建实例时没有设置密码,或者密码丢失,您可以在控制台上重新设置实例的登录密码。本文仅描述如何在 ECS 管理控制台上修改实例登录密码。
4076 0
手把手教你生成对抗网络 GAN,50 行代码玩转 GAN 模型!
本文为大家介绍了生成对抗网络(Generate Adversarial Network,GAN),以最直白的语言来讲解它,最后实现一个简单的 GAN 程序来帮助大家加深理解。
1588 0
sublime生成html骨架|学习笔记
快速学习 sublime生成html骨架
19 0
SIGIR-2018-EASR workshop keynote,阿士比亚:阿里巴巴智能内容生成实践
研讨会由罗格斯大学计算机系张永锋老师、加州大学圣克鲁兹分校计算机系张奕老师、清华大学计算机系张敏老师共同主办,张永锋老师现场主持。
1483 0
IDEA 中 30 秒生成 Spring Cloud Alibaba 工程
近日,阿里巴巴发布了 Spring 的国内脚手架定制版 Aliyun Java Initializer,因为全中文界面和流畅速度,被广大开发者热传。Spring 脚手架为开发者提供了丰富的可选组件,并且可以选择多种打包方式,大大方便了开发人员的使用。
10366 0
64bit libcurl.lib生成步骤及注意事项详解
64bit libcurl.lib生成步骤及注意事项详解
215 0
MyEclipse 从数据库反向生成Hibernate实体类
         第一个大步骤 window-->open Perspective-->MyEclipse Java Persistence 进行了上面的 操作后会出现一个视图DB Brower:MyEclipse Derby,点击右键新建一个在出现的面板中,driver templat...
800 0
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
4519 0
双 11 模块 79.34% 的代码是怎样智能生成的?
作为今年阿里经济体前端委员会的四大技术方向之一,前端智能化方向一被提及,就不免有人好奇:前端结合 AI 能做些什么,怎么做,未来会不会对前端产生很大的冲击等等。本篇文章将围绕这些问题,以「设计稿自动生成代码」场景为例,从背景分析、竞品分析、问题拆解、技术方案等几个角度切入,细述相关思考及过程实践。
9254 0
EnjoyCSS – 在线的,先进的 CSS3 代码生成器
  EnjoyCSS 是一款先进的 CSS3 代码生成工具,可以让你摆脱日常的编码。它方便和易于使用的用户界面允许您快速,无需编码就可以调节出丰富的图形样式。您将能够玩转所有的 EnjoyCSS 参数,就像在 Photoshop 或 illustarator 中一样,结合所有可能的 CSS3 样式功能。
1014 0
+关注
147
文章
3
问答
文章排行榜
最热
最新
相关电子书
更多
文娱运维技术
立即下载
《SaaS模式云原生数据仓库应用场景实践》
立即下载
《看见新力量:二》电子书
立即下载