Version 2

    JBoss EJB 3.0 and Extensions

     

    &12487;&12540;&12479;&12505;&12540;&12473;&12398;&26356;&26032;&12392;&21516;&26399; (Update and Synchronize the Database)

    &12399;&12376;&12417;&12395; (Introduction)

     

    The EJB 3.0 container allows you to update data rows in the database by directly manipulating the entity bean objects. The changes are automatically queued and sent to the database. In this trail, you will learn how exactly the database update works.

     

    EJB 3.0&12467;&12531;&12486;&12490;&12399;&12456;&12531;&12486;&12451;&12486;&12451;Bean&12458;&12502;&12472;&12455;&12463;&12488;&12434;&30452;&25509;&25805;&20316;&12377;&12427;&12371;&12392;&12391;&12487;&12540;&12479;&12505;&12540;&12473;&20869;&12398;&12487;&12540;&12479;&34892;&12434;&26356;&26032;&21487;&33021;&12395;&12375;&12414;&12377;&12290;&12381;&12398;&22793;&26356;&12399;&33258;&21205;&30340;&12395;&12461;&12517;&12540;&12395;&33988;&31309;&12373;&12428;(queued)&12289;&12487;&12540;&12479;&12505;&12540;&12473;&12395;&36865;&20986;&12373;&12428;&12414;&12377;&12290;&12371;&12398;&23567;&36947;&12391;&12399;&12289;&12414;&12373;&12375;&12367;&12487;&12540;&12479;&12505;&12540;&12473;&12364;&26356;&26032;&12364;&27231;&33021;&12377;&12427;&27096;&23376;&12434;&23398;&12403;&12414;&12377;&12290;

     

    &12469;&12531;&12503;&12523;&12450;&12503;&12522;&12465;&12540;&12471;&12519;&12531; (The sample application)

     

    To illustrate database update, we implement a new feature for the investment calculator to update all the dollar values in the TimedRecord table to another currency. All you need to do is to enter the currency exchange rate in the following form and click on the "Update" button.

     

    &12487;&12540;&12479;&12505;&12540;&12473;&26356;&26032;&12434;&35500;&26126;&12377;&12427;&12383;&12417;&12289;&25237;&36039;&35336;&31639;&27231;&12395;TimeRecord&12486;&12540;&12502;&12523;&20869;&12398;&12377;&12409;&12390;&12398;&12489;&12523;&12398;&20516;&12434;&21029;&12398;&36890;&36008;(currency)&12408;&26356;&26032;&12377;&12427;&26032;&27231;&33021;&12434;&23455;&35013;&12375;&12414;&12377;&12290;&12420;&12425;&12394;&12369;&12428;&12400;&12394;&12425;&12394;&12356;&12371;&12392;&12399;&12289;&27425;&12398;&12501;&12457;&12540;&12512;&12398;&28858;&26367;&22793;&25563;&12524;&12540;&12488;&12434;&20837;&21147;&12375;&12390;&12300;&26356;&26032;&12301;&12508;&12479;&12531;&12434;&12463;&12522;&12483;&12463;&12377;&12427;&12384;&12369;&12391;&12377;&12290;

     

    &26356;&26032;&12503;&12525;&12475;&12473; (The update process)

     

    To update rows in a table, you should first retrieve those rows into entity bean objects via the EntityManager API. Then, you can just use the regular setter methods to update any data attributes (mapped to table columns in the database). The updates are automatically sent to the database. The code segment below shows how the update works.

     

    &12486;&12540;&12502;&12523;&12398;&35079;&25968;&34892;&12434;&26356;&26032;&12377;&12427;&12395;&12399;&12289;&26368;&21021;&12395;EntityManager API&12395;&12424;&12387;&12390;&12381;&12428;&12425;&12398;&34892;&12434;&12456;&12531;&12486;&12451;&12486;&12451;Bean&12408;&21462;&24471;&12377;&12409;&12365;&12391;&12377;&12290;&12381;&12358;&12377;&12428;&12400;&12289;&65288;&12487;&12540;&12479;&12505;&12540;&12473;&20869;&12398;&12486;&12540;&12502;&12523;&12459;&12521;&12512;&12395;&12510;&12483;&12503;&12373;&12428;&12427;&65289;&20219;&24847;&12398;&12487;&12540;&12479;&23646;&24615;&12398;&26356;&26032;&12434;&12377;&12427;&12398;&12395;&12289;&36890;&24120;&12398;&12475;&12483;&12479;&12540;&12513;&12477;&12483;&12489;&12434;&20351;&12358;&12384;&12369;&12391;&21487;&33021;&12395;&12394;&12426;&12414;&12377;&12290;

    @Stateless
    public class UpdateCalculator implements Calculator {
    
      @PersistenceContext
      protected EntityManager em;
    
      // ... ...
    
      public void updateExchangeRate (double newrate) {
        Collection <TimedRecord> rc = 
          em.createQuery("from TimedRecord r").getResultList();
        for (Iterator iter = rc.iterator(); iter.hasNext();) {
          TimedRecord r = (TimedRecord) iter.next();
          r.setSaving(r.getSaving() * newrate);
          r.setResult(r.getResult() * newrate);
        }
      }
    }
    

    &12487;&12540;&12479;&12505;&12540;&12473;&12392;&12398;&21516;&26399; (Synchronize with database)

     

    In the updateExchangeRate() method, we used a loop to update all the calculation record bean instances. But it would be slow and inefficient for the container to send a remote SQL update to the database for every bean update inside the loop. The multiple round trips increase the chance for network errors and increase the database load. A much better way is to queue the updates and synchronize them to the database in a batch after the loop finishes. That is exactly what the container did in this case.

     

    updateExchangeRate()&12513;&12477;&12483;&12489;&12391;&12399;&12289;&12377;&12409;&12390;&12398;&35336;&31639;&35352;&37682;Bean&12452;&12531;&12473;&12479;&12531;&12473;&12434;&26356;&26032;&12377;&12427;&12383;&12417;&12395;&12523;&12540;&12503;&12434;&20351;&12387;&12390;&12356;&12414;&12375;&12383;&12290;&12375;&12363;&12375;&12289;&12523;&12540;&12503;&20869;&12391;&21508;Bean&12434;&26356;&26032;&12377;&12427;&12383;&12417;&12395;&12467;&12531;&12486;&12490;&12364;&12487;&12540;&12479;&12505;&12540;&12473;&12395;&23550;&12375;&12390;&12522;&12514;&12540;&12488;&12398;SQL&26356;&26032;&12434;&36865;&20449;&12377;&12427;&12392;&12356;&12358;&12398;&12399;&36933;&12367;&12390;&21177;&29575;&12364;&24746;&12356;&12371;&12392;&12391;&12377;&12290;&35079;&25968;&12521;&12454;&12531;&12489;&12488;&12522;&12483;&12503;(&35379;&27880;:&12354;&12392;&12391;&36969;&24403;&12394;&35379;&35486;&12434;&32771;&12360;&12427;)&12399;&12493;&12483;&12488;&12527;&12540;&12463;&12456;&12521;&12540;&12398;&27231;&20250;&12434;&22679;&22823;&12373;&12379;&12289;&12487;&12540;&12479;&12505;&12540;&12473;&12398;&20184;&21152;&12434;&22679;&22823;&12373;&12379;&12414;&12377;&12290;&12424;&12426;&33391;&12356;&26041;&27861;&12399;&12289;&12461;&12517;&12540;&12395;&26356;&26032;&12434;&33988;&31309;&12375;&12289;&12523;&12540;&12503;&12364;&32066;&20102;&12375;&12383;&24460;&12391;&12496;&12483;&12481;&12395;&12424;&12387;&12390;&12381;&12428;&12425;&12398;&35201;&27714;&12434;&12487;&12540;&12479;&12505;&12540;&12473;&12392;&21516;&26399;&12373;&12379;&12427;&12392;&12356;&12358;&26041;&27861;&12391;&12377;&12290;&12371;&12428;&12399;&12467;&12531;&12486;&12490;&12364;&12371;&12398;&12465;&12540;&12473;&12391;&12414;&12373;&12395;&23455;&34892;&12375;&12390;&12356;&12383;&12371;&12392;&12391;&12377;&12290;

     

    By default, all the EntityManager operations, including persisting new beans, removing beans and updating beans, are cached in memory. They are synchronized to the database in a single batch when the current thread (i.e., stack of method calls) finishes, or before the next database query is issued, whichever comes first. In our example, the container synchronizes all the bean objects to the database immediately after the updateExchangeRate() method finishes.

     

    &12487;&12501;&12457;&12523;&12488;&12391;&12399;&12289;&12377;&12409;&12390;&12398;EntityManager&25805;&20316;&65288;&26032;&35215;Bean&12398;&27704;&32154;&21270;&12289;Bean&12398;&21066;&38500;&12289;Bean&12398;&26356;&26032;&65289;&12399;&12289;&12513;&12514;&12522;&19978;&12395;&12461;&12515;&12483;&12471;&12517;&12373;&12428;&12414;&12377;&12290;&12381;&12428;&12425;&12399;&29694;&22312;&12473;&12524;&12483;&12489;&65288;&12388;&12414;&12426;&12289;&12513;&12477;&12483;&12489;&21628;&12403;&20986;&12375;&12473;&12479;&12483;&12463;&65289;&12364;&23436;&20102;&12375;&12383;&12392;&12365;&12289;&12354;&12427;&12356;&12399;&27425;&12398;&12487;&12540;&12479;&12505;&12540;&12473;&21839;&21512;&12379;&12364;&30330;&34892;&12373;&12428;&12427;&21069;&12289;&12398;&12356;&12378;&12428;&12363;&26089;&12356;&26041;&12391;&12289;&21336;&19968;&12398;&12496;&12483;&12481;&12395;&12424;&12387;&12390;&12487;&12540;&12479;&12505;&12540;&12473;&12392;&12398;&21516;&26399;&12364;&34892;&12431;&12428;&12414;&12377;&12290;&20363;&12391;&12399;&12289;&12467;&12531;&12486;&12490;&12399;updateExchangeRate()&12513;&12477;&12483;&12489;&12364;&23436;&20102;&12375;&12383;&30452;&24460;&12395;&12377;&12409;&12390;&12398;Bean&12458;&12502;&12472;&12455;&12463;&12488;&12399;&12487;&12540;&12479;&12505;&12540;&12473;&12392;&21516;&26399;&12373;&12379;&12425;&12428;&12414;&12377;&12290;

     

    But for some users, it might be desirable to manually control and optimize exactly when the database is synchronized inside a thread. For instance, you might want to send in the changes earlier to reduce memory use and avoid large cache replication in clusters. Inside a transaction, you can always flush the current in-memory changes in the EntityManager to the database by calling the EntityManager.flush() method. You can flush the EntityManager in the middle of a method or at the end of a method in the middle of a call stack (i.e., in the middle of a thread).

     

    &12375;&12363;&12375;&12289;&12518;&12540;&12470;&12395;&12424;&12387;&12390;&12399;&12289;&12473;&12524;&12483;&12489;&20869;&12391;&12398;&12487;&12540;&12479;&12505;&12540;&12473;&21516;&26399;&12398;&12479;&12452;&12511;&12531;&12464;&12434;&25163;&21205;&12391;&27491;&30906;&12395;&21046;&24481;&12375;&12289;&26368;&36969;&21270;&12375;&12383;&12356;&12392;&26395;&12416;&12363;&12418;&12375;&12428;&12414;&12379;&12435;&12290;&20363;&12360;&12400;&12289;&12463;&12521;&12473;&12479;&20869;&12391;&12513;&12514;&12522;&12434;&21066;&28187;&12375;&12289;&22823;&12365;&12394;&12461;&12515;&12483;&12471;&12517;&35079;&35069;&12434;&36991;&12369;&12427;&12383;&12417;&12289;&26089;&26399;&12395;&22793;&26356;&12434;&36865;&20449;&12375;&12383;&12356;&12392;&26395;&12416;&12363;&12418;&12375;&12428;&12414;&12379;&12435;&12290;&12488;&12521;&12531;&12470;&12463;&12471;&12519;&12531;&20869;&12391;&12399;&12289;EntityManager.flush()&12434;&21628;&12403;&20986;&12377;&12371;&12392;&12395;&12424;&12387;&12390;&12289;EntityManager&20869;&12398;&29694;&22312;&12398;&12452;&12531;&12539;&12513;&12514;&12522;(in-memory)&22793;&26356;&12434;&12487;&12540;&12479;&12505;&12540;&12473;&12395;&23550;&12375;&12390;&12501;&12521;&12483;&12471;&12517;&12377;&12427;&12371;&12392;&12364;&21487;&33021;&12391;&12377;&12290;EntityManager&12398;&12501;&12521;&12483;&12471;&12517;&12399;&12289;&12513;&12477;&12483;&12489;&12398;&36884;&20013;&12420;&12467;&12540;&12523;&12473;&12479;&12483;&12463;&12398;&36884;&20013;&12391;&12398;&12513;&12477;&12483;&12489;&12398;&26368;&24460;&65288;&12388;&12414;&12426;&12289;&12473;&12524;&12483;&12489;&12398;&36884;&20013;&65289;&12391;&21487;&33021;&12391;&12377;&12290;

     

    &12456;&12531;&12486;&12451;&12486;&12451;Bean&12398;&12487;&12540;&12479;&12505;&12540;&12473;&12408;&12398;&12510;&12540;&12472; (Merge entity beans into database)

     

    The local EntityManager keeps track of the entity beans it retrieved and captures all updates to the beans objects that need to be synchronized to the database. But how about entity bean instances that are not obtained by the local EntityManager? For instance, what if you have a TimedRecord bean that is sent via a serialized network connection? How do you update it and get the changes synchronized to the database? To do that, you can use the EntityManager.merge() method and pass the bean instance as the call parameter.

     

    &12525;&12540;&12459;&12523;EntityManager&12399;&21462;&24471;&28168;&12415;&12398;&12456;&12531;&12486;&12451;&12486;&12451;Bean&12398;&35352;&37682;&12434;&21462;&12426;&12289;&12487;&12540;&12479;&12505;&12540;&12473;&12408;&12398;&21516;&26399;&12364;&24517;&35201;&12392;&12394;&12427;&12424;&12358;&12394;Bean&12458;&12502;&12472;&12455;&12463;&12488;&12408;&12398;&12377;&12409;&12390;&12398;&26356;&26032;&24773;&22577;&12434;&25429;&25417;&12375;&12414;&12377;&12290;&12375;&12363;&12375;&12289;&12525;&12540;&12459;&12523;EntityManager&12363;&12425;&24471;&12427;&12371;&12392;&12364;&12391;&12365;&12394;&12356;&12456;&12531;&12486;&12451;&12486;&12451;Bean&12452;&12531;&12473;&12479;&12531;&12473;&12395;&12388;&12356;&12390;&12399;&12393;&12358;&12377;&12428;&12400;&12424;&12356;&12398;&12391;&12375;&12423;&12358;&12363;&12290;&20363;&12360;&12400;&12289;TimedRecord Bean&12364;&12493;&12483;&12488;&12527;&12540;&12463;&25509;&32154;&12434;&20171;&12375;&12390;&12471;&12522;&12450;&12521;&12452;&12474;&12373;&12428;&12390;&12356;&12383;&12392;&12375;&12383;&12425;&12393;&12358;&12375;&12414;&12377;&12363;&12290;&12393;&12358;&12420;&12387;&12390;&12381;&12428;&12434;&26356;&26032;&12375;&12383;&12426;&12289;&12487;&12540;&12479;&12505;&12540;&12473;&12408;&21516;&26399;&12377;&12409;&12365;&22793;&26356;&12434;&21462;&24471;&12375;&12383;&12426;&12391;&12365;&12427;&12398;&12391;&12375;&12423;&12358;&12290;&12381;&12428;&12434;&12377;&12427;&12395;&12399;&12289;EntityManager.merge()&12513;&12477;&12483;&12489;&12434;&20351;&12387;&12390;&12289;&12381;&12398;&21628;&12403;&20986;&12375;&12497;&12521;&12513;&12479;&12392;&12375;&12390;Bean&12452;&12531;&12473;&12479;&12531;&12473;&12434;&28193;&12377;&12371;&12392;&12364;&12391;&12365;&12427;&12398;&12391;&12377;&12290;

     

    In general, if you update an entity bean obtained outside of the local thread, you need to invoke the EntityManager.merge() method to merge its values back to the database.

     

    &19968;&33324;&30340;&12395;&12399;&12289;&12525;&12540;&12459;&12523;&12473;&12524;&12483;&12489;&20197;&22806;&12363;&12425;&24471;&12383;&12456;&12531;&12486;&12451;&12486;&12451;Bean&12434;&26356;&26032;&12377;&12427;&12394;&12425;&12289;EntityManager.merge()&12434;&21628;&12403;&20986;&12375;&12390;&12381;&12398;&20516;&12434;&12487;&12540;&12479;&12505;&12540;&12473;&12408;&26360;&12365;&25147;&12375;&12390;&12510;&12540;&12472;&12377;&12427;&24517;&35201;&12364;&12354;&12426;&12414;&12377;&12290;

     

    &23436;&20840;&12394;&12477;&12540;&12473;&12467;&12540;&12489;&12522;&12501;&12449;&12524;&12531;&12473; (Complete source code reference)

     

    Session bean

     

    &12475;&12483;&12471;&12519;&12531;Bean

     

         Calculator.java is the stateless session bean interface

         Calculator.java&12399;&12473;&12486;&12540;&12488;&12524;&12473;&12475;&12483;&12471;&12519;&12531;Bean&12452;&12531;&12479;&12501;&12455;&12540;&12473;&12391;&12377;

         UpdateCalculatorBean.java is the session bean implement that performs the database update

         UpdateCalculatorBean.java&12399;&12487;&12540;&12479;&12505;&12540;&12473;&26356;&26032;&12398;&23455;&34892;&12434;&23455;&35013;&12377;&12427;&12475;&12483;&12471;&12519;&12531;Bean&12391;&12377;&12290;

     

    The JSP user interface

     

    JSP&12518;&12540;&12470;&12452;&12531;&12479;&12501;&12455;&12540;&12473;

     

         update.jsp

     

    &12414;&12392;&12417; (Summary)

     

    In this trail, you learned how to update the database. We also discussed the database synchronization strategies and merging unmanaged entity bean instances. In fact, in EJB 3.0, the database synchronization is managed by the container's transaction manager. In the transaction trail later, you will learn how the transaction manager works. In the next trail, let's briefly go over entity bean's life cycle callbacks in the next trail.

     

    &12371;&12398;&23567;&36947;&12391;&12399;&12289;&12487;&12540;&12479;&12505;&12540;&12473;&12398;&26356;&26032;&26041;&27861;&12434;&23398;&32722;&12375;&12414;&12375;&12383;&12290;&12487;&12540;&12479;&12505;&12540;&12473;&21516;&26399;&25126;&30053;&12392;&26356;&26032;&12373;&12428;&12390;&12356;&12394;&12356;&12456;&12531;&12486;&12451;&12486;&12451;Bean&12452;&12531;&12473;&12479;&12531;&12473;&12398;&12510;&12540;&12472;&12395;&12388;&12356;&12390;&12418;&35696;&35542;&12375;&12414;&12375;&12383;&12290;&12388;&12414;&12426;&12289;EJB 3.0&12391;&12399;&12289;&12487;&12540;&12479;&12505;&12540;&12473;&21516;&26399;&12399;&12467;&12531;&12486;&12490;&12398;&12488;&12521;&12531;&12470;&12463;&12471;&12519;&12531;&12510;&12493;&12540;&12472;&12515;&12395;&12424;&12387;&12390;&31649;&29702;&12373;&12428;&12427;&12398;&12391;&12377;&12290;&24460;&12391;&30331;&22580;&12377;&12427;&12488;&12521;&12531;&12470;&12463;&12471;&12519;&12531;&12398;&23567;&36947;&12391;&12399;&12289;&12488;&12521;&12531;&12470;&12463;&12471;&12519;&12531;&12510;&12493;&12540;&12472;&12515;&12364;&12393;&12398;&12424;&12358;&12395;&21205;&20316;&12377;&12427;&12363;&12395;&12388;&12356;&12390;&23398;&12403;&12414;&12377;&12290;&27425;&12398;&23567;&36947;&12391;&12399;&12289;&12456;&12531;&12486;&12451;&12486;&12451;Bean&12398;&12521;&12452;&12501;&12469;&12452;&12463;&12523;&12467;&12540;&12523;&12496;&12483;&12463;&12395;&12388;&12356;&12390;&25163;&30701;&12395;&23398;&12403;&12414;&12375;&12423;&12358;(&35379;&27880;: in the next trail&12364;&20887;&38263;)&12290;

     

    � 2005 JBoss, Inc. All Rights Reserved