2013-05-10 1 views
0

У меня есть две сущности как Люди и История. Теперь я публикую свою историю и проверяю свои истории, но иногда изредка приводит список разных историй. Я имею в виду, что usr.stories.hashCode() не совпадает с запросом differernt от точно такого же пользователя. Таблица базы данных всегда правильная, поэтому я очень смущен. Я проверил ссылку Hibernate для получения более подробной информации, но это совсем не помогло.EclipseLink JPA @OneToMany Список не одинаковый в differernt запросе той же сессии в Jesery REST

класс

Модель:

@MappedSuperclass 
public class People{ 
    @Id 
    @GeneratedValue(strategy = IDENTITY) 
    @Column(name = "id", unique = true, nullable = false) 
    public Integer id; 
    @OrderBy(value = "id DESC") 
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "people") 
    public List<Story> stories = new LinkedList<Story>(); 

    public People(){ 
    } 
} 

@MappedSuperclass 
public class Story{ 
    @Id 
    @GeneratedValue(strategy = IDENTITY) 
    @Column(name = "id", unique = true, nullable = false) 
    public Integer id; 
    @ManyToOne(fetch = FetchType.LAZY) 
    @JoinColumn(name = "people_id") 
    public People people; 
    @Column(name = "story", nullable = false) 
    public String story; 

    public Story(String story){ 
     this.story = story; 
    } 
} 

REST класс:

@Path("/story") 
public class StoryRS { 
    @POST 
    public StreamingOutput create(final @Context HttpServletRequest req, final String story) throws IOException{ 
     return new StreamingOutput() { 
      @Override 
      public void write(OutputStream os) { 
       HttpSession hs = req.getSession(false); 
       if (hs != null && story != null && story.trim().length() > 0) { 
        Integer uid = (Integer) hs.getAttribute("uid"); 
        People usr = uid != null ? PeopleDAO.findById(uid) : null; 
        if (usr != null) { 
         Story obj = new Story(story); 
         EntityManagerHelper.beginTransaction(); 
         StoryDAO.save(obj); 
         EntityManagerHelper.commit(); 
         os.write(obj.id); 
        } 
       } 
       os.close(); 
      } 
     }; 
    } 

    @GET 
    public StreamingOutput create(final @Context HttpServletRequest req) throws IOException{ 
     return new StreamingOutput() { 
      @Override 
      public void write(OutputStream os) { 
       HttpSession hs = req.getSession(false); 
       if (hs != null && story != null && story.trim().length() > 0) { 
        Integer uid = (Integer) hs.getAttribute("uid"); 
        People usr = uid != null ? PeopleDAO.findById(uid) : null; 
        if (usr != null && usr.stories != null && usr.stories.size()>0) { 
         os.write(usr.stories...); 
        } 
       } 
       os.close(); 
      } 
     }; 
    } 
} 

PeopleDAO:

