如何在Java JPA中持久存在多对一的双向实体?

时间:2015-08-04 21:18:36

标签: java hibernate jpa

我得到一个空值,用于持久存在导致约束错误的一对多双向实体。

我有两个实体设置如下,我有一个抽象的外观'它处理实体管理器,它只是将实体持久化,刷新,合并等数据库。我有一个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给用户。通过用户名获取用户来找到用户。不确定是什么导致了这个问题。

0 个答案:

没有答案