2016-06-13 3 views
1

У меня возникла проблема, когда я обновляю модель в ebean, но другие ссылки на модель не меняются. Мне было интересно, можно ли автоматически обновлять или обновлять любые модели, которые ссылаются на обновленную модель, используя объединенные столбцы или сопоставления @ManyToMany.Как обновить все ссылки в ebean orm

Это мой тестовый код:

// Create students and club 
Student john = new Student("John"); 
Student lizz = new Student("Lizz"); 
Club soccer = new Club("Soccer"); 

// Save the students 
server.save(john); 
server.save(lizz); 

// Add them to their club 
john.getClubs().add(soccer); 
server.save(john); 
lizz.getClubs().add(soccer); 
server.save(lizz); 

// Reload users (fresh) 
john = server.find(Student.class).where().ieq("name", "john").findUnique(); 
lizz = server.find(Student.class).where().ieq("name", "lizz").findUnique(); 
System.out.println("Club: " + lizz.getClubs().get(0).getName()); 

// Modify the club name 
john.getClubs().get(0).setName("Baseball"); 
System.out.println("Club: " + lizz.getClubs().get(0).getName()); 

// Update the club 
server.save(john); 
System.out.println("Club: " + lizz.getClubs().get(0).getName()); 

и это мои модели:

@Entity 
@Table(name = "students") 
public class Student { 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Column(unique = true, updatable = false) 
    private int id; 

    @Column 
    private String name; 

    @ManyToMany(mappedBy = "students", cascade = CascadeType.ALL) 
    private List<Club> clubs; 

    @Version 
    private long version; 
} 

и:

@Entity 
@Table(name = "clubs") 
public class Club { 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Column(unique = true, updatable = false) 
    private int id; 

    @Column 
    private String name; 

    @ManyToMany 
    @JoinColumn 
    private List<Student> students; 

    @Version 
    private long version; 
} 

Выход в том, что клуб остается футбол, как и :
Клуб: футбол
Клуб: Футбол
Клуб: Футбол

+0

Когда код перезагружает john и lizz ... поскольку нет контекста транзакции/персистентности ... это создает 2 независимых графа объектов. Эти графические объекты представляют собой «моментальный снимок части базы данных в определенный момент времени и на определенном уровне изоляции (чтение выполняется по умолчанию в соответствии со спецификацией JPA и т. Д.). –

+0

@RobBygrave, что имеет смысл, я устанавливаю уровень изоляции SERIALIZABLE, потому что он поддерживает как SQLite, так и MySQL, а некоторые другие не поддерживают . Можно ли всегда поддерживать одну и ту же ссылку? – lenis0012

+0

В SERIALIZABLE Оптимистическая проверка параллелизма не работает (ну, проверка относится к началу транзакции). В общем, вам нужно начать использовать пессимистическую блокировку в SERIALIZABLE. Для приложения с высоким уровнем параллелизма это проблема. Поэтому READ_COMMITTED - это намного лучший выбор. Если ... –

ответ

2

Вы модифицируете John, но печатаете Lizz. Лизз не изменился (в том, что клуб для Lizz был загружен и он не обновился).

Причина в том, что выборка Джона и Лизда выполняется в двух разных транзакциях и как таковые имеют два разных контекста постоянства.

Если произошла транзакция, охватывающая выбор BOTH John и Lizz, тогда Клуб был бы одним и тем же/единственным экземпляром для обоих, поскольку основной контекст сохранения привязан к транзакции и гарантирует, что они используют один и тот же экземпляр для Клуба ,

В качестве отправной точки на стороне, вы должны смотреть на включение SQL и журнала транзакций таким образом, что вы подтвердите это то, что вы думаете, он должен:

<!-- LOGBACK configuration --> 

<!-- SQL and bind values --> 
<logger name="org.avaje.ebean.SQL" level="TRACE"/> 

<!-- Transaction Commit and Rollback events --> 
<logger name="org.avaje.ebean.TXN" level="TRACE"/> 

Для настройки журналирования см http://ebean-orm.github.io/docs/setup/logging

Do:

server.beginTransaction(); 
try { 
    // persistence context scoped to transaction so 
    // .. now spans both fetches giving John and Lizz 
    // .. the same shared Club instance 
    john = server.find(Student.class).where().ieq("name", "john").findUnique(); 
    lizz = server.find(Student.class).where().ieq("name", "lizz").findUnique(); 
} finally { 
    server.endTransaction(); 
} 
+0

спасибо, что это очень полезно. Однако на практике я бы не загружал их одновременно. Но я хотел бы изменить клуб для одного студента, не имея всех клубов в непоследовательности. – lenis0012

+0

См. Другое обсуждение выше. –

+0

FYI: есть видео, в котором обсуждается «Контекст сохранения» Эсэ на https://youtu.be/Y18HsBkeLuk ... сравнивая его с JPA и, надеюсь, объясняя немного больше, почему это работает так. –