2017-11-20 9 views
0

Ich entwickle eine Webanwendung, wo ich unter anderem eine Datei in eine BLOB-Spalte in einer MySQL-Tabelle hochladen muss. Von dem, was ich sehe, kann dies getan werden kann, mit JDBC (PrepareStatement() usw.) nennt, aber ich möchte in der Lage sein, dies in einer EJB-Klasse zu tun - was habe ich gepflasterten sieht zusammen wie folgt aus:EJB und vorbereiteteStatement?

@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; 
    } 
... 
} 

ich habe zwei Fragen, aber:

  • ich mag JDBC nicht direkt verwenden - ist es eine Möglichkeit, dies zu tun, die ‚reine JPA‘ (edit: nicht EJB) ist?

  • Wenn ich es so machen muss, ist PreparedStatement in der Container-verwalteten Transaktion enthalten?


Ein weiterer edit: der obige Code macht den Job - ich jetzt getestet haben. Aber es ist nicht schön, denke ich.

+0

Es ist unklar, was Sie mit "reinem EJB" meinen. EJB ist keine Datenzugriffstechnologie. Normalerweise verwenden Sie JDBC oder JPA, um über EJBs auf die Datenbank zuzugreifen. –

+0

Ah, ja, JPA, falsche Wortwahl - ich korrigiere es in meiner Frage. – j4nd3r53n

Antwort

0

Das erste, was Sie tun müssen, BLOB-Werte der JPA Weg Sie bestehen bleiben Definieren Sie eine Entität. Die folgenden ein Beispiel pseodo Code:

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

    @Lob 
    private byte[] doc; 

    // .... getters + setters 
} 

Dann Sie Ihre EJB wie folgt ändern:

@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????? 
    } 
    ... 
} 

Wenn Sie sich nicht ändern Sie die Standardeinstellungen EJB Methoden werden in einer Transaktion standardmäßig aufgerufen. Wenn Ihre Methode beendet wird, sollte das Update daher mit der Datenbank synchronisiert werden.

Diese Antwort kann Ihnen nur helfen, wenn Sie die Grundlagen der JPA lesen und verstehen. Und here ist ein offizielles Tutorial zur JPA-Persistenz unter vielen anderen Tutorials im Web.

aktualisieren

Ich möchte JDBC nicht direkt verwenden - ist es eine Möglichkeit, dies zu tun, die 'reine JPA' ist

Nr

Wenn Ich muss es so machen, ist das PreparedStatement in der Container-verwalteten Transaktion enthalten?

Nein. Sie können jedoch eine Bean-gesteuerte Transaktion verwenden. Wenn Sie BMT verwenden möchten, könnte der folgende Pseudocode Ihnen helfen:

@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

Ich sehe, ich hätte mehr Details zur Verfügung stellen sollen - ich verstehe JPA, und der Code, in den dieses Fragment passt, ist eine Standard-Webanwendung mit EJB, CDI, JPA, JSF usw. Ich habe jedoch keine Möglichkeit gefunden, das zu tun, was ich will. Das ist, einen InputStream direkt zu einer BLOB-Spalte in einer Tabelle zu streamen, wie es der JDBC-Code in meinem Beispiel tut. Die Datei, die ich im BLOB speichern möchte, stammt möglicherweise von einem Remote-Client über einen Webbrowser. Ich weiß also nicht, wie groß sie ist, und sie könnte sehr groß sein. daher möchte ich es nicht in ein Byte-Array im Speicher kopieren, und ich möchte es auch nicht in eine Datei kopieren. – j4nd3r53n

+0

Nun, das nächste Mal, wenn Sie eine Frage stellen, versuchen Sie, genau zu Ihrer Anforderung zu sein. Sie haben nicht erwähnt, wie groß Ihre Datei sein könnte. – ujulu

+0

Thx für die Antwort - Ich werde Ihre Antwort akzeptieren. Der Grund, warum ich nichts über die Größe der Datei gesagt habe, ist, weil ich keine wirkliche Idee habe - es könnte alles von etwas 100K (kleines Dokument?) Bis zu wirklich groß sein. Aber, was noch wichtiger ist, wenn es in einer zukünftigen Inkarnation eine große Anzahl von Benutzern gibt, dann wäre es gut, wenn ich bereits darüber nachgedacht hätte, keinen großen Puffer für jede Sitzung zuzuweisen. – j4nd3r53n