gpt4 book ai didi

java - 为什么 Hibernate 在调用 session.save(object) 时会抛出 ClassCastException?

转载 作者:行者123 更新时间:2023-12-02 00:26:01 25 4
gpt4 key购买 nike

当我执行以下 Hibernate 调用时,我收到 ClassCastException(请参阅 Stacktrace),但我无法理解原因。 Hibernate 在这里想做什么?它是否试图将我的一个对象转换为不同的类类型?如果是,为什么以及到什么类(class)?

session.save(fooAccount);

堆栈跟踪:

com.foo.web.model.exception.FailedDatabaseOperationException: java.lang.ClassCastException: com.foo.web.model.authentication.SecurePassword
at com.foo.web.controller.db.HibernateController.savefooAccount(HibernateController.java:883)
at com.foo.web.model.account.fooAccount.save(fooAccount.java:459)
at com.foo.web.controller.AccountController.createfooAccount(AccountController.java:258)
at com.foo.web.view.start.RegisterController.register(RegisterController.java:233)
at com.foo.web.view.start.RegisterController.onClick$btn_register(RegisterController.java:196)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.zkoss.zk.ui.event.GenericEventListener.onEvent(GenericEventListener.java:81)
at org.zkoss.zk.ui.impl.EventProcessor.process0(EventProcessor.java:192)
at org.zkoss.zk.ui.impl.EventProcessor.process(EventProcessor.java:138)
at org.zkoss.zk.ui.impl.EventProcessingThreadImpl.process0(EventProcessingThreadImpl.java:517)
at org.zkoss.zk.ui.impl.EventProcessingThreadImpl.sendEvent(EventProcessingThreadImpl.java:121)
at org.zkoss.zk.ui.event.Events.sendEvent(Events.java:319)
at org.zkoss.zk.ui.event.Events.sendEvent(Events.java:329)
at org.zkoss.zk.ui.AbstractComponent$ForwardListener.onEvent(AbstractComponent.java:3034)
at org.zkoss.zk.ui.impl.EventProcessor.process0(EventProcessor.java:192)
at org.zkoss.zk.ui.impl.EventProcessor.process(EventProcessor.java:138)
at org.zkoss.zk.ui.impl.EventProcessingThreadImpl.process0(EventProcessingThreadImpl.java:517)
at org.zkoss.zk.ui.impl.EventProcessingThreadImpl.run(EventProcessingThreadImpl.java:444)
Caused by: java.lang.ClassCastException: com.foo.web.model.authentication.SecurePassword
at org.hibernate.type.ComponentType.toLoggableString(ComponentType.java:410)
at org.hibernate.type.ComponentType.toLoggableString(ComponentType.java:414)
at org.hibernate.pretty.Printer.toString(Printer.java:76)
at org.hibernate.pretty.Printer.toString(Printer.java:113)
at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:120)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:383)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:133)
at com.foo.web.controller.db.HibernateController.savefooAccount(HibernateController.java:879)
<小时/>

编辑:以下是映射以及存储对象的代码:

映射文件(缩短版本。省略不相关的内容):

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- Generated 26.04.2011 14:49:15 by Hibernate Tools 3.3.0.GA -->
<hibernate-mapping>
<class name="com.foo.web.model.account.fooAccount" table="fooACCOUNT">

<id name="id" type="long" access="field">
<column name="foo_ACCOUNT_ID" />
<generator class="native" />
</id>

<many-to-one name="defaultMailAccount" lazy="false" column="DEFAULT_MAIL_ACCOUNT_ID" />

<bag name="mailAccounts" table="MAILACCOUNTS" lazy="false" inverse="true">
<key column="foo_ACCOUNT_ID"></key>
<one-to-many class="com.foo.web.model.mail.account.MailAccount" />
</bag>

<component name="user" class="com.foo.web.model.account.fooUser">
<component name="activationCode">
<property name="activationCode" column="ACTIVATION_CODE"></property>
</component>

<component name="password" class="com.foo.web.model.authentication.MediumSecurePassword">
<property name="hash" column="PASSWORD" />
</component>

<component name="resetCode">
<property name="resetCode" column="RESET_CODE" />
</component>
<one-to-one name="fooAccount" class="com.foo.web.model.account.fooAccount"></one-to-one>
<component name="username">
<property name="username" column="USERNAME" unique="true" />
</component>

<property name="userStatus">
<column name="USERSTATUS" />
<type name="org.hibernate.type.EnumType">
<param name="type">12</param>
<param name="enumClass">com.foo.web.model.account.UserStatus</param>
</type>
</property>
<property name="userType">
<column name="USERTYPE" />
<type name="org.hibernate.type.EnumType">
<param name="type">12</param>
<param name="enumClass">com.foo.web.model.account.UserType</param>
</type>
</property>
</component>