public class PeopleDAO{ 
@Override 
public void save(People entity) { 
    try { 
     getEntityManager().persist(entity); 
    } catch (RuntimeException re) { 
     EntityManagerHelper.log("save failed", Level.SEVERE, re); 
     throw re; 
    } 
} 

@Override 
public void delete(People entity) { 
    try { 
     entity = getEntityManager().getReference(People.class, entity.getId()); 
     getEntityManager().remove(entity); 
    } catch (RuntimeException re) { 
     EntityManagerHelper.log("delete failed", Level.SEVERE, re); 
     throw re; 
    } 
} 

@Override 
public People update(People entity) { 
    try { 
     People result = getEntityManager().merge(entity); 
     return result; 
    } catch (RuntimeException re) { 
     EntityManagerHelper.log("update failed", Level.SEVERE, re); 
     throw re; 
    } 
} 

@Override 
public People findById(Integer id) { 
    try { 
     People instance = getEntityManager().find(People.class, id); 
     return instance; 
    } catch (RuntimeException re) { 
     EntityManagerHelper.log("find failed", Level.SEVERE, re); 
     throw re; 
    } 
} 

StoryDAO:

public class StoryDAO{ 
@Override 
public void save(Story entity) { 
    try { 
     getEntityManager().persist(entity); 
    } catch (RuntimeException re) { 
     EntityManagerHelper.log("save failed", Level.SEVERE, re); 
     throw re; 
    } 
    entity.People.stories.add(0, entity); 
} 

@Override 
public void delete(Story entity) { 
    try { 
     entity = getEntityManager().getReference(Story.class, entity.getId()); 
     getEntityManager().remove(entity); 
    } catch (RuntimeException re) { 
     EntityManagerHelper.log("delete failed", Level.SEVERE, re); 
     throw re; 
    } 
    entity.People.stories.remove(entity); 
} 

@Override 
public Story update(Story entity) { 
    try { 
     Story result = getEntityManager().merge(entity); 
     return result; 
    } catch (RuntimeException re) { 
     EntityManagerHelper.log("update failed", Level.SEVERE, re); 
     throw re; 
    } 
} 

@Override 
public Story findById(Integer id) { 
    try { 
     Story instance = getEntityManager().find(Story.class, id); 
     return instance; 
    } catch (RuntimeException re) { 
     EntityManagerHelper.log("find failed", Level.SEVERE, re); 
     throw re; 
    } 
} 

EntityManagerHelper:

public class EntityManagerHelper { 
private static final EntityManagerFactory emf; 
private static final ThreadLocal<EntityManager> threadLocal; 
private static final Logger logger; 

static { 
    emf = Persistence.createEntityManagerFactory("db"); 
    threadLocal = new ThreadLocal<EntityManager>(); 
    logger = Logger.getLogger("db"); 
    logger.setLevel(Level.ALL); 
} 

public static EntityManager getEntityManager() { 
    EntityManager manager = threadLocal.get(); 
    if (manager == null || !manager.isOpen()) { 
     manager = emf.createEntityManager(); 
     threadLocal.set(manager); 
    } 
    return manager; 
} 

public static void closeEntityManager() { 
    EntityManager em = threadLocal.get(); 
    threadLocal.set(null); 
    if (em != null) 
     em.close(); 
} 

public static void beginTransaction() { 
    getEntityManager().getTransaction().begin(); 
} 

public static void commit() { 
    getEntityManager().getTransaction().commit(); 
} 

public static void rollback() { 
    getEntityManager().getTransaction().rollback(); 
} 

public static Query createQuery(String query) { 
    return getEntityManager().createQuery(query); 
} 

Большое спасибо за любой ответ

+0

Вы можете разместить свой код DAO? –

+0

ok @Mark Robinson –

ответ

0

Вот ваша проблема

public static EntityManager getEntityManager() { 
    EntityManager manager = threadLocal.get(); 
    if (manager == null || !manager.isOpen()) { 
     manager = emf.createEntityManager(); 
     threadLocal.set(manager); 
    } 
    return manager; 
} 

EntityManager-х должны быть короткоживущие объекты. Они дешевы, чтобы их уничтожать. Это также объясняет, почему вы получаете непоследовательные результаты. У EntityManager есть внутренний кеш, который на удивление агрессивный.

Правило для работы с ЭМ составляет «Один EntityManager за транзакцию».

Измените свой код, чтобы получать новый EM каждый раз, и ваши проблемы исчезнут.

+0

Спасибо! Получать новый EM каждый раз, нет кеша объектов? Как насчет производительности? –

+0

Все кэширование выполняется во втором кэше второго уровня, который является общим для ЭМ. Как вы заметили, производительность не имеет значения, если она не работает правильно;) Но производительность будет лучше для транзакции, поскольку эти объекты предназначены для короткого замыкания и быстрой очистки. У EM будет очень непростая очистка кеша, исходя из предположения, что GC решит проблему в конце. EMF - это место, где тяжелый подъем осуществляется в JPA. –

+0

Спасибо! Я думал использовать карту, чтобы поддерживать тот же EM для того же пользователя, но слишком много работы для добавления параметра uid к каждому методу DAO. Теперь я знаю, что производительность не проблема. Но я отказался от OneToMany List, слишком много работы для сохранения сохранения/удаления в DAO. Я изменил каждый список @OneToMany на findByProperty(). –

Смежные вопросы