【问题标题】:Different behavior/content of Spring/Hibernate/SessionFactory when running Maven+Surefire vs Eclipse+jUnit运行 Maven+Surefire 与 Eclipse+jUnit 时 Spring/Hibernate/SessionFactory 的不同行为/内容
【发布时间】:2011-04-02 07:12:07
【问题描述】:

我尽量快。

事实上,当我在 Eclipse 中运行它时,运行项目的 Maven 命令(mvn install,因此使用 Surefire 插件)时,我的一个 jUnit 测试失败了。

我尝试了很多东西,但我设法看到的唯一区别是: - 在调试模式下使用 Maven/Surefire,在 Hibernate-SessionFactory 我只有 3 个 EntityPersister 实例 - 使用 Eclipse 在调试透视图中,我可以看到 6 个 EntityPersister 实例(实际上是我项目中的 annotatedClasses 的数量)

这是我的 Spring 配置文件(“dataSource”是在另一个项目中定义的,我没有放 DAO 类):

<beans ...>

 <!-- le gestionnaire de BLOB / CLOB de chez Spring -->
 <bean id="lobHandler" class="org.springframework.jdbc.support.lob.DefaultLobHandler" />

 <!-- Hibernate SessionFactory Definition -->
 <bean id="sessionFactory"
  class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
  <property name="hibernateProperties">
   <props>
    <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
    <prop key="hibernate.show_sql">true</prop>
    <prop key="hibernate.hbm2ddl.auto">create</prop>
   </props>
  </property>
  <property name="dataSource">
   <ref bean="datasource" />
  </property>
  <property name="packagesToScan">
   <list>
    <value>com.wft.model</value>
    <value>com.wft.model.user</value>
   </list>
  </property>
  <!-- 
  <property name="annotatedClasses">
   <list>
    <value>com.wft.model.Project</value>
    <value>com.wft.model.Authors</value>
    <value>com.wft.model.user.User</value>
    <value>com.wft.model.user.Administrator</value>
    <value>com.wft.model.user.Gamer</value>
    <value>com.wft.model.user.Organizer</value>
   </list>
  </property>
   -->
  </bean>

 <!-- Hibernate Transaction Manager Definition -->
 <bean id="transactionManager"
  class="org.springframework.orm.hibernate3.HibernateTransactionManager">
  <property name="sessionFactory" ref="sessionFactory" />
 </bean>

 <!-- TODO: Switch to annotations for transactions
 <tx:annotation-driven/>
 -->
 <bean id="transactionInterceptor"
  class="org.springframework.transaction.interceptor.TransactionInterceptor">
  <property name="transactionManager" ref="transactionManager" />
  <property name="transactionAttributes">
   <props>
    <prop key="*">PROPAGATION_REQUIRED</prop>
   </props>
  </property>
 </bean>

 <!-- -->
 <bean id="autoProxyCreator"
  class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
  <property name="interceptorNames">
   <list>
    <idref local="transactionInterceptor" />
   </list>
  </property>
  <property name="beanNames">
   <list>
    <value>*DAO</value>
   </list>
  </property>
 </bean>

 <bean id="projectDAO" class="com.wft.service.dao.impl.ProjectDAO">
  <constructor-arg>
   <value>com.wft.model.Project</value>
  </constructor-arg>
  <property name="sessionFactory">
   <ref bean="sessionFactory" />
  </property>
 </bean>

 <bean id="userDAO" class="com.wft.service.dao.impl.UserDAO">
  <constructor-arg>
   <value>com.wft.model.user.User</value>
  </constructor-arg>
  <property name="sessionFactory">
   <ref bean="sessionFactory" />
  </property>
 </bean>
</beans>

还有测试课:

public class TestDAO extends
  AbstractTransactionalDataSourceSpringContextTests {

 private IUserDAO userDAO;
 private IProjectDAO projectDAO;
 private SessionFactory sessionFactory;

 public void setSessionFactory(SessionFactory sessionFactory) {
  this.sessionFactory = sessionFactory;
 }

 protected String[] getConfigLocations() {
  return new String[] { "classpath*:myapp-persistence-tech.xml",
    "classpath*:datasource_mysql.xml" };
 }

 @Override
 protected boolean isDefaultRollback() {
  return false;
 }

 @Override
 protected boolean isRollback() {
  return false;
 }


 /**
  * Spring will automatically inject userDAO object on startup
  * 
  * @param userDAO
  */
 public void setUserDAO(IUserDAO userDAO) {
  this.userDAO = userDAO;
 }

 /**
  * Spring will automatically inject projectDAO object on startup
  * 
  * @param projectDAO
  */
 public void setProjectDAO(IProjectDAO projectDAO) {
  this.projectDAO = projectDAO;
 }

 public void test1() {
  System.out.println("Session Factory : "+sessionFactory);
  @SuppressWarnings("unused")
  SessionFactoryImpl sfImpl = (SessionFactoryImpl)sessionFactory;

  Administrator admin = new Administrator("admin", "admin");
  User user1 = new User("user1", "user1");
  User user2 = new User("user2", "user2");

  for (User user : userDAO.findAll()) {
   if (user instanceof Administrator) {
    System.out.println("Deleting administrator");
   } else {
    System.out.println("Deleting user");
   }
   userDAO.delete(user);
  }
  userDAO.add(user1);
  userDAO.add(admin);
  // dao.add(user2);

  System.out.println();
  assertTrue(true);
 }
}

