2017-11-20 10 views
0

Webアプリケーションを開発しています。特に、mysqlテーブルのBLOBカラムにファイルをアップロードする必要があります。EJBとpreparedStatement?

@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で行うことができます見ることができるものから(のprepareStatement()など)を呼び出しますが、私はEJBクラスでこれを実行できるようにしたいと思いますでも、私は2つの質問があります

  • 私は直接JDBCを使用しない希望 - 「純粋JPA」(編集:ないEJB)でこれを行う方法はありますか?

  • このようにすれば、コンテナ管理のトランザクションにはPreparedStatementが含まれていますか?


別の編集:上記のコードは仕事をしていません - 私は今それをテストしています。しかし、それはかなりではない、と私は思う。

+0

"純粋なEJB"とはどういう意味ですか? EJBはデータアクセス技術ではありません。通常は、JDBCまたはJPAを使用してEJBからデータベースにアクセスします。 –

+0

ああ、はい、JPA、言葉の間違った選択 - 私は私の質問でそれを修正します。 – j4nd3r53n

答えて

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メソッドは、デフォルトでは、トランザクションで呼び出されるデフォルト値を変更しない場合。したがって、メソッドが終了すると、更新はデータベースと同期されます。

この回答kannは、JPAの基本を読み、理解している場合にのみ役立ちます。そして、hereは、Web上の他の多くのチュートリアルのうち、JPA永続性の公式チュートリアルです。

私は直接JDBCを使用しない希望

アップデート - '純粋JPA'

もしあるこれを行う方法があります私はこのようにしなければなりません、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 ...; 
    } 
... 
} 
+0

私はJPAを理解していますが、EJB、CDI、JPA、JSFなどを使用した標準のWebアプリケーションは、JPAを理解しています。しかし、私が望むことをする方法は見つけられませんでした。テーブルのBLOBカラムにInputStreamを直接流し込みます。これは私の例のJDBCコードのやり方です。 BLOBに保存したいファイルは、Webブラウザを介してリモートクライアントから送信される可能性があるため、どのくらいの大きさなのかわからず、非常に大きくなる可能性があります。したがって、私はそれをメモリのバイト配列にコピーしたくなく、同様に、ディスクファイルにもコピーしたくありません。 – j4nd3r53n

+0

次回に質問を投稿するときに、あなたの要件について具体的にしてみてください。あなたはあなたのファイルがどれほど巨大であろうと言及していません。 – ujulu

+0

返信のためのThx - 私はあなたの答えを受け入れるでしょう。私がファイルのサイズについて何も言っていない理由は、実際のアイデアがないからです.100K(小さな文書)から本当に大きなものまで何でも構いません。しかし、おそらくもっと重要なのは、今後のある種のインカネーションで多数のユーザーがいる場合は、各セッションに大きなバッファを割り当てないことを既に考えていれば良いでしょう。 – j4nd3r53n