EJB和preparedStatement?

时间:2017-11-20 11:40:12

标签: java mysql jdbc ejb

我正在开发一个Web应用程序,除其他外,我需要将文件上传到mysql表中的BLOB列。从我可以看到这可以通过JDBC调用(PrepareStatement()等)完成,但我希望能够在EJB类中完成此操作 - 我拼凑在一起的内容如下所示:

@Stateless
public class ItemsSession {
    @PersistenceContext(unitName ="officePU")
    private EntityManager em;
    private List<Items> itl;
    private static final Logger logger=
            Logger.getLogger(ItemsSession.class.getName());
...
    public String updateDocument(Integer id,InputStream is) throws SQLException{
        String msg="";
        try{
            java.sql.Connection conn = em.unwrap(java.sql.Connection.class);
            PreparedStatement pstmt=conn.prepareStatement("UPDATE Documents SET doc = ? WHERE id = ?");
            pstmt.setBinaryStream(1, is);
            pstmt.setLong(2, id);
            pstmt.executeUpdate();
            pstmt.close();
        }
        catch (PersistenceException e){
            msg=e.getMessage();
        }

        return msg;
    }
...
}

但我有两个问题:

  • 我不想直接使用JDBC - 有没有办法做到这一点,纯粹的JPA&#39; (编辑:不是EJB)?

  • 如果我必须这样做,PreparedStatement是否包含在容器管理的交易中?

另一个编辑:上面的代码完成了工作 - 我现在已经测试过了。但我觉得它并不漂亮。

2 个答案:

答案 0 :(得分:0)

我认为您使用EJB intergate与JPA,因为您正在使用它:

@PersistenceContext(unitName ="officePU")

参考:http://www.adam-bien.com/roller/abien/entry/ejb_3_persistence_jpa_for

答案 1 :(得分:0)

要保持BLOB值JPA方式的第一件事就是定义一个实体。以下是一个示例pseodo代码:

@Entity
public class Documents {
    @Id
    private Long id;

    @Lob
    private byte[] doc;

    // .... getters + setters 
}

然后按如下方式修改EJB:

@Stateless
public class ItemsSession {
    @PersistenceContext(unitName ="officePU")
    private EntityManager em;
    // ... the rest of your code

    public String updateDocument(Integer id,InputStream is) throws SQLException{
        String msg = "";
        Documents docs = em.find(Documents.class, id); // fetch record from DB
        // Assuming your InputStream is a ByteArrayInputStream
        byte[] doc = new byte[is.available()]; // create target array
        is.read(doc, 0, doc.length);  // read bytes into byte array
        docs.setDoc(doc); // 

        return msg; // returning exception message from method call?????
    }
    ...
}

如果您没有更改默认值,默认情况下会在事务中调用EJB方法。因此,当您的方法退出时,更新应该与数据库同步。

如果您阅读并理解JPA的基础知识,这个答案kann只会帮助您。 here是JPA持久性在网络上其他许多教程中的官方教程。

<强>更新

  

我不想直接使用JDBC - 有没有办法做到这一点纯粹的JPA&#39;

没有

  

如果我必须这样做,PreparedStatement是否包含在容器管理事务中?

没有。但是你可以使用bean管理的事务。如果您想使用BMT,以下伪代码可能会对您有所帮助:

@Stateless
@TransactionManagement(TransactionManagementType.BEAN)
public class ItemsSession {

    @Resource UserTransaction ut;
    @Resource DataSource datasource;  // you should define datasource on your application server

    ...
    public String updateDocument(Integer id,InputStream is) throws SQLException{
        // ...
        try (java.sql.Connection conn = datasource.getConnection();
            PreparedStatement pstmt=conn.prepareStatement("UPDATE Documents SET doc = ? WHERE id = ?")) {

            pstmt.setBinaryStream(1, is);
            pstmt.setLong(2, id);

            ut.begin();
            pstmt.executeUpdate();
            ut.commit();

        } catch (PersistenceException e){
            // ... error handling
        }

        return ...;
    }
...
}