当我在 Eclipse 中调试 jUnit 时,我可以看到所有的 EntityPersisters :

entityPersisters HashMap<K,V>  (id=75) 
 entrySet HashMap$EntrySet  (id=87) 
 keySet null 
 loadFactor 0.75 
 modCount 6 
 size 6 
 table HashMap$Entry<K,V>[16]  (id=95) 
 threshold 12 
 values HashMap$Values  (id=136) 

但是在端口 5005 上远程调试 Surefire 时,我只得到了 3 个……

它以 :

结尾
test1(com.wft.service.services.TestDAO)  Time elapsed: 2.139 sec  <<< ERROR!
org.hibernate.MappingException: Unknown entity: com.wft.model.user.Administrator
 at org.hibernate.impl.SessionFactoryImpl.getEntityPersister(SessionFactoryImpl.java:580)

可能有一件重要的事情(管理员是用户的子类):

@Entity
@Table(name = "USER")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="DTYPE", discriminatorType=DiscriminatorType.STRING, columnDefinition="VARCHAR(32) DEFAULT \"ROLE_USER\"", length=32)
@DiscriminatorValue(value="ROLE_USER")
@ForceDiscriminator
public class User extends LightEntity implements Serializable {}

@Entity
@DiscriminatorValue(value="ROLE_ADMINISTRATOR")
@ForceDiscriminator
public class Administrator extends User {}

但继承似乎不是根本原因。

有人知道这两种环境(Maven+Surefire 与 Eclipse+jUnit 启动器)之间的这种差异吗? 它看起来像是surefire(或其他地方)中的错误还是所涉及的框架之一的错误使用?

【问题讨论】:

  • 如果你把Administrator注释掉怎么办?从命令行运行时能看到User吗?

标签: java unit-testing hibernate spring maven-2


【解决方案1】:

我相信您使用的工具是可以的。您可能会收到错误,因为当您从命令行运行它和从 Eclipse 运行它时涉及不同的类路径。首先检查您的文件结构。根据您的描述,您的实体分布在不同的项目中 - 尝试运行 mvn test -X 以查看 maven 使用的确切类路径

【讨论】:

    【解决方案2】:

    我已经在某处读到,大多数时候命令行和 Eclipse 之间的差异是由类路径引起的。事实上,我没有花时间检查类路径值,但这不可能是原因,因为 Spring 配置文件在这两种情况下都加载得很好,而且由于用户加载得很好,管理员(同一个包)也应该是。

    我被这个问题困扰了好几天,偶然地,我在这里发帖几个小时后就解决了这个问题......!我不敢相信。

    这个问题是由于管理员没有公共构造函数。 我知道拥有它是 Hibernate/JPA 最佳实践之一,但通常会引发明确的错误(“没有公共 ctor”或类似的东西),我剩下的问题是:

    为什么 mvn 命令和 Eclipse 中的行为不同?

    【讨论】:

    • 我很高兴它解决了。但是,请不要将问题混在一个问题中。如果您还有其他问题,请将其作为新问题发布(但恐怕很难重现,您应该在 Eclipse 和 Maven 下进行干净构建,以确保它们使用相同版本的代码)。
    • 我剩下的问题其实还是原来的。我只是说我找到了一个修复程序,但它并没有用万能解释这种奇怪的行为,或者为什么错误的含义不合适(IMO)
    • 那么请编辑原始问题,而不是发布后续问题作为答案。
    【解决方案3】:

    不确定这是否与此处相关,但是当您看到 IDE 和 Maven 之间的差异时需要注意的是,默认情况下,Maven 将引用本地存储库 (M2_REPO) 中的依赖项,而您的 IDE 可能正在查看其他模块的 /target 。如果您有一个多模块 maven 项目,则尤其如此。

    同样,-X 将帮助您识别 Maven 正在使用的类路径。将类路径的内容和类路径的顺序与您的 IDE 启动时进行比较。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-12-31
      • 2015-08-25
      • 2019-09-30
      • 2015-03-22
      • 1970-01-01
      • 2020-07-25
      • 2018-09-02
      • 2015-01-18
      相关资源
      最近更新 更多