如果我在 Spring 中 运行 我的 Hibernate 请求,为什么会得到 ClassCastException?
Why do I get a ClassCastException if I run my Hibernate Request in Spring?
虽然 运行 spring-应用程序出现以下异常:
java.lang.ClassCastException: project.db.dbmodels.Permission cannot be cast to project.db.dbmodels.Permission
at project.db.DataOperator.setUpDefaultPermission(DataOperator.java:573)
at project.web.WebController.start(WebController.java:18)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:879)
...
我无法重新创建此异常,而 运行 单元测试。
这些是我的 class:
权限:
package project.db.dbmodels;
import java.util.*;
import javax.persistence.*;
@Entity
@Table(name = "permission")
public class Permission {
@Id
@GeneratedValue
@Column(name = "id")
private int id;
@Column(name = "name")
private String name;
@OneToMany(mappedBy = "permission", cascade = CascadeType.ALL)
private Set<Permission_PermissionRole> permissionPermissionRole = new HashSet<Permission_PermissionRole>();
public Permission() {
}
public Permission(int id, String name, Set<Permission_PermissionRole> permissionPermissionRole) {
this.id = id;
this.name = name;
this.permissionPermissionRole = permissionPermissionRole;
}
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public Set<Permission_PermissionRole> getPermissionPermissionRole() {
return this.permissionPermissionRole;
}
public void setPermissionPermissionRole(Set<Permission_PermissionRole> permissionPermissionRole) {
this.permissionPermissionRole = permissionPermissionRole;
}
public void addPermissionPermissionRole(Permission_PermissionRole permissionPermissionRole) {
this.permissionPermissionRole.add(permissionPermissionRole);
}
public Permission id(int id) {
this.id = id;
return this;
}
public Permission name(String name) {
this.name = name;
return this;
}
public Permission permissionPermissionRole(Set<Permission_PermissionRole> permissionPermissionRole) {
this.permissionPermissionRole = permissionPermissionRole;
return this;
}
@Override
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof Permission)) {
return false;
}
Permission permission = (Permission) o;
return id == permission.id && Objects.equals(name, permission.name)
&& Objects.equals(permissionPermissionRole, permission.permissionPermissionRole);
}
@Override
public int hashCode() {
return Objects.hash(id, name);
}
@Override
public String toString() {
return "{" + " id='" + getId() + "'" + ", name='" + getName() + "'" + "}";
}
}
数据操作员:
package project.db;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.persistence.PersistenceException;
import javax.persistence.RollbackException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.query.Query;
import project.db.dbmodels.*;
import org.apache.log4j.Logger;
public class DataOperator {
final static Logger log = Logger.getLogger(DataOperator.class);
private static boolean setUpDefaultPermission(boolean change) {
SessionFactory sf = HibernateUtil.getSessionFactory();
if (sf == null) {
return false;
}
Session session = sf.openSession();
session.beginTransaction();
boolean arePermissionsReady = true;
// Setup permission "AcessAdminarea"
String request = "FROM Permission WHERE name = 'Acess Adminarea'";
Query<Permission> query = session.createQuery(request, Permission.class);
query.setMaxResults(1);
Permission permAdminArea = null;
try {
permAdminArea = query.uniqueResult();//The Exception occures here
} catch (PersistenceException e) {
return false;
}
if (permAdminArea == null) {
arePermissionsReady = false;
if (change) {
permAdminArea = new Permission();
permAdminArea.setName("Acess Adminarea");
session.save(permAdminArea);
}
}
// Setup permissionrole "Admin"
request = "FROM PermissionRole WHERE name = 'Admin'";
Query<PermissionRole> query2 = session.createQuery(request, PermissionRole.class);
PermissionRole roleAdmin = null;
try {
roleAdmin = query2.uniqueResult();
} catch (PersistenceException e) {
return false;
}
if (roleAdmin == null) {
arePermissionsReady = false;
if (change) {
roleAdmin = new PermissionRole();
roleAdmin.setName("Admin");
session.save(roleAdmin);
Permission_PermissionRole permPermrole = new Permission_PermissionRole();
permPermrole.setPermission(permAdminArea);
permPermrole.setRole(roleAdmin);
session.save(permPermrole);
}
}
// Setup permissionrole "Employee"
request = "FROM PermissionRole WHERE name = 'Employee'";
query2 = session.createQuery(request, PermissionRole.class);
PermissionRole roleEmployee = null;
try {
roleEmployee = query2.uniqueResult();
} catch (PersistenceException e) {
return false;
}
if (roleEmployee == null) {
arePermissionsReady = false;
if (change) {
roleEmployee = new PermissionRole();
roleEmployee.setName("Employee");
session.save(roleEmployee);
}
}
if (change && !arePermissionsReady) {
try {
session.getTransaction().commit();
arePermissionsReady = true;
} catch (IllegalStateException e) {
log.error(String.format("Unable to commit the transaction : %s", e.getMessage()));
} catch (RollbackException e) {
log.error(String.format("Unable to commit the transaction : %s", e.getMessage()));
}
session.close();
}
return arePermissionsReady;
}
}
在查找错误时,我试图获取更多调试内容,因此我替换了发生异常的行,并将以下代码插入到 DataOperator 中:
Object result = query.uniqueResult();
String resultType = result.getClass().toString();
boolean test = result instanceof Permission;
boolean test2 = Permission.class.toString().equals(resultType);
我在这个段之后设置了一个停止点,当调试时 运行 它与 Spring 我得到:
result: Permission@47 "{ id='15', name='Acess AdminArea'}"
resultType: "class project.db.dbmodels.Permission"
test: false
test2: true
虽然 运行 我得到了一个单元测试:
result: Permission@47 "{ id='15', name='Acess AdminArea'}"
resultType: "class project.db.dbmodels.Permission"
test: true
test2: true
编辑:他们有不同的 class 加载器。 sun.misc.Launcher$AppCLassLoader 和 org.springframework.boot.devtools.restart.classloader.RestartClassLoader.
我该怎么办?
当有问题的 class 从两个(或更多)class 加载器加载时,会发生这种情况。 java 中的 class 只有在与它的 class 加载程序结合时才是唯一的。可能您的权限 class 是从一个 class 加载程序加载的,然后被转换为相同的 class 但从不同的 class 加载程序加载。
将 class 加载程序添加到您的调试日志中,您可能会看到问题,并希望 class 正在加载哪些 class 加载程序。
正如 Ed Schaller 在另一个回复中提到的,问题来自于 classes 是从两个不同的实体加载的。
不过,我没有更改 class 路径,而是找到了一种解决此问题的方法,方法是使用 BootstrapServiceRegistry
并添加应用程序和休眠的 class 加载器。
public class HibernateUtil {
private static SessionFactory sessionFactory;
static {
final StandardServiceRegistry registry = new StandardServiceRegistryBuilder(
createHibernateBootstrapServiceRegistry()).configure().build();
try {
sessionFactory = new MetadataSources(registry).buildMetadata().buildSessionFactory();
} catch (Exception e) {
StandardServiceRegistryBuilder.destroy(registry);
}
}
private static BootstrapServiceRegistry createHibernateBootstrapServiceRegistry() {
ClassLoader tccl = Thread.currentThread().getContextClassLoader();
ClassLoader hibernateCl = BootstrapServiceRegistry.class.getClassLoader();
return new BootstrapServiceRegistryBuilder().applyClassLoader(tccl).applyClassLoader(hibernateCl).build();
}
public static Session openSession() {
return sessionFactory.openSession();
}
}
虽然 运行 spring-应用程序出现以下异常:
java.lang.ClassCastException: project.db.dbmodels.Permission cannot be cast to project.db.dbmodels.Permission
at project.db.DataOperator.setUpDefaultPermission(DataOperator.java:573)
at project.web.WebController.start(WebController.java:18)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:879)
...
我无法重新创建此异常,而 运行 单元测试。
这些是我的 class: 权限:
package project.db.dbmodels;
import java.util.*;
import javax.persistence.*;
@Entity
@Table(name = "permission")
public class Permission {
@Id
@GeneratedValue
@Column(name = "id")
private int id;
@Column(name = "name")
private String name;
@OneToMany(mappedBy = "permission", cascade = CascadeType.ALL)
private Set<Permission_PermissionRole> permissionPermissionRole = new HashSet<Permission_PermissionRole>();
public Permission() {
}
public Permission(int id, String name, Set<Permission_PermissionRole> permissionPermissionRole) {
this.id = id;
this.name = name;
this.permissionPermissionRole = permissionPermissionRole;
}
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public Set<Permission_PermissionRole> getPermissionPermissionRole() {
return this.permissionPermissionRole;
}
public void setPermissionPermissionRole(Set<Permission_PermissionRole> permissionPermissionRole) {
this.permissionPermissionRole = permissionPermissionRole;
}
public void addPermissionPermissionRole(Permission_PermissionRole permissionPermissionRole) {
this.permissionPermissionRole.add(permissionPermissionRole);
}
public Permission id(int id) {
this.id = id;
return this;
}
public Permission name(String name) {
this.name = name;
return this;
}
public Permission permissionPermissionRole(Set<Permission_PermissionRole> permissionPermissionRole) {
this.permissionPermissionRole = permissionPermissionRole;
return this;
}
@Override
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof Permission)) {
return false;
}
Permission permission = (Permission) o;
return id == permission.id && Objects.equals(name, permission.name)
&& Objects.equals(permissionPermissionRole, permission.permissionPermissionRole);
}
@Override
public int hashCode() {
return Objects.hash(id, name);
}
@Override
public String toString() {
return "{" + " id='" + getId() + "'" + ", name='" + getName() + "'" + "}";
}
}
数据操作员:
package project.db;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.persistence.PersistenceException;
import javax.persistence.RollbackException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.query.Query;
import project.db.dbmodels.*;
import org.apache.log4j.Logger;
public class DataOperator {
final static Logger log = Logger.getLogger(DataOperator.class);
private static boolean setUpDefaultPermission(boolean change) {
SessionFactory sf = HibernateUtil.getSessionFactory();
if (sf == null) {
return false;
}
Session session = sf.openSession();
session.beginTransaction();
boolean arePermissionsReady = true;
// Setup permission "AcessAdminarea"
String request = "FROM Permission WHERE name = 'Acess Adminarea'";
Query<Permission> query = session.createQuery(request, Permission.class);
query.setMaxResults(1);
Permission permAdminArea = null;
try {
permAdminArea = query.uniqueResult();//The Exception occures here
} catch (PersistenceException e) {
return false;
}
if (permAdminArea == null) {
arePermissionsReady = false;
if (change) {
permAdminArea = new Permission();
permAdminArea.setName("Acess Adminarea");
session.save(permAdminArea);
}
}
// Setup permissionrole "Admin"
request = "FROM PermissionRole WHERE name = 'Admin'";
Query<PermissionRole> query2 = session.createQuery(request, PermissionRole.class);
PermissionRole roleAdmin = null;
try {
roleAdmin = query2.uniqueResult();
} catch (PersistenceException e) {
return false;
}
if (roleAdmin == null) {
arePermissionsReady = false;
if (change) {
roleAdmin = new PermissionRole();
roleAdmin.setName("Admin");
session.save(roleAdmin);
Permission_PermissionRole permPermrole = new Permission_PermissionRole();
permPermrole.setPermission(permAdminArea);
permPermrole.setRole(roleAdmin);
session.save(permPermrole);
}
}
// Setup permissionrole "Employee"
request = "FROM PermissionRole WHERE name = 'Employee'";
query2 = session.createQuery(request, PermissionRole.class);
PermissionRole roleEmployee = null;
try {
roleEmployee = query2.uniqueResult();
} catch (PersistenceException e) {
return false;
}
if (roleEmployee == null) {
arePermissionsReady = false;
if (change) {
roleEmployee = new PermissionRole();
roleEmployee.setName("Employee");
session.save(roleEmployee);
}
}
if (change && !arePermissionsReady) {
try {
session.getTransaction().commit();
arePermissionsReady = true;
} catch (IllegalStateException e) {
log.error(String.format("Unable to commit the transaction : %s", e.getMessage()));
} catch (RollbackException e) {
log.error(String.format("Unable to commit the transaction : %s", e.getMessage()));
}
session.close();
}
return arePermissionsReady;
}
}
在查找错误时,我试图获取更多调试内容,因此我替换了发生异常的行,并将以下代码插入到 DataOperator 中:
Object result = query.uniqueResult();
String resultType = result.getClass().toString();
boolean test = result instanceof Permission;
boolean test2 = Permission.class.toString().equals(resultType);
我在这个段之后设置了一个停止点,当调试时 运行 它与 Spring 我得到:
result: Permission@47 "{ id='15', name='Acess AdminArea'}"
resultType: "class project.db.dbmodels.Permission"
test: false
test2: true
虽然 运行 我得到了一个单元测试:
result: Permission@47 "{ id='15', name='Acess AdminArea'}"
resultType: "class project.db.dbmodels.Permission"
test: true
test2: true
编辑:他们有不同的 class 加载器。 sun.misc.Launcher$AppCLassLoader 和 org.springframework.boot.devtools.restart.classloader.RestartClassLoader.
我该怎么办?
当有问题的 class 从两个(或更多)class 加载器加载时,会发生这种情况。 java 中的 class 只有在与它的 class 加载程序结合时才是唯一的。可能您的权限 class 是从一个 class 加载程序加载的,然后被转换为相同的 class 但从不同的 class 加载程序加载。
将 class 加载程序添加到您的调试日志中,您可能会看到问题,并希望 class 正在加载哪些 class 加载程序。
正如 Ed Schaller 在另一个回复中提到的,问题来自于 classes 是从两个不同的实体加载的。
不过,我没有更改 class 路径,而是找到了一种解决此问题的方法,方法是使用 BootstrapServiceRegistry
并添加应用程序和休眠的 class 加载器。
public class HibernateUtil {
private static SessionFactory sessionFactory;
static {
final StandardServiceRegistry registry = new StandardServiceRegistryBuilder(
createHibernateBootstrapServiceRegistry()).configure().build();
try {
sessionFactory = new MetadataSources(registry).buildMetadata().buildSessionFactory();
} catch (Exception e) {
StandardServiceRegistryBuilder.destroy(registry);
}
}
private static BootstrapServiceRegistry createHibernateBootstrapServiceRegistry() {
ClassLoader tccl = Thread.currentThread().getContextClassLoader();
ClassLoader hibernateCl = BootstrapServiceRegistry.class.getClassLoader();
return new BootstrapServiceRegistryBuilder().applyClassLoader(tccl).applyClassLoader(hibernateCl).build();
}
public static Session openSession() {
return sessionFactory.openSession();
}
}