hibernate 通用 dao 重载 removeById

Posted

技术标签:

【中文标题】hibernate 通用 dao 重载 removeById【英文标题】:hibernate generic dao overloading removeById 【发布时间】:2016-07-23 00:56:50 【问题描述】:

我在我的 java 项目中实现休眠 ORM。 我从github 下载了源代码 我已经编译了示例中包含的 hibernate-maven-web。 现在让我们假设我想在其中一个实现中重载方法 例如 CitizenDAOImpl.java 在我进行更改之前,它看起来像这样。

package sample.googlecode.genericdao.oldworld.dao;

import org.springframework.stereotype.Repository;

import sample.googlecode.genericdao.oldworld.model.Citizen;

/**
 * <p>
 * This is the implementation of the Citizen DAO. You can see that we don't
 * actually have to implement anything, it is all inherited from GenericDAOImpl
 * through BaseDAO. We just specify the entity type (Citizen) and its identifier
 * type (Long).
 * 
 * <p>
 * The @Repository allows Spring to recognize this as a managed component (so we
 * don't need to specify it in XML) and also tells spring to do DAO exception
 * translation to the Spring exception hierarchy.
 * 
 * @author dwolverton
 * 
 */
@Repository
public class CitizenDAOImpl extends BaseDAO<Citizen, Long> implements CitizenDAO 



我所做的只是重写将调用超类的 removeById。 稍后我打算添加一些加密功能,所以 id 都会被打乱。

package sample.googlecode.genericdao.oldworld.dao;

import org.springframework.stereotype.Repository;

import sample.googlecode.genericdao.oldworld.model.Citizen;

/**
 * <p>
 * This is the implementation of the Citizen DAO. You can see that we don't
 * actually have to implement anything, it is all inherited from GenericDAOImpl
 * through BaseDAO. We just specify the entity type (Citizen) and its identifier
 * type (Long).
 * 
 * <p>
 * The @Repository allows Spring to recognize this as a managed component (so we
 * don't need to specify it in XML) and also tells spring to do DAO exception
 * translation to the Spring exception hierarchy.
 * 
 * @author dwolverton
 * 
 */
@Repository
public class CitizenDAOImpl extends BaseDAO<Citizen, Long> implements CitizenDAO 

    @Override
    public boolean removeById(java.io.Serializable id) 
        return super.removeById(id);
    

当我运行 mvn clean install 时出现错误

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.
1:compile (default-compile) on project hibernate-maven-web: Compilation failure
[ERROR] /C:/Dev/spike/hibernate-maven-web/src/main/java/sample/googlecode/generi
cdao/oldworld/dao/CitizenDAOImpl.java:[26,24] name ***: removeById(java.io.Ser
ializable) in sample.googlecode.genericdao.oldworld.dao.CitizenDAOImpl and remov
eById(ID) in com.googlecode.genericdao.dao.hibernate.GenericDAO have the same er
asure, yet neither overrides the other
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e swit
ch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please rea
d the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureExc
eption

我知道它的模糊调用以及 BaseDAO 和 CitizenDAO 在某些时候确实继承了 GenericADO。 在这种情况下有什么好的解决方案? 谢谢

【问题讨论】:

【参考方案1】:

实际上你的方法并没有覆盖超类方法,你应该使用 Long id 而不是 Serializable id 作为参数使其被覆盖。

超类是一个有界泛型类,因为它对 ID 的泛型类型有ID extends Serializable 限制。请注意,通用信息不会存储在运行时中,并且会被删除。这只是一个编译时间信息。详情请见https://docs.oracle.com/javase/tutorial/java/generics/erasure.html

这里您的自定义方法不会覆盖超类方法,而且,这两个方法都是通用的并且具有相同的擦除。所以在运行时,在擦除之后,这些方法将具有相同的签名,JVM 会混淆要调用哪一个。这就是编译器因错误而失败的原因。

【讨论】:

感谢您的评论。我有点来自 C++ 世界,所以我会假设某种虚拟继承来在运行时手动选择方法。在这种情况下,我们在 Java 中做什么? 为什么你需要Serializable在这里输入ID?根据类定义,它必须是Long。如果您需要其他类型的 ID,请考虑创建 extends BaseDAO&lt;Citizen, Serializable&gt; 的新类。如果您需要在当前类中接受Serializable ID 的方法,您可以选择另一个方法名称(在这种情况下不要忘记删除@Override 注释)。但是以这种方式,我怀疑该方法的必要性,因为它非常脆弱。如果您传递与 Long 不同的内容,您将不得不手动转换类型,并且将在运行时捕获 ClassCastException 我改成 Long 了,问题依旧。 完全相同的错误?不敢相信,这很奇怪..你能附上更新的代码和错误信息吗?

以上是关于hibernate 通用 dao 重载 removeById的主要内容,如果未能解决你的问题,请参考以下文章

为 Hibernate 创建一个通用的 DAO 类

Spring 3,带有通用 DAO 的 Hibernate 4 AutoWired sessionFactory

在通用 DAO 中使用 Hibernate 调用存储过程的最佳方法是啥?

通用Hibernate-Dao

Hibernate Dao映射配置通用接口类反射获取加载calass实例

通用 DAO hibernate 4 + spring 4 和异常处理