postgresql 类'LocalCertificate'的属性[id]Map到数据库中的主键列,不允许更新

06odsfpq  于 2023-02-22  发布在  PostgreSQL
关注(0)|答案(1)|浏览(122)

我很久以前就面临这个问题了,我没有意识到Java方面的这个问题。我正在处理一个旧的JPA项目,没有Java和Postgres SQL的先验知识。
我有一个实体类,我可以把它推到derby数据库中,但是现在我也想把数据复制到Postgres中。
实体类:

@Table(name = "certs")
public class LocalCertificate implements Serializable {

    private static final long serialVersionUID = -5003848691574858779L;

    @Expose
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Expose
    @Column(name = "d_id")
    private String d_id;
    
    @Expose
    @Column(name = "certificate", columnDefinition="clob")
    @Convert()
    @Lob
    private X509CertificateHolder certificate;
    
    @Expose
    @Column(name = "revoked")
    public boolean revoked = false;
    
    public byte[] getCertDER() throws IOException {
        return certificate.getEncoded();
    }
    
    
    public long getId() {
        return id.longValue();
    }
    
    public String getDId() {
        return d_id;
    }
    
    public void store() {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("LDB");
        EntityManager locEm = emf.createEntityManager();

        EntityTransaction ta = locEm.getTransaction();
        ta.begin();
        locEm.persist(this);
        ta.commit();
        
        // for Postgres
        EntityManagerFactory eemf = Persistence.createEntityManagerFactory("PU_CSA");
        EntityManager llocEm = eemf.createEntityManager();

        EntityTransaction tta = llocEm.getTransaction();
        tta.begin();
        llocEm.persist(this);
        tta.commit();
    }
    
    public void update() {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("LDB");
        EntityManager locEm = emf.createEntityManager();

        EntityTransaction ta = locEm.getTransaction();
        
        ta.begin();
        locEm.merge(this);
        ta.commit();
        
        // for postgres
        EntityManagerFactory eemf = Persistence.createEntityManagerFactory("PU_CSA");
        EntityManager llocEm = eemf.createEntityManager();

        EntityTransaction tta = llocEm.getTransaction();
        
        tta.begin();
        llocEm.merge(this);
        tta.commit();
    }
    
    public void setD_id(String dId) {
        // TODO Auto-generated method stub
        this.d_id =  dId;
    }

    public void setCertificate(X509CertificateHolder cert) {
        // TODO Auto-generated method stub
        this.certificate = cert;        
    }
}

持久性xml文件:

<persistence-unit name="LDB">
        <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
        <non-jta-data-source>java:comp/env/jdbc/LDB</non-jta-data-source>
        <class>org.backend.dao.LocalCertificate</class>
        <class>org.backend.certserver.jpa.LocalCertificateAdapter</class>
        
        <properties>
            <!-- EclipseLink should create the database schema automatically -->
            <property name="eclipselink.ddl-generation" value="create-or-extend-tables" />
            <property name="eclipselink.ddl-generation.output-mode" value="database" />
        </properties>
    </persistence-unit>

    <persistence-unit name="PU_CSA">
        <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
        <non-jta-data-source>java:comp/env/jdbc/CSA</non-jta-data-source>
        <class>org.backend.dao.Device</class>
        <class>org.backend.dao.LocalCertificate</class>
        <class>org.backend.certserver.jpa.LocalCertificateAdapter</class>
        <properties>
            <!-- EclipseLink should create the database schema automatically -->
            <property name="eclipselink.ddl-generation" value="create-or-extend-tables" />
            <property name="eclipselink.ddl-generation.output-mode" value="database" /> 
        </properties>
    </persistence-unit>

对于d_id和证书列,我可以看到NULL值。如何解决此问题?

xzv2uavs

xzv2uavs1#

要实现这一点,您需要创建要持久化/合并的示例的副本,以便在第二个持久化上下文中使用-类似于:

Static final EntityManagerFactory emf = Persistence.createEntityManagerFactory("LDB");
// for postgres
Static final EntityManagerFactory eemf = Persistence.createEntityManagerFactory("PU_CSA");

public void update(LocalCertificate cert) {
    EntityManager locEm = emf.createEntityManager()
    try {
      EntityTransaction ta = locEm.getTransaction();
    
      ta.begin();
      locEm.merge(cert);
      ta.commit();
    } finally { locEm.close();}

    CopyGroup group = new CopyGroup();
    LocalCertificate copy = (Playlist)em.unwrap( JpaEntityManager.class ).copy( cert, group );
    
    EntityManager llocEm = eemf.createEntityManager();
    try {
      EntityTransaction tta = llocEm.getTransaction();
    
      tta.begin();
      llocEm.merge(copy);
      tta.commit();
    } finally { llocEm.close();}
}

要持久化一个新的实体,你需要做更多的工作,因为你的模型不能像现在这样工作--你可能不能在Derby和Postgres中同时使用身份管理,或者你的实体将被赋予不同的主键值。要解决这个问题,最简单的解决方案是自己赋值,如下所示:

@Table(name = "certs")
public class LocalCertificate implements Serializable {

  @Id
  private String id;
  ..
  @PrePersist
  public void setId() {
    if (StringUtil.isBlank(id)) {
      id = UUID.randomUUID().toString();
    }
  }
 }

然后可以使用相同的概念进行持久化。

相关问题