Преглед на файлове

Removed the OR-mapped relation between DeliveryHistory and HandlingEvent, making DH a transient object. DH is populated by a repository call.

peter_backlund преди 18 години
родител
ревизия
6e66db1fd3

+ 2
- 3
dddsample/src/main/java/se/citerus/dddsample/domain/Cargo.java Целия файл

@@ -26,8 +26,8 @@ public class Cargo {
26 26
   @ManyToOne
27 27
   private Location finalDestination;
28 28
 
29
-  @Embedded
30
-  private DeliveryHistory deliveryHistory;
29
+  @Transient
30
+  private DeliveryHistory deliveryHistory = new DeliveryHistory();
31 31
 
32 32
   @OneToOne
33 33
   private Itinerary itinerary;
@@ -36,7 +36,6 @@ public class Cargo {
36 36
     this.trackingId = trackingId;
37 37
     this.origin = origin;
38 38
     this.finalDestination = finalDestination;
39
-    this.deliveryHistory =  new DeliveryHistory();
40 39
   }
41 40
 
42 41
   /**

+ 0
- 6
dddsample/src/main/java/se/citerus/dddsample/domain/DeliveryHistory.java Целия файл

@@ -3,20 +3,14 @@ package se.citerus.dddsample.domain;
3 3
 import org.apache.commons.lang.builder.ReflectionToStringBuilder;
4 4
 import org.apache.commons.lang.builder.ToStringStyle;
5 5
 
6
-import javax.persistence.Embeddable;
7
-import javax.persistence.JoinColumn;
8
-import javax.persistence.OneToMany;
9 6
 import java.util.*;
10 7
 
11 8
 /**
12 9
  * The delivery history of a cargo.
13 10
  *
14 11
  */
15
-@Embeddable
16 12
 public class DeliveryHistory {
17 13
 
18
-  @OneToMany
19
-  @JoinColumn(name = "cargo_id")
20 14
   private Set<HandlingEvent> events = new HashSet<HandlingEvent>();
21 15
 
22 16
   /**

+ 12
- 1
dddsample/src/main/java/se/citerus/dddsample/repository/CargoRepositoryHibernate.java Целия файл

@@ -10,16 +10,27 @@ import se.citerus.dddsample.domain.TrackingId;
10 10
 @Repository
11 11
 public class CargoRepositoryHibernate extends HibernateRepository implements CargoRepository {
12 12
 
13
+  HandlingEventRepository handlingEventRepository;
13 14
 
14 15
   public Cargo find(TrackingId trackingId) {
15
-    return (Cargo) getSession().
16
+    Cargo cargo = (Cargo) getSession().
16 17
             createQuery("from Cargo where trackingId = ?").
17 18
             setParameter(0, trackingId).
18 19
             uniqueResult();
20
+    /*
21
+        If this extra database call were a problem, you might want to use a different model.
22
+        For example, calculate the effect/status of the cargo and store it separate from the
23
+        handling events.
24
+     */
25
+    cargo.deliveryHistory().addAllEvents(handlingEventRepository.findEventsForCargo(trackingId));
26
+    return cargo;
19 27
   }
20 28
 
21 29
   public void save(Cargo cargo) {
22 30
     getSession().saveOrUpdate(cargo);
23 31
   }
24 32
 
33
+  public void setHandlingEventRepository(HandlingEventRepository handlingEventRepository) {
34
+    this.handlingEventRepository = handlingEventRepository;
35
+  }
25 36
 }

+ 8
- 0
dddsample/src/main/java/se/citerus/dddsample/repository/HandlingEventRepository.java Целия файл

@@ -1,6 +1,9 @@
1 1
 package se.citerus.dddsample.repository;
2 2
 
3 3
 import se.citerus.dddsample.domain.HandlingEvent;
4
+import se.citerus.dddsample.domain.TrackingId;
5
+
6
+import java.util.List;
4 7
 
5 8
 /**
6 9
  * Handling event repository.
@@ -15,4 +18,9 @@ public interface HandlingEventRepository {
15 18
    */
16 19
   void save(HandlingEvent event);
17 20
 
21
+  /**
22
+   * @param trackingId cargo tracking id
23
+   * @return All handling events for this cargo, ordered by completion time.
24
+   */
25
+  List<HandlingEvent> findEventsForCargo(TrackingId trackingId);
18 26
 }

+ 10
- 0
dddsample/src/main/java/se/citerus/dddsample/repository/HandlingEventRepositoryHibernate.java Целия файл

@@ -2,6 +2,9 @@ package se.citerus.dddsample.repository;
2 2
 
3 3
 import org.springframework.stereotype.Repository;
4 4
 import se.citerus.dddsample.domain.HandlingEvent;
5
+import se.citerus.dddsample.domain.TrackingId;
6
+
7
+import java.util.List;
5 8
 
6 9
 /**
7 10
  * Hibernate implementation of HandlingEventRepository.
@@ -14,4 +17,11 @@ public class HandlingEventRepositoryHibernate extends HibernateRepository implem
14 17
     getSession().save(event);
15 18
   }
16 19
 
20
+  public List<HandlingEvent> findEventsForCargo(TrackingId tid) {
21
+    return getSession().createQuery(
22
+            "from HandlingEvent where cargo.trackingId = :tid order by completionTime").
23
+            setParameter("tid", tid).
24
+            list();
25
+  }
26
+
17 27
 }

+ 5
- 4
dddsample/src/main/java/se/citerus/dddsample/repository/HandlingEventRepositoryInMem.java Целия файл

@@ -8,10 +8,7 @@ import se.citerus.dddsample.domain.HandlingEvent.Type;
8 8
 import java.text.DateFormat;
9 9
 import java.text.ParseException;
10 10
 import java.text.SimpleDateFormat;
11
-import java.util.Date;
12
-import java.util.HashMap;
13
-import java.util.HashSet;
14
-import java.util.Set;
11
+import java.util.*;
15 12
 
16 13
 public class HandlingEventRepositoryInMem implements HandlingEventRepository{
17 14
   private HashMap<String, HandlingEvent> eventDB;
@@ -111,6 +108,10 @@ public class HandlingEventRepositoryInMem implements HandlingEventRepository{
111 108
     */
