gpt4 book ai didi

java - 首次保存后出现 TransientObjectException 错误

转载 作者:搜寻专家 更新时间:2023-11-01 03:17:25 24 4
gpt4 key购买 nike

每当我进行连续保存时,我都会收到 TransientObjectException;我在第一次保存或刷新屏幕/页面时没有收到此错误。这让我很困惑,因为一旦对象被成功保存,它就不应该是暂时的,因为它在我的数据库中有一个表示。

我下面的文件(用户和 UserPasswordInfo)具有一对多关系,其中一个用户可以拥有多个 UserPasswordInfo(或 UPI),并且它们由我的用户的主键链接:user_id.

我很确定问题存在于以下文件中,而不是其他地方,因为 TOE 错误仅在添加此文件后出现,据我所知,该软件在其生命周期(几年)中从未出现过此问题.

这是我的 hibernate 文件:

用户.hbm.xml

<hibernate-mapping>
<class name="com.app.common.domain.User" table="users" >
<id name="id" type="java.lang.Integer">
<column name="user_id" />
<generator class="identity" />
</id>

<set name="passwordInfos" table="user_password_info" lazy="false" cascade="all" fetch="select">
<key>
<column name="user_id"></column>
</key>
<one-to-many class="com.app.common.domain.UserPasswordInfo" />
</set>

</class>
</hibernate-mapping>

UserPasswordInfo.hbm.xml

<hibernate-mapping>
<class name="com.app.common.domain.UserPasswordInfo" table="user_password_info">
<id name="passwordInfoId" type="java.lang.Integer">
<column name="password_info_id" />
<generator class="identity" />
</id>

<property name="password" column="password" type="java.lang.String"/>
<property name="passwordTS" column="password_ts" type="java.sql.Timestamp"/>
<property name="pwdChange" column="initial_password_change" type="java.lang.Boolean"/>
<property name="userId" column="user_id" type="java.lang.Integer"/>

</class>
</hibernate-mapping>

这是他们的 Java 文件:

用户.java

import java.sql.Timestamp;
import java.util.Collections;
import java.util.Comparator;

import java.util.HashSet;
import java.util.Set;

public class User extends DBObject {//DBObject has a getter and setter for the id

private Set<UserPasswordInfo> passwordInfos = new HashSet<UserPasswordInfo>(0);

public User() {
super();
}

.
.
.

public Set<UserPasswordInfo> getPasswordInfos() {
return passwordInfos;
}

public void setPasswordInfos(Set<UserPasswordInfo> passwordInfos) {
this.passwordInfos = passwordInfos;
}

public void addUPI(String pwd, Timestamp pwdTS, Boolean pwdChng){
UserPasswordInfo upi = new UserPasswordInfo();
upi.setPassword(pwd);
upi.setPasswordTS(pwdTS);
upi.setPwdChange(pwdChng);
if(getId() != null)
upi.setUserId(getId().intValue());
passwordInfos.add(upi);
}

public String getLatestPassword(){
return getSortedList().get(0).getPassword();
}

public UserPasswordInfo getLatestUPI(){
ArrayList<UserPasswordInfo> list = getSortedList();
return (list == null || list.size() == 0) ? null : list.get(0);
}

public ArrayList<String> getLastThreePasswords(){

final ArrayList<UserPasswordInfo> upiList = getSortedList();

if(upiList == null)
return null;

ArrayList<String> list = new ArrayList<String>();
int i = 0;
while(i < 3 && i < list.size()){
list.add(upiList.get(i++).getPassword());
}
return list;
}

public ArrayList<UserPasswordInfo> getSortedList(){

ArrayList<UserPasswordInfo> upi = new ArrayList<UserPasswordInfo>(getPasswordInfos());
if(upi == null || upi.size() == 0){
return null;
}

Collections.sort(upi, new Comparator<UserPasswordInfo>() {
public int compare(UserPasswordInfo o1, UserPasswordInfo o2) {
if (o1.getPasswordTS() == null || o2.getPasswordTS() == null)
return 0;
return o2.getPasswordTS().compareTo(o1.getPasswordTS());
}
});
return upi;
}
}

UserPasswordInfo.java

import java.sql.Timestamp;

