Hibernate - 映射集合上的重复项

时间:2012-02-21 10:02:08

标签: hibernate

我有两个实体:

/*CREATE TABLE `card_type_tmp` (
  `id` int(11) NOT NULL auto_increment,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;*/

@Entity
@org.hibernate.annotations.Cache(usage = org.hibernate.annotations.CacheConcurrencyStrategy.TRANSACTIONAL)
@Table(name = "card_type_tmp")
public class CardType {
@Id
@GeneratedValue
@Column(name = "id", nullable = false, updatable = false)
private int                      id     = 0;

@OneToMany(cascade = { CascadeType.REMOVE }, mappedBy = "cardType", fetch = FetchType.LAZY)

private List<EmDefinition> emColl = new ArrayList<EmDefinition>();

public List<EmDefinition> getEmColl() {
    return emColl;
}

public int getId() {
    return id;
}
}

/*CREATE TABLE `em_def_tmp` (
  `id` int(11) NOT NULL auto_increment,
   card_type_id int(11),
  dev_param_id int(11),
  PRIMARY KEY (`id`),
CONSTRAINT cardtypeFK FOREIGN KEY (card_type_id) REFERENCES card_type_tmp(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;*/
@Entity
@Table(name = "em_def_tmp")
@NamedQuery(name = EmDefinition.NQ_FIND_BY_DEVICE_PARAM_ID_AND_CARD_TYPE_ID, query = "SELECT e FROM EmDefinition e WHERE e.dparamId=:dParamId AND e.cardType.id = :cardTypeId")
public class EmDefinition{
public static final String NQ_FIND_BY_DEVICE_PARAM_ID_AND_CARD_TYPE_ID =   "EmDefinition,findByDeviceParamAndCardType";

@Id
@GeneratedValue
@Column(name = "id", nullable = false)
private int      id = 0;

@JoinColumn(name = "card_type_id", referencedColumnName = "id", updatable = false)
@ManyToOne(cascade = {}, fetch = FetchType.LAZY)
private CardType cardType;

@Column(name = "dev_param_id")
private int      dparamId;

public int getId() {
    return id;
}

public void setId(int id) {
    this.id = id;
}

public CardType getCardType() {
    return cardType;
}

public void setCardType(CardType cardType) {
    this.cardType = cardType;
}
public int getDparamId() {
    return dparamId;
}

public void setDparamId(int dparamId) {
    this.dparamId = dparamId;
}
}

和两个sessionBeans:

@Stateless    公共类SessionBean1实现SessionBean1Local,SessionBean1Remote {

@PersistenceContext(unitName = "TestPU")
private EntityManager     em       = null;

@EJB
@org.jboss.annotation.IgnoreDependency
private SessionBean2Local sessionL = null;

private int addDefinitions(CardType card) {
//System.out.println("the 'size' value is: " + card.getEmColl().size()); //when uncommenting this printing - the result is 6 always - WHY?????
       sessionL.addDefinitions(card);
       int i = 0;
       //System.out.println("the 'size' value is: " + card.getEmColl().size());
    for (EmDefinition def : card.getEmColl()) {
        System.out.println("definitionId:" + def.getId()); //there is 7 objects printed on screen (the last two are the same)
        i++;
    }
    System.out.println("the 'i' value is: " + i);
    return i;
}

private CardType createCardType() {
    CardType cardType = new CardType();
    em.persist(cardType);
    return cardType;
}

public int createCard() {
    return this.createCardType().getId();
}

public int addDefinitions(int cardTypeId) {
    CardType card = em.find(CardType.class, cardTypeId);
    return this.addDefinitions(card);
}
}



@Stateless
public class SessionBean2 implements SessionBean2Local {

@PersistenceContext(unitName = "AirSyncPU")
private EntityManager em = null;

@Override
public void addDefinitions(CardType card) {
    for (int i = 0; i < 6; i++) {
        this.addDefinition(card, i);
    }
}

private void addDefinition(CardType card, int dParamId) {
    EmDefinition def = findByDeviceParamIdAndCardTypeId(dParamId, card.getId());
    if (def == null) {
        def = new EmDefinition();
        def.setCardType(card);
        def.setDparamId(dParamId);
        def.setId(0);           
        card.getEmColl().add(def);
        em.persist(def);
    } else {
        def.setDparamId(dParamId);
    }

    /////////////////////// WRONG BEHAViours. WHY?????????????????????
    //EmDefinition def = null;
    // em.persist(def);
    //card.getEmColl().add(def);
    //results with 12 objects on the list

    //EmDefinition def = findByDeviceParamIdAndCardTypeId(dParamId, card.getId());
    // em.persist(def);
    //card.getEmColl().add(def);
    //results with 7 objects on the list

    //EmDefinition def = findByDeviceParamIdAndCardTypeId(dParamId, card.getId());
    //card.getEmColl().add(def);
    //em.persist(def);
    //results with 7 of object on the list - the order does not matter
}

private EmDefinition findByDeviceParamIdAndCardTypeId(int dParamId, int cardTypeId) {
    Query q = em.createNamedQuery(EmDefinition.NQ_FIND_BY_DEVICE_PARAM_ID_AND_CARD_TYPE_ID);
    q.setParameter("cardTypeId", cardTypeId);
    q.setParameter("dParamId", dParamId);

    try {
        return (EmDefinition) q.getSingleResult();
    } catch (NoResultException e) {
        return null;
    }
}
}

