gpt4 book ai didi

java - JPA 乐观锁异常

转载 作者:太空宇宙 更新时间:2023-11-04 15:09:26 25 4
gpt4 key购买 nike

我正在编程的项目有问题。
它是一个 jsf 2.1 版应用程序。我使用 eclipse 链接作为 jpa 实现。

我正在处理的类称为 User、Logentry 和 LoginLogManager。用户仅包含有关网站用户的信息和登录项列表。每次用户登录时,都会创建一个 Logentry 并将其写入数据库。这发生在 LoginLogmanager 中。

所以这是我的问题:当我的 Logentry 表为空时,我可以毫无问题地创建一个 logentry 并将其写入表中,但是当我再次执行此操作时,会抛出 OptimisticLockException。
我对 JPA 还很陌生,但到目前为止,我发现当我想要保存的行 self 上次阅读以来被更新或删除时,就会发生这种情况。
这真的让我很困惑,因为我以前从未读过日志。该对象是在我将其写入数据库之前创建的。

@Entity
@Table(name="LOGENTRY")
@NamedQuery(name="Logentry.findAll", query="SELECT l FROM Logentry l")
public class Logentry implements Serializable {
private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy = IDENTITY)
private int LE_ID;

@Column(nullable=false)
private Timestamp CREATE_TIMESTAMP;

private boolean DELETED;

@Column(nullable=false, length=1000)
private String DESCRIPTION;

@Column(nullable=false)
private Timestamp MODIFIEDTS;

@Version
@Column(nullable=false)
private int VERSION_ID;

//bi-directional many-to-one association to Logtype
@ManyToOne
@JoinColumn(name="LT_ID", nullable=false)
private Logtype LOGTYPE;

//bi-directional many-to-one association to User
@ManyToOne
@JoinColumn(name="US_ID", nullable=false)
private User USER;

public Logentry() {
}

public int getLE_ID() {
return this.LE_ID;
}

public void setLE_ID(int LE_ID) {
this.LE_ID = LE_ID;
}

public Timestamp getCREATE_TIMESTAMP() {
return this.CREATE_TIMESTAMP;
}

public void setCREATE_TIMESTAMP(Timestamp CREATE_TIMESTAMP) {
this.CREATE_TIMESTAMP = CREATE_TIMESTAMP;
}

public boolean getDELETED() {
return this.DELETED;
}

public void setDELETED(boolean DELETED) {
this.DELETED = DELETED;
}

public String getDESCRIPTION() {
return this.DESCRIPTION;
}

public void setDESCRIPTION(String DESCRIPTION) {
this.DESCRIPTION = DESCRIPTION;
}

public Timestamp getMODIFIEDTS() {
return this.MODIFIEDTS;
}

public void setMODIFIEDTS(Timestamp MODIFIEDTS) {
this.MODIFIEDTS = MODIFIEDTS;
}

public int getVERSION_ID() {
return this.VERSION_ID;
}

public void setVERSION_ID(int VERSION_ID) {
this.VERSION_ID = VERSION_ID;
}

public Logtype getLOGTYPE() {
return this.LOGTYPE;
}

public void setLOGTYPE(Logtype LOGTYPE) {
this.LOGTYPE = LOGTYPE;
}

public User getUSER() {
return this.USER;
}