public class UserPasswordInfo extends DBObject{

private int passwordInfoId;
private String password;
private Timestamp passwordTS;
private Boolean pwdChange;
private int userId;

public UserPasswordInfo(){}

public UserPasswordInfo(String pwd, Timestamp pwdTS, Boolean pwdChng){
password = pwd;
passwordTS = pwdTS;
pwdChange = pwdChng;
}

public UserPasswordInfo(int userId, String pwd, Timestamp pwdTS, Boolean pwdChng){
this.userId = userId;
password = pwd;
passwordTS = pwdTS;
pwdChange = pwdChng;
}

public int getPasswordInfoId(){
return passwordInfoId;
}
public void setPasswordInfoId(int pid){
passwordInfoId = pid;
}
public String getPassword(){
return password;
}
public void setPassword(String pwd){
password = pwd;
}
public Timestamp getPasswordTS(){
return passwordTS;
}
public void setPasswordTS(Timestamp ts){
passwordTS = ts;
}
public void setPwdChange(Boolean pwdChange) {
this.pwdChange = pwdChange;
}
public Boolean getPwdChange() {
return pwdChange;
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
}

这是错误信息:

ERROR BeanPopulator - 
propertyName=passwordInfos
readerMethod=public java.util.Set com.app.domain.User.getPasswordInfos()
setterMethod=public void com.app.common.domain.User.setPasswordInfos(java.util.Set)
fromBean=[User someUser, id: 268, role: front desk]
toBean=[User , id: null]

net.sf.gilead.exception.TransientObjectException
at net.sf.gilead.core.hibernate.HibernateUtil.getId(HibernateUtil.java:316)
at net.sf.gilead.core.hibernate.HibernateUtil.getId(HibernateUtil.java:224)
at net.sf.gilead.core.hibernate.HibernateUtil.loadPersistentCollection(HibernateUtil.java:854)
at net.sf.gilead.core.hibernate.HibernateUtil.createPersistentCollection(HibernateUtil.java:843)
at net.sf.gilead.core.beanlib.merge.MergeCollectionReplicator.replicateCollection(MergeCollectionReplicator.java:119)
at net.sf.beanlib.provider.replicator.ReplicatorTemplate.replicate(ReplicatorTemplate.java:112)
at net.sf.beanlib.provider.BeanTransformer.transform(BeanTransformer.java:231)
at net.sf.beanlib.provider.BeanPopulator.doit(BeanPopulator.java:201)
at net.sf.beanlib.provider.BeanPopulator.processSetterMethod(BeanPopulator.java:172)
at net.sf.beanlib.provider.BeanPopulator.populate(BeanPopulator.java:269)
at net.sf.gilead.core.LazyKiller.populate(LazyKiller.java:288)
at net.sf.gilead.core.LazyKiller.attach(LazyKiller.java:237)
at net.sf.gilead.core.PersistentBeanManager.mergePojo(PersistentBeanManager.java:554)
at net.sf.gilead.core.PersistentBeanManager.merge(PersistentBeanManager.java:318)
at net.sf.gilead.core.PersistentBeanManager.mergeCollection(PersistentBeanManager.java:581)
at net.sf.gilead.core.PersistentBeanManager.merge(PersistentBeanManager.java:290)
at net.sf.gilead.gwt.GileadRPCHelper.parseInputParameters(GileadRPCHelper.java:94)
at net.sf.gilead.gwt.GileadRPCHelper.parseInputParameters(GileadRPCHelper.java:137)
at net.sf.gilead.gwt.PersistentRemoteService.processCall(PersistentRemoteService.java:172)

编辑 以下是一些可能与此错误相关的链接和代码部分:

这是我保存对象时调用的方法(上面的错误是在调用这个方法之前抛出的)

@SuppressWarnings({ "rawtypes" })
private List saveObjectList(List<? extends DBObject> values) {
Session session = sessionFactory.getCurrentSession();
Transaction tx = null;

try {
tx = session.beginTransaction();
for (DBObject value : values) {
if (value.getIsDirty()) {
Integer clientId = value.getClientId();
if (value.getId() != null) {//enters here
value = (DBObject) session.merge(value);
session.persist(value);
}
else {
session.save(value);
}
value.setClientId(clientId);
value.setIsDirty(false);
}
}
tx.commit();//fails here

return values;
}
catch (Exception ex) {
String msg = "Failed to save values. ";
if (values == null) {
msg += " Values to save were null.";
}
else {
msg += " Values to save had length: " + values.size();
}
rollbackOrCloseSession(tx, session, "saveObjectList() - " + msg, ex);
return null;
}
}

GileadRPCHelper

/**
* Parse RPC input parameters.
* Must be called before GWT service invocation.
* @param rpcRequest the input GWT RPC request
* @param beanManager the Hibernate bean manager
* @param session the HTTP session (for HTTP Pojo store)
*/
public static void parseInputParameters(Object[] parameters,
PersistentBeanManager beanManager,
HttpSession session)
{
// Init classloader for proxy mode
//
if (beanManager.getClassMapper() instanceof ProxyClassMapper)
{
initClassLoader();
}

// Set HTTP session of Pojo store in thread local
//
HttpSessionProxyStore.setHttpSession(session);

// Merge parameters if needed
//
if (parameters != null)
{
long start = System.currentTimeMillis();
for (int index = 0 ; index < parameters.length; index ++)
{
if (parameters[index] != null)
{
try
{
//***ERROR occurs when this is called
parameters[index] = beanManager.merge(parameters[index], true);
}
catch (NotAssignableException ex)
{
log.debug(parameters[index] + " not assignable");
}
catch (TransientObjectException ex)
{
log.info(parameters[index] + " is transient : cannot merge...");
}
}
}

if (log.isDebugEnabled())
{
log.debug("Merge took " + (System.currentTimeMillis() - start) + " ms.");
}
}
}

PersistentBeanManager

/**
* Merge the clone POJO to its Hibernate counterpart
*/
public Object merge(Object object) {
// Explicit merge
return merge(object, false);
}

/**
* Merge the clone POJO to its Hibernate counterpart
*/
@SuppressWarnings("unchecked")
public Object merge(Object object, boolean assignable) {
// Precondition checking
//
if (object == null) {
return null;
}

if (_persistenceUtil == null) {
throw new RuntimeException("No Persistence Util set !");
}

// Collection handling
//
if (object instanceof Collection) {
return mergeCollection((Collection) object, assignable);
} else if (object instanceof Map) {
return mergeMap((Map) object, assignable);
} else if (object.getClass().isArray()) {
// Check primitive type
//
if (object.getClass().getComponentType().isPrimitive()) {
return object;
}

// Merge as a collection
//
Object[] array = (Object[]) object;
Collection result = mergeCollection(Arrays.asList(array), assignable);

// Get the result as an array (much more tricky !!!)
//
Class<?> componentType = object.getClass().getComponentType();
Object[] copy = (Object[]) java.lang.reflect.Array.newInstance(componentType, array.length);
return result.toArray(copy);
} else {
return mergePojo(object, assignable);
}
}

/**
* Retrieve the Hibernate Pojo and merge the modification from GWT
*
* @param clonePojo the clone pojo
* @param assignable does the source and target class must be assignable
* @return the merged Hibernate POJO
* @exception UnsupportedOperationException if the clone POJO does not implements ILightEntity and the POJO store is
* stateless
* @exception NotAssignableException if source and target class are not assignable
*/
protected Object mergePojo(Object clonePojo, boolean assignable) {

// Get Hibernate associated class
Class<?> cloneClass = clonePojo.getClass();
Class<?> hibernateClass = null;
if (_classMapper != null) {
hibernateClass = _classMapper.getSourceClass(cloneClass);
}
if (hibernateClass == null) {
// Not a clone : take the inner class
hibernateClass = clonePojo.getClass();
}

// Precondition checking : is the pojo managed by Hibernate
if (_persistenceUtil.isPersistentClass(hibernateClass) == true) {
// Assignation checking
if ((assignable == true) && (hibernateClass.isAssignableFrom(cloneClass) == false)) {
throw new NotAssignableException(hibernateClass, cloneClass);
}
}

// Retrieve the pojo
try {
Serializable id = null;
try {
id = _persistenceUtil.getId(clonePojo, hibernateClass);
if (id == null) {
_log.info("HibernatePOJO not found : can be transient or deleted data : " + clonePojo);
}
} catch (TransientObjectException ex) {
_log.info("Transient object : " + clonePojo);
} catch (NotPersistentObjectException ex) {
if (holdPersistentObject(clonePojo) == false) {
// Do not merge not persistent instance, since they do not
// necessary
// implement the Java bean specification
//
if (_log.isDebugEnabled()) {
_log.debug("Not persistent object, merge is not needed : " + clonePojo);
}
return clonePojo;
} else {
if (_log.isDebugEnabled()) {
_log.debug("Merging wrapper object : " + clonePojo);
}
}
}

if (ClassUtils.immutable(hibernateClass)) {
// Do not clone immutable types
//
return clonePojo;
}

// Create a new POJO instance
//
Object hibernatePojo = null;
try {
if (AnnotationsManager.hasGileadAnnotations(hibernateClass)) {
if (id != null) {
// ServerOnly or ReadOnly annotation : load from DB
// needed
//
hibernatePojo = _persistenceUtil.load(id, hibernateClass);
} else {
// Transient instance
//
hibernatePojo = clonePojo;
}
} else {
Constructor<?> constructor = hibernateClass.getDeclaredConstructor(new Class<?>[] {});
constructor.setAccessible(true);
hibernatePojo = constructor.newInstance();
}
} catch (Exception e) {
throw new RuntimeException("Cannot create a fresh new instance of the class " + hibernateClass, e);
}

// Merge the modification in the Hibernate Pojo
//
_lazyKiller.attach(hibernatePojo, clonePojo);
return hibernatePojo;
} finally {
_persistenceUtil.closeCurrentSession();
_proxyStore.cleanUp();
}
}

BeanPopulator

@Override
public <T> T populate() {
if (getBeanTransformerSpi() != null) {
getBeanTransformerSpi().getClonedMap().put(fromBean, toBean);
}
// invoking all declaring setter methods of toBean from all matching getter methods of fromBean
for (Method m : baseConfig.getSetterMethodCollector().collect(toBean)) {
processSetterMethod(m);
}
@SuppressWarnings("unchecked")
T ret = (T) toBean;
return ret;
}

private void processSetterMethod(Method setterMethod) {
String methodName = setterMethod.getName();
final String propertyString = methodName.substring(baseConfig.getSetterMethodCollector().getMethodPrefix().length());

if (baseConfig.isDebug()) {
if (log.isInfoEnabled()) {
log.info(new StringBuilder("processSetterMethod: processing propertyString=").append(propertyString).append("")
.append(", fromClass=").append(fromBean.getClass()).append(", toClass=").append(toBean.getClass()).toString());
}
}
Method readerMethod = baseConfig.getReaderMethodFinder().find(propertyString, fromBean);

if (readerMethod == null) {
return;
}
// Reader method of fromBean found
Class<?> paramType = setterMethod.getParameterTypes()[0];
String propertyName = Introspector.decapitalize(propertyString);
try {
doit(setterMethod, readerMethod, paramType, propertyName);
} catch (Exception ex) {
baseConfig.getBeanPopulationExceptionHandler().initFromBean(fromBean).initToBean(toBean).initPropertyName(propertyName)
.initReaderMethod(readerMethod).initSetterMethod(setterMethod).handleException(ex, log);
}
}

private <T> void doit(Method setterMethod, Method readerMethod, Class<T> paramType, final String propertyName) {
if (baseConfig.getDetailedPropertyFilter() != null) {
if (!baseConfig.getDetailedPropertyFilter().propagate(propertyName, fromBean, readerMethod, toBean, setterMethod)) {
return;
}
}
if (baseConfig.getPropertyFilter() != null) {
if (!baseConfig.getPropertyFilter().propagate(propertyName, readerMethod)) {
return;
}
}
Object propertyValue = this.invokeMethodAsPrivileged(fromBean, readerMethod, null);

if (baseConfig.getBeanSourceHandler() != null) {
baseConfig.getBeanSourceHandler().handleBeanSource(fromBean, readerMethod, propertyValue);
}

if (transformer != null) {
PropertyInfo propertyInfo = new PropertyInfo(propertyName, fromBean, toBean);
propertyValue = transformer.transform(propertyValue, paramType, propertyInfo);
}

if (baseConfig.isDebug()) {
if (log.isInfoEnabled()) {
log.info("processSetterMethod: setting propertyName=" + propertyName);
}
}
// Invoke setter method
Object[] args = { propertyValue };
this.invokeMethodAsPrivileged(toBean, setterMethod, args);
return;
}

Gilead HibernateUtil class

最佳答案

这可能是由以下代码引起的:

public void addUPI(String pwd, Timestamp pwdTS, Boolean pwdChng){
UserPasswordInfo upi = new UserPasswordInfo();
upi.setPassword(pwd);
upi.setPasswordTS(pwdTS);
upi.setPwdChange(pwdChng);
if(getId() != null)
upi.setUserId(getId().intValue());
passwordInfos.add(upi);
}

如果您调用此方法然后存储您的 User 对象,我会假设抛出异常。关键是您需要先将 UserPasswordInfo 附加到上下文,然后才能将其添加到 User 对象。

所以正确的顺序是先存储UserPasswordInfo:

entityManager.persist(upi);

然后将其添加到密码并存储用户对象:

user.getPasswordInfos().add(upi);
entityManager.save(user);

关于java - 首次保存后出现 TransientObjectException 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44530801/

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