</class>
</hibernate-mapping>

SecurePassword.java(缩短)

/**
* Represents a password.
*/
public class SecurePassword extends Password {

/**
* Default constructor
*/
public SecurePassword() {
super();
}

/**
* Constructor method. Will throw IllegalPasswordException if password is
* not safe.
*/
public SecurePassword(String password) throws IllegalPasswordException {
setPassword(password);
}

/**
* Checks if the given character is a number
*
* @param c
* The character to check
* @return Returns true if the given character is a number
*/
public boolean isNumber(char c) {
// ...
}

/**
* Checks is a given password is valid.
*/
public boolean passwordValid(Password password)
throws IllegalPasswordException {
return passwordValid(password.toString());
}

/**
* Checks is a given password is valid.
*/
public boolean passwordValid(String password)
throws IllegalPasswordException {

// ...
}

/**
* Sets a new password.
*/
@Override
public void setPassword(String password) throws IllegalPasswordException {

if (passwordValid(password)) {
this.password = password;
}
}

}

Password.java(缩写)

/**
* Represents a simple password without much restriction
*/
public class Password {
Crypter crypter = new Crypter();
String hash = null;
String password = null;

public Password() {
super();
}

public Password(String password) throws IllegalPasswordException {
setPassword(password);
}

@Override
public boolean equals(Object password) {

if (this == password) {
return true;
}

if (password instanceof Password) {
Password p = (Password) password;
return getHash().equals(p.getHash());
}

if (password instanceof String) {
String password_str = getPassword();
if (password_str != null) {
return password_str.equals(password);
}
}

return false;
}

/**
* Returns the hashed version of this password
*
* @return The hashed version of this password
*/
public String getHash() {
if (hash == null) {
try {
hash = crypter.hash(getPassword());
} catch (FailedCryptOperationException e) {
handleException(e, false, null, null);
}
}
return hash;
}

public String getPassword() {
return password;
}

/*
* Handles the given exception
*/
private void handleException(Exception e, boolean notifyUser,
String customTitle, String customErrorMessage) {

SystemController.handleException(e, notifyUser, customTitle,
customErrorMessage);
}

public void setHash(String hash) {
this.hash = hash;
}

@SuppressWarnings("unused")
public void setPassword(String password) throws IllegalPasswordException {
hash = null;
this.password = password;
}

@Override
public String toString() {

return getPassword();
}
}

MediumSecurePassword.java

public class MediumSecurePassword extends SecurePassword {

public final int MAX_LENGTH = 64;
public final int MIN_LENGTH = 6;
StringUtil stringUtil = new StringUtil();


public MediumSecurePassword() {
super();
}

/**
* Constructor method. Will throw IllegalPasswordException if password is
* not safe. Medium Safe passwords are at least 6 characters long.
*/
public MediumSecurePassword(String password) throws IllegalPasswordException {
setPassword(password);
}

/**
* Checks if the given character is a number
*/
public boolean isNumber(char c) {
// ...
}

/**
* Checks is a given password is valid. Valid means that it's secure (at
* least 8 characters, at least 1 number, at least 1 special character).
*/
public boolean passwordValid(Password password)
throws IllegalPasswordException {
return passwordValid(password.toString());
}

/**
* Checks is a given password is valid. Valid means that it's "medium secure" (min.
* length of 6).
*/
public boolean passwordValid(String password)
throws IllegalPasswordException {

// ...
}

/**
* Sets a new password. Will throw IllegalPasswordException if password is
* not safe. Safe passwords are at least 8 characters long, consist of
* numbers, letters and special characters.
*/
@Override
public void setPassword(String password) throws IllegalPasswordException {

if (passwordValid(password)) {
this.password = password;
}
}
}
<小时/>

注意:如果我从映射文件中删除这 3 行,一切都会顺利运行:

<component name="password" class="com.foo.web.model.authentication.MediumSecurePassword">
<property name="hash" column="PASSWORD" />
</component>

那么,对我来说,通过 passwordInstance.getHash() 获取密码的哈希值似乎存在问题?但不确定。

最佳答案

在映射中使用密码子类的子类背后的想法是什么?

        <component name="password" class="com.foo.web.model.authentication.MediumSecurePassword">
<property name="hash" column="PASSWORD" />
</component>

这里发生的情况是,您需要在持久上序列化特定实现。在您的情况下,您的对象实现了父类 (SecurePassword),因此它不能转换为 MediumSecurePassword。

我建议在映射中使用父类,这样您就可以在实现中使用 SecurePassword 和 MediumSecurePassword:

        <component name="password" class="com.foo.web.model.authentication.Password">
<property name="hash" column="PASSWORD" />
</component>

关于java - 为什么 Hibernate 在调用 session.save(object) 时会抛出 ClassCastException?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10043771/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com