public void setUSER(User USER) {
this.USER = USER;
}

}`

我的用户Pojo:

@Entity
@Table(name="USER")
@NamedQuery(name="User.findAll", query="SELECT u FROM User u")
public class User implements Serializable {
private static final long serialVersionUID = 1L;

private static Logger log = Logger.getLogger(User.class.getName());

@Id
@GeneratedValue(strategy = IDENTITY)
private int US_ID;

private Timestamp BIRTHDAY;

@Column(length=50)
private String CITY;

@Column(length=50)
private String COUNTRY;

@Column(length=20)
private String DEGREE;

private boolean DELETED;

@Column(nullable=false, length=75)
private String EMAIL;

@Column(length=45)
private String FAX;

@Column(length=100)
private String FIRST_NAME;

@Column(length=45)
private String FIXED_LINE;

private Timestamp INACTIVATION_TIMESTAMP;

@Column(nullable=false, length=100)
private String LAST_NAME;

@Column(length=45)
private String MOBILE_PHONE;

@Column(nullable=false)
private Timestamp MODIFIEDTS;

@Column(nullable=false, length=50)
private String PASSWORD;

@Column(length=50)
private String STATE;

@Column(length=100)
private String STREET_NAME;

@Column(length=20)
private String STREET_NO;

@Column(length=20)
private String TITLE;

@Column(nullable=false, length=75)
private String USER_NAME;

@Version
@Column(nullable=false)
private int VERSION_ID;

@Column(length=10)
private String ZIP;

//bi-directional many-to-one association to Logentry
@OneToMany(mappedBy="USER")
private List<Logentry> LOGENTRIES;

//bi-directional many-to-one association to SupplierUserRole
@OneToMany(mappedBy="USER")
private List<Supplier_User_Role> SUPPLIER_USER_ROLES;

//bi-directional many-to-one association to Taskbox
@OneToMany(mappedBy="FROM_USER")
private List<Taskbox> TASKBOX_AS_USERS;

//bi-directional many-to-one association to Taskbox
@OneToMany(mappedBy="TO_USER")
private List<Taskbox> TASKBOX_AS_TOS;

//bi-directional many-to-one association to Language
@ManyToOne(fetch = LAZY)
@JoinColumn(name="LA_ID", nullable=false)
private Language LANGUAGE;

public User() {
}

public int getUS_ID() {
return this.US_ID;
}

public void setUS_ID(int US_ID) {
this.US_ID = US_ID;
}

public Timestamp getBIRTHDAY() {
return this.BIRTHDAY;
}

public void setBIRTHDAY(Timestamp BIRTHDAY) {
this.BIRTHDAY = BIRTHDAY;
}

public String getCITY() {
return this.CITY;
}

public void setCITY(String CITY) {
this.CITY = CITY;
}

public String getCOUNTRY() {
return this.COUNTRY;
}

public void setCOUNTRY(String COUNTRY) {
this.COUNTRY = COUNTRY;
}

public String getDEGREE() {
return this.DEGREE;
}

public void setDEGREE(String DEGREE) {
this.DEGREE = DEGREE;
}

public boolean getDELETED() {
return this.DELETED;
}

public void setDELETED(boolean DELETED) {
this.DELETED = DELETED;
}

public String getEMAIL() {
return this.EMAIL;
}

public void setEMAIL(String EMAIL) {
this.EMAIL = EMAIL;
}

public String getFAX() {
return this.FAX;
}

public void setFAX(String FAX) {
this.FAX = FAX;
}

public String getFIRST_NAME() {
return this.FIRST_NAME;
}

public void setFIRST_NAME(String FIRST_NAME) {
this.FIRST_NAME = FIRST_NAME;
}

public String getFIXED_LINE() {
return this.FIXED_LINE;
}

public void setFIXED_LINE(String FIXED_LINE) {
this.FIXED_LINE = FIXED_LINE;
}

public Timestamp getINACTIVATION_TIMESTAMP() {
return this.INACTIVATION_TIMESTAMP;
}

public void setINACTIVATION_TIMESTAMP(Timestamp INACTIVATION_TIMESTAMP) {
this.INACTIVATION_TIMESTAMP = INACTIVATION_TIMESTAMP;
}

public String getLAST_NAME() {
return this.LAST_NAME;
}

public void setLAST_NAME(String LAST_NAME) {
this.LAST_NAME = LAST_NAME;
}

public String getMOBILE_PHONE() {
return this.MOBILE_PHONE;
}

public void setMOBILE_PHONE(String MOBILE_PHONE) {
this.MOBILE_PHONE = MOBILE_PHONE;
}

public Timestamp getMODIFIEDTS() {
return this.MODIFIEDTS;
}

public void setMODIFIEDTS(Timestamp MODIFIEDTS) {
this.MODIFIEDTS = MODIFIEDTS;
}

public String getPASSWORD() {
return this.PASSWORD;
}

public void setPASSWORD(String PASSWORD) {
this.PASSWORD = PASSWORD;
}

public String getSTATE() {
return this.STATE;
}

public void setSTATE(String STATE) {
this.STATE = STATE;
}

public String getSTREET_NAME() {
return this.STREET_NAME;
}

public void setSTREET_NAME(String STREET_NAME) {
this.STREET_NAME = STREET_NAME;
}

public String getSTREET_NO() {
return this.STREET_NO;
}

public void setSTREET_NO(String STREET_NO) {
this.STREET_NO = STREET_NO;
}

public String getTITLE() {
return this.TITLE;
}

public void setTITLE(String TITLE) {
this.TITLE = TITLE;
}

public String getUSER_NAME() {
return this.USER_NAME;
}

public void setUSER_NAME(String USER_NAME) {
this.USER_NAME = USER_NAME;
}

public int getVERSION_ID() {
return this.VERSION_ID;
}

public void setVERSION_ID(int VERSION_ID) {
this.VERSION_ID = VERSION_ID;
}

public String getZIP() {
return this.ZIP;
}

public void setZIP(String ZIP) {
this.ZIP = ZIP;
}

public List<Logentry> getLOGENTRIES() {
return this.LOGENTRIES;
}

public void setLOGENTRIES(List<Logentry> LOGENTRIES) {
this.LOGENTRIES = LOGENTRIES;
}

public Logentry addLOGENTRy(Logentry LOGENTRy) {
getLOGENTRIES().add(LOGENTRy);

if(this.getLOGENTRIES()!=null)
log.info("Liste mit Logs ist nicht null!");

LOGENTRy.setUSER(this);

return LOGENTRy;
}

public Logentry removeLOGENTRy(Logentry LOGENTRy) {
getLOGENTRIES().remove(LOGENTRy);
LOGENTRy.setUSER(null);

return LOGENTRy;
}

public List<Supplier_User_Role> getSUPPLIER_USER_ROLES() {
return this.SUPPLIER_USER_ROLES;
}

public void setSUPPLIER_USER_ROLES(List<Supplier_User_Role> SUPPLIER_USER_ROLES) {
this.SUPPLIER_USER_ROLES = SUPPLIER_USER_ROLES;
}

public Supplier_User_Role addSUPPLIER_USER_ROLE(Supplier_User_Role SUPPLIER_USER_ROLE) {
getSUPPLIER_USER_ROLES().add(SUPPLIER_USER_ROLE);
SUPPLIER_USER_ROLE.setUSER(this);

return SUPPLIER_USER_ROLE;
}

public Supplier_User_Role removeSUPPLIER_USER_ROLE(Supplier_User_Role SUPPLIER_USER_ROLE) {
getSUPPLIER_USER_ROLES().remove(SUPPLIER_USER_ROLE);
SUPPLIER_USER_ROLE.setUSER(null);

return SUPPLIER_USER_ROLE;
}

public List<Taskbox> getTASKBOX_AS_USERS() {
return this.TASKBOX_AS_USERS;
}

public void setTASKBOX_AS_USERS(List<Taskbox> TASKBOX_AS_USERS) {
this.TASKBOX_AS_USERS = TASKBOX_AS_USERS;
}

public Taskbox addTASKBOX_AS_USER(Taskbox TASKBOX_AS_USER) {
getTASKBOX_AS_USERS().add(TASKBOX_AS_USER);
TASKBOX_AS_USER.setFROM_USER(this);

return TASKBOX_AS_USER;
}

public Taskbox removeTASKBOX_AS_USER(Taskbox TASKBOX_AS_USER) {
getTASKBOX_AS_USERS().remove(TASKBOX_AS_USER);
TASKBOX_AS_USER.setFROM_USER(null);

return TASKBOX_AS_USER;
}

public List<Taskbox> getTASKBOX_AS_TOS() {
return this.TASKBOX_AS_TOS;
}

public void setTASKBOX_AS_TOS(List<Taskbox> TASKBOX_AS_TOS) {
this.TASKBOX_AS_TOS = TASKBOX_AS_TOS;
}

public Taskbox addTASKBOX_AS_TO(Taskbox TASKBOX_AS_TO) {
getTASKBOX_AS_TOS().add(TASKBOX_AS_TO);
TASKBOX_AS_TO.setTO_USER(this);

return TASKBOX_AS_TO;
}

public Taskbox removeTASKBOX_AS_TO(Taskbox TASKBOX_AS_TO) {
getTASKBOX_AS_TOS().remove(TASKBOX_AS_TO);
TASKBOX_AS_TO.setTO_USER(null);

return TASKBOX_AS_TO;
}

public Language getLANGUAGE() {
return this.LANGUAGE;
}

public void setLANGUAGE(Language LANGUAGE) {
this.LANGUAGE = LANGUAGE;
}

}

和我的 LoginLogManager:

@ManagedBean(name="loginLogManager")
@SessionScoped
public class LoginLogManager implements Serializable{

private static final long serialVersionUID = 1L;
private static Logger log = Logger.getLogger(LoginLogManager.class.getName());

@ManagedProperty(value="#{logtypeDaoImpl}")
private LogtypeDao logTypeDao;

@ManagedProperty(value="#{logentryDaoImpl}")
private LogentryDao logEntryDao;

@ManagedProperty(value="#{userDaoImpl}")
private UserDao userDao;

private Timestamp timeStamp;
private Logentry logEntry;
private Logtype logtype;


public void createLog(String description,int logTypeId,User user){

timeStamp=new Timestamp(System.currentTimeMillis());
logtype=logTypeDao.findByID(logTypeId);


logEntry=new Logentry();
logEntry.setCREATE_TIMESTAMP(timeStamp);
logEntry.setDESCRIPTION(description);
logEntry.setLOGTYPE(logtype);
logEntry.setMODIFIEDTS(timeStamp);


user.addLOGENTRy(logEntry);
userDao.update(user);

}


public static Logger getLog() {
return log;
}


public static void setLog(Logger log) {
LoginLogManager.log = log;
}


public LogtypeDao getLogTypeDao() {
return logTypeDao;
}


public void setLogTypeDao(LogtypeDao logTypeDao) {
this.logTypeDao = logTypeDao;
}


public UserDao getUserDao() {
return userDao;
}


public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}


public Timestamp getTimeStamp() {
return timeStamp;
}


public void setTimeStamp(Timestamp timeStamp) {
this.timeStamp = timeStamp;
}


public Logentry getLogEntry() {
return logEntry;
}


public void setLogEntry(Logentry logEntry) {
this.logEntry = logEntry;
}


public Logtype getLogtype() {
return logtype;
}


public void setLogtype(Logtype logtype) {
this.logtype = logtype;
}


public static long getSerialversionuid() {
return serialVersionUID;
}


public LogentryDao getLogEntryDao() {
return logEntryDao;
}


public void setLogEntryDao(LogentryDao logEntryDao) {
this.logEntryDao = logEntryDao;
}



}

这是我的 UserDao:

@ManagedBean(name = "userDaoImpl")
@SessionScoped
public class UserDaoImpl extends GenericDaoImpl<User> implements UserDao,
Serializable {

private static Logger log = Logger.getLogger(UserDaoImpl.class.getName());

/**
*
*/
private static final long serialVersionUID = -5280393555113818663L;

/**
* Loads a User by his Username
*
* @param username
* @return founded User
*/
@Override
public User findUserByUserName(String username) {
em = EMF.getEMF().createEntityManager();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<User> cq = cb.createQuery(User.class);
Root<User> user = cq.from(User.class);
cq.where(cb.and(cb.equal(user.get(User_.USER_NAME), username)));

// EntityType<User>user_=entityManager.getMetamodel().entity(User.class);

TypedQuery<User> typedQuery = em.createQuery(cq);
List<User> userList = typedQuery.getResultList();
em.close();
return userList.get(0);
}

/**
* Loads a User by his Username and Password
*
* @param username
* @param password
* @return founded User
*/
@Override
public User findUserByUsernameAndPassword(String username, String password) {
em = EMF.getEMF().createEntityManager();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<User> cq = cb.createQuery(User.class);
Root<User> user = cq.from(User.class);
cq.where(cb.and(cb.equal(user.get(User_.USER_NAME), username),
cb.equal(user.get(User_.PASSWORD), password)));

log.info(""+username + " "+password);
log.info(""+user.get(User_.USER_NAME)+ " "+(user.get(User_.PASSWORD)));

// EntityType<User>user_=entityManager.getMetamodel().entity(User.class);

TypedQuery<User> typedQuery = em.createQuery(cq);
List<User> userList = typedQuery.getResultList();
em.close();
return userList.get(0);
}
}

以及实现的 GenericDAO:

public abstract class GenericDaoImpl<T> implements GenericDao<T> {

protected EntityManager em = null;

private Class<T> type;

@SuppressWarnings("unchecked")
public GenericDaoImpl() {
Type t = getClass().getGenericSuperclass();
ParameterizedType pt = (ParameterizedType) t;
type = (Class<T>) pt.getActualTypeArguments()[0];
}

/**
* Inserts a new row to the database
*
*
* @param t
* : Object to insert
* @return Object with key and new version
*/
@Override
public T insert(final T t) {
em = EMF.getEMF().createEntityManager();
em.getTransaction().begin();
em.persist(t);
// em.flush();
// em.refresh(t);
em.getTransaction().commit();
em.close();
return t;
}

/**
* Deletes a row in the database by id
*
*
* @param id
* : id of the Object
*/
@Override
public void delete(final Object id) {
em = EMF.getEMF().createEntityManager();
em.getTransaction().begin();
em.remove(em.getReference(type, id));
em.getTransaction().commit();
em.close();
}

/**
* Finds a row in the database by id and return it
*
*
* @param id
* : id of the Object
* @return Object, which is found
*/
@Override
public T findByID(final Object id) {
em = EMF.getEMF().createEntityManager();
em.getTransaction().begin();
T te = (T) em.find(type, id);
em.getTransaction().commit();
em.close();
return te;
}

/**
* Updates a row in the database
*
*
* @param t
* : Object to update
* @return Object with new version
*/
@Override
public T update(final T t) {
em = EMF.getEMF().createEntityManager();
em.getTransaction().begin();
T te = em.merge(t);
em.getTransaction().commit();
em.close();
return te;
}

/**
* Counts the number of rows in this database table
*
*
* @param params
* : database arguments for counting
* @return number of rows
*/
@Override
public long countAll(final Map<String, Object> params) {

final StringBuffer queryString = new StringBuffer(
"SELECT count(o) from ");

queryString.append(type.getSimpleName()).append(" o ");
queryString.append(getQueryClauses(params, null));

em = EMF.getEMF().createEntityManager();
em.getTransaction().begin();
final Query query = em.createQuery(queryString.toString());
em.getTransaction().commit();
em.close();

return (Long) query.getSingleResult();

}

/**
* Finds All Objects in this database table
*
*
* @return all Objects in the database table
*/
@SuppressWarnings("unchecked")
public List<T> findAll() {
em = EMF.getEMF().createEntityManager();
em.getTransaction().begin();
List<T> teList = em.createQuery(
"Select t from " + type.getSimpleName() + " t").getResultList();
em.getTransaction().commit();
em.close();
return teList;
}

/**
* Creates a part of a String for a Query
*
* @return created String
*/
private String getQueryClauses(final Map<String, Object> params,
final Map<String, Object> orderParams) {
final StringBuffer queryString = new StringBuffer();
if ((params != null) && !params.isEmpty()) {
queryString.append(" where ");
for (final Iterator<Map.Entry<String, Object>> it = params
.entrySet().iterator(); it.hasNext();) {
final Map.Entry<String, Object> entry = it.next();
if (entry.getValue() instanceof Boolean) {
queryString.append(entry.getKey()).append(" is ")
.append(entry.getValue()).append(" ");
} else {
if (entry.getValue() instanceof Number) {
queryString.append(entry.getKey()).append(" = ")
.append(entry.getValue());
} else {
// string equality
queryString.append(entry.getKey()).append(" = '")
.append(entry.getValue()).append("'");
}
}
if (it.hasNext()) {
queryString.append(" and ");
}
}
}
if ((orderParams != null) && !orderParams.isEmpty()) {
queryString.append(" order by ");
for (final Iterator<Map.Entry<String, Object>> it = orderParams
.entrySet().iterator(); it.hasNext();) {
final Map.Entry<String, Object> entry = it.next();
queryString.append(entry.getKey()).append(" ");
if (entry.getValue() != null) {
queryString.append(entry.getValue());
}
if (it.hasNext()) {
queryString.append(", ");
}
}
}
return queryString.toString();
}
}

正如我之前所说,当我第二次登录并且数据库中已经有一个日志时,它会抛出 OLE。

无法合并对象 [at.dccs.csm.database.entity.Logentry@419a7187],因为自上次读取以来该对象已更改或已删除。

这就是异常描述。
我不知道为什么这里抛出这个异常。
我希望您能给我建议并帮助我解决我的问题。

最佳答案

首先,在Java Word中,大写属性用于静态最终字段。您可以搜索 JavaBeans 规范。

private Long id; public Long getId(){return id;} public void setId(Long id){this.id=id;}

我建议您使用原始包装器而不是原始的 id。我的意思是,使用 Integer 而不是 int。如果 id 为 null,则您的实体不会被持久化。

其次,您不需要覆盖 equals/hashcode 即可使其工作。

第三,在JPA世界中,你不需要任何DAO。您可以搜索域存储模式。实体管理器已经完成了“CRUD”工作。

当您关闭实体管理器时,所有实体都将从持久性上下文中分离。因此,对 DAO 的每次调用都有不同的上下文,导致您创建不同的实体/事务。

在您的 DAO 世界中,您不得打开和关闭实体管理器并在 dao 内创建事务。您希望在提交事务之前执行多个请求。如果创建多个事务,如果发生错误,则仅最后一部分会回滚。这非常糟糕。

您需要有一个服务层来完成这项工作。

对于您的问题,在同一事务中,合并您的用户,合并您的日志条目(设置用户),然后在您的用户中添加日志条目。

关于java - JPA 乐观锁异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21535133/

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