112 109
   }
113 110
 
111
+  public List<HandlingEvent> findEventsForCargo(TrackingId trackingId) {
112
+    return new ArrayList<HandlingEvent>(eventDB.values());
113
+  }
114
+
114 115
   public DeliveryHistory findDeliveryHistory(TrackingId trackingId) {
115 116
     return null;  //To change body of implemented methods use File | Settings | File Templates.
116 117
   }

+ 11
- 15
dddsample/src/main/java/se/citerus/dddsample/service/HandlingEventServiceImpl.java Целия файл

@@ -18,6 +18,7 @@ public class HandlingEventServiceImpl implements HandlingEventService {
18 18
 
19 19
   @Transactional(readOnly = false)
20 20
   public void register(Date completionTime, TrackingId trackingId, CarrierMovementId carrierMovementId, UnLocode unlocode, HandlingEvent.Type type) throws UnknownCarrierMovementIdException, UnknownTrackingIdException, UnknownLocationException {
21
+    // Carrier movement may be null for certain event types
21 22
     Validate.noNullElements(new Object[] {trackingId, unlocode, type});
22 23
 
23 24
     Cargo cargo = cargoRepository.find(trackingId);
@@ -28,23 +29,18 @@ public class HandlingEventServiceImpl implements HandlingEventService {
28 29
     Date registrationTime = new Date();
29 30
     HandlingEvent event = new HandlingEvent(cargo, completionTime, registrationTime, type, location, carrierMovement);
30 31
 
31
-    //DeliveryHistory deliveryHistory = deliveryHistoryRepository.findByTrackingId(trackingId);
32
-    //DeliveryHistory deliveryHistory = cargo.deliveryHistory();
33
-
34
-    //deliveryHistory.addEvent(event);
35
-    //deliveryHistoryRepository.save(deliveryHistory);
36
-
37
-    /*
38
-    HandlingEvent event;
39
-    if (carrierMovement != null) {
40
-      event = new HandlingEvent(cargo, completionTime, registrationTime, type, location, carrierMovement);
41
-    } else {
42
-      event = new HandlingEvent(cargo, completionTime, registrationTime, type, location);
43
-    }
44
-    */
45 32
     handlingEventRepository.save(event);
46 33
 
47
-    //assert cargo.deliveryHistory().eventsOrderedByCompletionTime().contains(event); // <- FALSE here
34
+    /*
35
+      NOTE:
36
+        The cargo instance that's loaded and associated with the handling event is
37
+        in an inconsitent state, because the cargo delivery history's collection of
38
+        events does not contain the event created here. However, this is not a problem,
39
+        because cargo is in a different aggregate from handling event.
40
+        The rules of an aggregate dictate that all consistency rules within the aggregate
41
+        are enforced synchronously in the transaction, but consistency rules of other aggregates
42
+        are enforced by asynchronous updates, after the commit of this transaction.
43
+     */
48 44
   }
49 45
 
50 46
   private CarrierMovement findCarrierMovement(CarrierMovementId carrierMovementId) throws UnknownCarrierMovementIdException {

+ 1
- 0
dddsample/src/main/resources/context-persistence.xml Целия файл

@@ -24,6 +24,7 @@
24 24
 
25 25
   <bean id="cargoRepository" class="se.citerus.dddsample.repository.CargoRepositoryHibernate">
26 26
     <property name="sessionFactory" ref="sessionFactory"/>
27
+    <property name="handlingEventRepository" ref="handlingEventRepository"/>
27 28
   </bean>
28 29
 
29 30
   <bean id="handlingEventRepository" class="se.citerus.dddsample.repository.HandlingEventRepositoryHibernate">

+ 0
- 1
dddsample/src/main/resources/hibernate.cfg.xml Целия файл

@@ -15,7 +15,6 @@
15 15
     <mapping class="se.citerus.dddsample.domain.CarrierMovement"/>
16 16
     <mapping class="se.citerus.dddsample.domain.Itinerary"/>
17 17
     <mapping class="se.citerus.dddsample.domain.TrackingId"/>
18
-    <mapping class="se.citerus.dddsample.domain.DeliveryHistory"/>
19 18
     <mapping class="se.citerus.dddsample.domain.CarrierMovementId"/>
20 19
     <mapping class="se.citerus.dddsample.domain.UnLocode"/>
21 20
   </session-factory>

+ 6
- 0
dddsample/src/test/java/se/citerus/dddsample/repository/HandlingEventRepositoryTest.java Целия файл

@@ -3,6 +3,7 @@ package se.citerus.dddsample.repository;
3 3
 import se.citerus.dddsample.domain.*;
4 4
 
5 5
 import java.util.Date;
6
+import java.util.List;
6 7
 import java.util.Map;
7 8
 
8 9
 public class HandlingEventRepositoryTest extends AbstractRepositoryTest {
@@ -43,4 +44,9 @@ public class HandlingEventRepositoryTest extends AbstractRepositoryTest {
43 44
     // TODO: the rest of the columns
44 45
   }
45 46
 
47
+  public void testFindEventsForCargo() throws Exception {
48
+    List<HandlingEvent> handlingEvents = handlingEventRepository.findEventsForCargo(new TrackingId("XYZ"));
49
+    assertEquals(12, handlingEvents.size());
50
+  }
51
+
46 52
 }