我得到一个空值,用于持久存在导致约束错误的一对多双向实体。
我有两个实体设置如下,我有一个抽象的外观'它处理实体管理器,它只是将实体持久化,刷新,合并等数据库。我有一个Restful后端来处理ejbs和web客户端(mobile inc)之间的交互。除了我试图坚持一个"令牌"在此示例中,向其添加现有用户。下面的代码应该解释我想要实现的目标。
用户
package ejb;
import java.io.Serializable;
import java.util.Collection;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import javax.persistence.PrePersist;
import java.util.UUID;
import javax.persistence.UniqueConstraint;
@Entity
@Table(name = "users", catalog = "test", schema = "public", uniqueConstraints = @UniqueConstraint(columnNames = {"username", "email"}))
@XmlRootElement
@NamedQueries({
@NamedQuery(name = "Users.findAll", query = "SELECT u FROM Users u")
})
public class Users implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false)
@NotNull
@Size(min = 1, max = 36)
@Column(name = "userid")
private String userid;
@Size(max = 100)
@Column(name = "username")
private String username;
@Size(max = 108)
@Column(name = "email")
private String email;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "users")
private Collection<Tokens> tokensCollection;
public Users() {
}
public Users(String userid) {
this.userid = userid;
}
public String getUserid() {
return userid;
}
public void serUserid(String userid) {
this.userid= userid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@XmlTransient
public Collection<Tokens> getTokensCollection() {
return tokensCollection;
}
public void setTokensCollection(Tokens token) {
token.setUser(this);
tokensCollection.add(token);
}
@Override
public String toString() {
return "ejb.Users[ userid =" + userid + " ]";
}
@PrePersist
protected void setUUID(){
String uuid = UUID.randomUUID().toString();
this.userid = uuid;
}
}
令牌
package ejb;
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.Date;
import java.util.UUID;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.PrePersist;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import javax.xml.bind.annotation.XmlRootElement;
@Entity
@Table(name = "tokens", catalog = "test", schema = "public")
@XmlRootElement
@NamedQueries({
@NamedQuery(name = "Tokens.findAll", query = "SELECT t FROM Tokens t"),
@NamedQuery(name = "Tokens.findByTokenid", query = "SELECT t FROM Tokens t WHERE t.tokenid = :tokenid"),
@NamedQuery(name = "Tokens.findByDevice", query = "SELECT t FROM Tokens t WHERE t.device = :device"),
@NamedQuery(name = "Tokens.findByJWT", query = "SELECT t FROM Tokens t WHERE t.jwt = :jwt"),
@NamedQuery(name = "Tokens.findByCreatedTime", query = "SELECT t FROM Tokens t WHERE t.createdTime = :createdTime"),
@NamedQuery(name = "Tokens.findByExpires", query = "SELECT t FROM Tokens t WHERE t.expires = :expires")
})
public class Tokens implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false)
@NotNull
@Size(min = 1, max = 36)
@Column(name = "tokenid")
private String tokenid;
@Column(name = "device")
private String device;
@Basic(optional = false)
@NotNull
@Column(name = "jwt")
private String jwt;
@Basic(optional = false)
@NotNull
@Column(name = "createdTime")
@Temporal(TemporalType.TIMESTAMP)
private Date createdTime;
@Basic(optional = false)
@NotNull
@Column(name = "expires")
@Temporal(TemporalType.TIMESTAMP)
private Date expires;
@JoinColumn(name = "userid", referencedColumnName = "userid", insertable = false, updatable = false)
@ManyToOne(optional = false)
@NotNull
private Users users;
public String getTokenid() {
return tokenid;
}
public void setTokenid(String tokenid) {
this.tokenid = tokenid;
}
public String getDevice() {
return device;
}
public void setDevice(String device) {
this.device = device;
}
public String getJWT() {
return jwt;
}
public void setJWT(String JWT) {
this.jwt = JWT;
}
public Date getCreatedTime() {
return createdTime;
}
public void setCreatedTime(Date createdTime) {
this.createdTime = createdTime;
}
public Date getExpiryTime() {
return expires;
}
public void setExpiryTime(Date expires) {
this.expires = expires;
}
public Users getUsers() {
return users;
}
public void setUsers(Users users) {
this.users = users;
}
@Override
public int hashCode() {
int hash = 0;
hash += (tokenid != null ? tokenid.hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Tokens)) {
return false;
}
Tokens other = (Tokens) object;
if ((this.tokenid == null && other.tokenid != null) || (this.tokenid != null && !this.tokenid.equals(other.tokenid))) {
return false;
}
return true;
}
@Override
public String toString() {
return "ejb.tokens[ id=" + tokenid + " ]";
}
@PrePersist
protected void setUUID() {
String uuid = UUID.randomUUID().toString();
this.tokenid = uuid;
this.createdTime = new Timestamp(new Date().getTime());
long expTime = 60 * 60 * 24 * 30;
this.expires = new Timestamp(new Date().getTime() + expTime);
}
}
抽象外观
package ejb;
import java.util.List;
import javax.persistence.EntityManager;
public abstract class AbstractFacade<T> {
private Class<T> entityClass;
public AbstractFacade(Class<T> entityClass) {
this.entityClass = entityClass;
}
protected abstract EntityManager getEntityManager();
public void create(T entity) {
getEntityManager().persist(entity);
getEntityManager().flush();
}
public void edit(T entity) {
getEntityManager().merge(entity);
}
public void remove(T entity) {
getEntityManager().remove(getEntityManager().merge(entity));
}
public T find(Object id) {
return getEntityManager().find(entityClass, id);
}
public List<T> findAll() {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
return getEntityManager().createQuery(cq).getResultList();
}
public List<T> findRange(int[] range) {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
javax.persistence.Query q = getEntityManager().createQuery(cq);
q.setMaxResults(range[1] - range[0] + 1);
q.setFirstResult(range[0]);
return q.getResultList();
}
public int count() {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
javax.persistence.criteria.Root<T> rt = cq.from(entityClass);
cq.select(getEntityManager().getCriteriaBuilder().count(rt));
javax.persistence.Query q = getEntityManager().createQuery(cq);
return ((Long) q.getSingleResult()).intValue();
}
}
创建令牌的代码块
Users user = ufl.getUserByUsername(username);
//test the user isn't null => outputs expected result of username
System.out.println("===WHO? " + user.getUsername() + "===");
Tokens tkn = new Tokens();
tkn.setJWT(token);
tkn.setUsers(user);
tfl.create(tkn);
错误
Caused by: org.postgresql.util.PSQLException: ERROR: null value in column "userid" violates not-null constraint
Detail: Failing row contains (5aa5fefa-4744-4acf-a640-338ea9b35758, 2015-08-04 20:28:08.578, null, 2015-08-04 21:11:20.578, eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJiNmY0N2ViMS1iMDdmLTQyNTctYWI0OS0..., null).
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2157)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1886)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:255)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:559)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:417)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:363)
at org.jboss.jca.adapters.jdbc.WrappedPreparedStatement.executeUpdate(WrappedPreparedStatement.java:493)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:208) [hibernate-core-4.3.7.Final.jar:4.3.7.Final]
... 98 more
结论 它试图保持实体但是为userid插入一个空值,即使在代码块中我有setUser给用户。通过用户名获取用户来找到用户。不确定是什么导致了这个问题。