我的测试:

   @Test
    public void test() throws NamingException {
        int card = getSessionBean1Remote().createCard();
        int definitionsNo= getSessionBean1Remote().addDefinitions(card);
        System.out.println(definitionsNo);
    }

调用getSessionBean1Remote()。addDefinitions(card);我手动添加了6个定义(数据库填充了6个定义)但是...在SessionBean1中我调用card.getEmColl()。size()并将其打印到日志中有7个对象和测试结果返回'definitionsNo '等于7。

我将休眠日志转为TRACE,这就是我所得到的:

    2012-01-18 08:22:40,294 TRACE  [org.hibernate.event.def.DefaultInitializeCollectionEventListener] initializing collection [com.tests.dupliactes.CardType.emColl#28]
    2012-01-18 08:22:40,294 TRACE [org.hibernate.event.def.DefaultInitializeCollectionEventListener] checking second-level cache
    2012-01-18 08:22:40,294 TRACE [org.hibernate.event.def.DefaultInitializeCollectionEventListener] collection not cached
    2012-01-18 08:22:40,294 DEBUG [org.hibernate.loader.Loader] loading collection: [com.tests.dupliactes.CardType.emColl#28]
    2012-01-18 08:22:40,294 DEBUG [org.hibernate.jdbc.AbstractBatcher] about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
    2012-01-18 08:22:40,294 DEBUG [org.hibernate.jdbc.ConnectionManager] opening JDBC connection
    2012-01-18 08:22:40,294 DEBUG [org.hibernate.SQL] select emcoll0_.card_type_id as card3_1_, emcoll0_.id as id1_, emcoll0_.id as id1_0_, emcoll0_.card_type_id as card3_1_0_, emcoll0_.dev_param_id as dev2_1_0_ from em_def_tmp emcoll0_ where emcoll0_.card_type_id=?
    2012-01-18 08:22:40,294 TRACE [org.hibernate.jdbc.AbstractBatcher] preparing statement
    2012-01-18 08:22:40,295 TRACE [org.hibernate.type.IntegerType] binding '28' to parameter: 1
    .......
    2012-01-18 08:22:40,300 DEBUG [org.hibernate.loader.Loader] result row: EntityKey[com.tests.dupliactes.EmDefinition#133]
    ...
    2012-01-18 08:22:40,301 DEBUG [org.hibernate.loader.Loader] result row:    EntityKey[com.tests.dupliactes.EmDefinition#134]
    ..
    2012-01-18 08:22:40,302 DEBUG [org.hibernate.loader.Loader] result row: EntityKey[com.tests.dupliactes.EmDefinition#135]
    ...
    2012-01-18 08:22:40,303 DEBUG [org.hibernate.loader.Loader] result row:  EntityKey[com.tests.dupliactes.EmDefinition#136]
    ...
    2012-01-18 08:22:40,303 DEBUG [org.hibernate.loader.Loader] result row: EntityKey[com.tests.dupliactes.EmDefinition#137]
    ...
    2012-01-18 08:22:40,304 DEBUG [org.hibernate.loader.Loader] result row: EntityKey[com.tests.dupliactes.EmDefinition#138]
    ....
    2012-01-18 08:22:40,304 DEBUG [org.hibernate.loader.Loader] found row of collection: [com.tests.dupliactes.CardType.emColl#28]
    2012-01-18 08:22:40,304 TRACE [org.hibernate.engine.loading.CollectionLoadContext] starting attempt to find loading collection [[com.tests.dupliactes.CardType.emColl#28]]
    2012-01-18 08:22:40,304 TRACE [org.hibernate.engine.loading.LoadContexts] attempting to locate loading collection entry   [CollectionKey[com.tests.dupliactes.CardType.emColl#28]] in any result-set context
    2012-01-18 08:22:40,304 TRACE [org.hibernate.engine.loading.LoadContexts] collection [CollectionKey[com.tests.dupliactes.CardType.emColl#28]] not located in load context
    2012-01-18 08:22:40,304 TRACE [org.hibernate.engine.loading.CollectionLoadContext] found loading collection bound to current result set processing; reading row
    2012-01-18 08:22:40,304 TRACE [org.hibernate.type.IntegerType] returning '138' as column: id1_
    2012-01-18 08:22:40,304 TRACE [org.hibernate.event.def.DefaultLoadEventListener] loading entity: [com.tests.dupliactes.EmDefinition#138]
    2012-01-18 08:22:40,304 TRACE [org.hibernate.event.def.DefaultLoadEventListener] attempting to resolve: [com.tests.dupliactes.EmDefinition#138]
    2012-01-18 08:22:40,304 TRACE [org.hibernate.event.def.DefaultLoadEventListener] resolved object in session cache: [com.tests.dupliactes.EmDefinition#138]
    2012-01-18 08:22:40,304 TRACE [org.hibernate.loader.Loader] done processing result set (6 rows)
    2012-01-18 08:22:40,304 DEBUG [org.hibernate.jdbc.AbstractBatcher] about to close ResultSet (open ResultSets: 1, globally: 1)
    2012-01-18 08:22:40,304 DEBUG [org.hibernate.jdbc.AbstractBatcher] about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
    2012-01-18 08:22:40,304 TRACE [org.hibernate.jdbc.AbstractBatcher] closing statement
    2012-01-18 08:22:40,305 DEBUG [org.hibernate.jdbc.ConnectionManager] aggressively releasing JDBC connection
    2012-01-18 08:22:40,305 DEBUG [org.hibernate.jdbc.ConnectionManager] releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)]
    2012-01-18 08:22:40,305 TRACE [org.hibernate.loader.Loader] total objects hydrated: 0
    2012-01-18 08:22:40,305 TRACE [org.hibernate.engine.loading.LoadContexts] attempting to locate loading collection entry [CollectionKey[com.tests.dupliactes.CardType.emColl#28]] in any result-set context
    2012-01-18 08:22:40,305 TRACE [org.hibernate.engine.loading.LoadContexts] collection [CollectionKey[com.tests.dupliactes.CardType.emColl#28]] not located in load context
    2012-01-18 08:22:40,305 TRACE [org.hibernate.engine.loading.CollectionLoadContext] removing collection load entry [org.hibernate.engine.loading.LoadingCollectionEntry<rs=com.mysql.jdbc.JDBC4ResultSet@6405b42e, coll=[com.tests.dupliactes.CardType.emColl#28]>@56de8a94]
    2012-01-18 08:22:40,305 DEBUG [org.hibernate.engine.loading.CollectionLoadContext] 1 collections were found in result set for role: com.tests.dupliactes.CardType.emColl
    2012-01-18 08:22:40,305 DEBUG [org.hibernate.engine.loading.CollectionLoadContext] ending loading collection [org.hibernate.engine.loading.LoadingCollectionEntry<rs=com.mysql.jdbc.JDBC4ResultSet@6405b42e, coll=[com.tests.dupliactes.CardType.emColl#28]>@56de8a94]
    2012-01-18 08:22:40,305 DEBUG [org.hibernate.engine.loading.CollectionLoadContext] collection fully initialized: [com.tests.dupliactes.CardType.emColl#28]
    2012-01-18 08:22:40,305 DEBUG [org.hibernate.engine.loading.CollectionLoadContext] 1 collections initialized for role: com.tests.dupliactes.CardType.emColl
    2012-01-18 08:22:40,305 DEBUG [org.hibernate.engine.StatefulPersistenceContext] initializing non-lazy collections
    2012-01-18 08:22:40,305 DEBUG [org.hibernate.loader.Loader] done loading collection
    2012-01-18 08:22:40,305 TRACE [org.hibernate.event.def.DefaultInitializeCollectionEventListener] collection initialized
    2012-01-18 08:22:40,308 INFO [STDOUT] the 'size' value is: 7
    2012-01-18 08:22:40,308 INFO [STDOUT] definitionId:133
    2012-01-18 08:22:40,308 INFO [STDOUT] definitionId:134
    2012-01-18 08:22:40,308 INFO [STDOUT] definitionId:135
    2012-01-18 08:22:40,308 INFO [STDOUT] definitionId:136
    2012-01-18 08:22:40,308 INFO [STDOUT] definitionId:137
    2012-01-18 08:22:40,308 INFO [STDOUT] definitionId:138
    2012-01-18 08:22:40,308 INFO [STDOUT] definitionId:138
    2012-01-18 08:22:40,308 INFO [STDOUT] the 'i' value is: 7
    2012-01-18 08:22:40,308 TRACE [org.hibernate.transaction.CacheSynchronization] transaction before completion callback
    2012-01-18 08:22:40,309 TRACE [org.hibernate.jdbc.JDBCContext] before transaction completion
    2012-01-18 08:22:40,309 TRACE [org.hibernate.impl.SessionImpl] before transaction completion
    2012-01-18 08:22:40,309 TRACE [org.hibernate.ejb.AbstractEntityManagerImpl] automatically flushing session
    2012-01-18 08:22:40,309 TRACE [org.hibernate.impl.SessionImpl] automatically flushing session
    2012-01-18 08:22:40,309 TRACE [org.hibernate.event.def.AbstractFlushingEventListener] flushing session
    2012-01-18 08:22:40,309 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] processing flush-time cascades
    2012-01-18 08:22:40,309 TRACE [org.hibernate.engine.Cascade] processing cascade ACTION_PERSIST_ON_FLUSH for: com.tests.dupliactes.CardType
    2012-01-18 08:22:40,309 TRACE [org.hibernate.engine.Cascade] done processing cascade ACTION_PERSIST_ON_FLUSH for: com.tests.dupliactes.CardType
    2012-01-18 08:22:40,309 TRACE [org.hibernate.engine.Cascade] processing cascade ACTION_PERSIST_ON_FLUSH for: com.tests.dupliactes.EmDefinition
    2012-01-18 08:22:40,309 TRACE [org.hibernate.engine.Cascade] done processing cascade ACTION_PERSIST_ON_FLUSH for: com.tests.dupliactes.EmDefinition
    2012-01-18 08:22:40,309 TRACE [org.hibernate.engine.Cascade] processing cascade ACTION_PERSIST_ON_FLUSH for: com.tests.dupliactes.EmDefinition
    2012-01-18 08:22:40,309 TRACE [org.hibernate.engine.Cascade] done processing cascade ACTION_PERSIST_ON_FLUSH for: com.tests.dupliactes.EmDefinition
    2012-01-18 08:22:40,309 TRACE [org.hibernate.engine.Cascade] processing cascade ACTION_PERSIST_ON_FLUSH for: com.tests.dupliactes.EmDefinition
    2012-01-18 08:22:40,309 TRACE [org.hibernate.engine.Cascade] done processing cascade ACTION_PERSIST_ON_FLUSH for: com.tests.dupliactes.EmDefinition
    2012-01-18 08:22:40,309 TRACE [org.hibernate.engine.Cascade] processing cascade ACTION_PERSIST_ON_FLUSH for: com.tests.dupliactes.EmDefinition
    2012-01-18 08:22:40,309 TRACE [org.hibernate.engine.Cascade] done processing cascade ACTION_PERSIST_ON_FLUSH for: com.tests.dupliactes.EmDefinition
    2012-01-18 08:22:40,309 TRACE [org.hibernate.engine.Cascade] processing cascade ACTION_PERSIST_ON_FLUSH for: com.tests.dupliactes.EmDefinition
    2012-01-18 08:22:40,309 TRACE [org.hibernate.engine.Cascade] done processing cascade ACTION_PERSIST_ON_FLUSH for: com.tests.dupliactes.EmDefinition
    2012-01-18 08:22:40,309 TRACE [org.hibernate.engine.Cascade] processing cascade ACTION_PERSIST_ON_FLUSH for: com.tests.dupliactes.EmDefinition
    2012-01-18 08:22:40,309 TRACE [org.hibernate.engine.Cascade] done processing cascade ACTION_PERSIST_ON_FLUSH for: com.tests.dupliactes.EmDefinition
    2012-01-18 08:22:40,309 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] dirty checking collections
    2012-01-18 08:22:40,309 DEBUG [org.hibernate.engine.CollectionEntry] Collection dirty: [com.tests.dupliactes.CardType.emColl#28]
    2012-01-18 08:22:40,310 TRACE [org.hibernate.event.def.AbstractFlushingEventListener] Flushing entities and processing referenced collections
    2012-01-18 08:22:40,310 DEBUG [org.hibernate.engine.Collections] Collection found: [com.tests.dupliactes.CardType.emColl#28], was: [com.tests.dupliactes.CardType.emColl#28] (initialized)
    2012-01-18 08:22:40,310 TRACE [org.hibernate.event.def.AbstractFlushingEventListener] Processing unreferenced collections
    2012-01-18 08:22:40,310 TRACE [org.hibernate.event.def.AbstractFlushingEventListener] Scheduling collection removes/(re)creates/updates
    2012-01-18 08:22:40,310 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] Flushed: 0 insertions, 0 updates, 0 deletions to 7 objects
    2012-01-18 08:22:40,310 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] Flushed: 0 (re)creations, 1 updates, 0 removals to 1 collections
    2012-01-18 08:22:40,310 DEBUG [org.hibernate.pretty.Printer] listing entities:
    2012-01-18 08:22:40,310 DEBUG [org.hibernate.pretty.Printer] com.tests.dupliactes.EmDefinition{id=137, dparamId=4, cardType=com.tests.dupliactes.CardType#28}
    2012-01-18 08:22:40,310 DEBUG [org.hibernate.pretty.Printer] com.tests.dupliactes.EmDefinition{id=136, dparamId=3, cardType=com.tests.dupliactes.CardType#28}
    2012-01-18 08:22:40,310 DEBUG [org.hibernate.pretty.Printer] com.tests.dupliactes.EmDefinition{id=138, dparamId=5, cardType=com.tests.dupliactes.CardType#28}
    2012-01-18 08:22:40,310 DEBUG [org.hibernate.pretty.Printer] com.tests.dupliactes.EmDefinition{id=133, dparamId=0, cardType=com.tests.dupliactes.CardType#28}
    2012-01-18 08:22:40,311 DEBUG [org.hibernate.pretty.Printer] com.tests.dupliactes.CardType{id=28, emColl=[com.tests.dupliactes.EmDefinition#133, com.tests.dupliactes.EmDefinition#134, com.tests.dupliactes.EmDefinition#135, com.tests.dupliactes.EmDefinition#136, com.tests.dupliactes.EmDefinition#137, com.tests.dupliactes.EmDefinition#138, com.tests.dupliactes.EmDefinition#138]}
    2012-01-18 08:22:40,311 DEBUG [org.hibernate.pretty.Printer] com.tests.dupliactes.EmDefinition{id=135, dparamId=2, cardType=com.tests.dupliactes.CardType#28}
    2012-01-18 08:22:40,311 DEBUG [org.hibernate.pretty.Printer] com.tests.dupliactes.EmDefinition{id=134, dparamId=1, cardType=com.tests.dupliactes.CardType#28}
    2012-01-18 08:22:40,311 TRACE [org.hibernate.event.def.AbstractFlushingEventListener] executing flush
    2012-01-18 08:22:40,311 TRACE [org.hibernate.jdbc.ConnectionManager] registering flush begin
    2012-01-18 08:22:40,311 TRACE [org.hibernate.jdbc.ConnectionManager] registering flush end
    2012-01-18 08:22:40,311 DEBUG [org.hibernate.jdbc.ConnectionManager] aggressively releasing JDBC connection
    2012-01-18 08:22:40,311 TRACE [org.hibernate.event.def.AbstractFlushingEventListener] post flush
    2012-01-18 08:22:40,335 TRACE [org.hibernate.impl.SessionImpl] closing session
    2012-01-18 08:22:40,335 TRACE [org.hibernate.jdbc.ConnectionManager] connection already null in cleanup : no action
    2012-01-18 08:22:40,335 TRACE [org.hibernate.transaction.CacheSynchronization] transaction after completion callback, status: 3
    2012-01-18 08:22:40,335 TRACE [org.hibernate.jdbc.JDBCContext] after transaction completion
    2012-01-18 08:22:40,335 TRACE [org.hibernate.impl.SessionImpl] after transaction completion



**The line 2012-01-18 08:22:40,311 DEBUG [org.hibernate.pretty.Printer] com.tests.dupliactes.CardType{id=28, emColl=[com.tests.dupliactes.EmDefinition#133, com.tests.dupliactes.EmDefinition#134, com.tests.dupliactes.EmDefinition#135, com.tests.dupliactes.EmDefinition#136, com.tests.dupliactes.EmDefinition#137, com.tests.dupliactes.EmDefinition#138, com.tests.dupliactes.EmDefinition#138]} has duplicated objects!**

我的问题是返回值为7的原因。更多信息:查看我在SessionBean1代码中的注释。当我在此指定位置添加打印cardType.getEmColl()。size()时,集合大小和返回值始终为6.如何在不使用flush或refresh的情况下解决此问题?

1 个答案:

答案 0 :(得分:0)

我不了解所有内容,但我猜你正在从db加载一个cardtype,在另一个会话中有6个defs,然后在你的会话中添加相同的defs并将它们添加到卡中。