У меня есть две таблицы, которые связаны отношением ManyToMany.
Таблица 1 имеет временной интервал и содержит коллекцию документов, созданных в этот временной интервал.
Таблица 2 представляет собой Документы и содержит коллекцию временных интервалов, поскольку данный документ может быть изменен много раз в разных временных интервалах.
В этой конкретной программе для каждого документа я нахожу или создаю для него строку документа. Далее я нахожу или создаю временной интервал, который представляет эпоху действия, создания, обновления, удаления. Примечание: удаление - это событие, выполняемое в документе, а не в строке, которая его представляет. В этой программе нет операций удаления или удаления, выполненных для любой строки любой из таблиц.
Однако я вижу столько удалений в таблице сопоставления timeslot_document, сколько имеется вставок.
У меня такой вопрос, почему Hibernate выдает удаление? Похоже, это связано с грязной обработкой обновлений. Почему повторное удаление из временного интервала, где id = 1?
Когда у меня была OneToMany, я не видел удалений, но модель тогда была неточной (как вы можете себе представить).
Для каждого документа я определяю дату (только с точностью до часа), когда произошло действие, увеличиваю счет и добавляю документ в коллекцию.
Что-то еще любопытное - я реализую MVCC через аннотацию @Version, но в состоянии 'show innodb status \ G' я вижу таблицу заблокированной. На данный момент есть одна строка для временного интервала, в ней подсчитаны документы 1988 года, а версия строки - в 1999 году. Блокировка таблицы касается меня.
Вот основной фрагмент кода:
for (Eventlog event : eventsList) {
currentEvent = event.getEventId();
String tmp = formatter.format(event.getEpoch());
Date epoch = null;
try {
epoch = formatter.parse(tmp);
} catch (ParseException ex) {
Logger.getLogger(Converter.class.getName()).log(Level.SEVERE, null, ex);
}
cal.setTime(epoch);
Tuple tuple = holding.get(epoch);
if (tuple == null) {
tuple = new Tuple();
holding.put(epoch, tuple);
}
queryTimeSlot.setParameter("docType", docType);
queryTimeSlot.setParameter("date", epoch);
try {
ats = (TimeSlot)queryTimeSlot.getSingleResult();
insertATS = false;
} catch (Exception e) {
insertATS = true;
ats = new TimeSlot();
atsk = new TimeSlotKey();
atsk.setSlotDate(epoch);
atsk.setDocType(docType);
ats.setHour(cal.get(Calendar.HOUR_OF_DAY));
ats.setSlotKey(atsk);
}
if (processMM) {
queryDocument.setParameter("id", event.getUpdEventLogDocId());
queryDocument.setParameter("doc", docType);
try {
doc = (Document)queryDocument.getSingleResult();
insertDoc = false;
} catch (Exception e) {
doc = new Document();
docKey = new DocumentKey();
docKey.setDocid(event.getUpdEventLogDocId());
docKey.setType(docType);
doc.setDocKey(docKey);
insertDoc = true;
}
}
try {
ats.getDocuments().add(doc);
} catch (Exception e) {
Logger.getLogger(Converter.class.getName()).log(Level.SEVERE, "{0}", e);
System.exit(-1);
}
if (processMM) {
doc.getTimes().add(ats);
}
TimeSlot Entity
@Entity
@Table(name = "TimeSlot", catalog = "Analytics")
public class TimeSlot implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue
@Basic(optional=false)
@Column(name="id")
private Integer id;
@Basic(optional = false)
@Column(name = "slotKey")
private TimeSlotKey slotKey;
@Basic(optional = false)
@Column(name = "slotHour")
private int slotHour;
@Basic(optional = false)
@Column(name = "inserts")
private int inserts;
@Basic(optional = false)
@Column(name = "deletes")
private int deletes;
@Basic(optional = false)
@Column(name = "active")
private int active;
@ManyToMany(fetch=FetchType.LAZY)
@JoinColumn(name="doc_id")
private Collection<Document> documents;
@Basic(optional = false)
@Version
@Column(name = "version")
private int version;
public TimeSlot() {
documents = new ArrayList<Document>(0);
}
public Collection<Document> getDocuments() {
return documents;
}
public void setDocuments(Collection<Document>documents) {
this.documents = documents;
}
public int getHour() {
return slotHour;
}
public void setHour(int slotHour) {
this.slotHour = slotHour;
}
@Override
public int hashCode() {
int hash = 0;
hash += (slotKey != null ? slotKey.hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object object) {
if (!(object instanceof ActivityTimeSlot)) {
return false;
}
}
Документы следующие:
@Entity
@Table(name = "Documents", catalog = "Analytics")
public class Document implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue
@Basic(optional=false)
@Column(name="id")
private Integer id;
@Basic(optional = false)
@Column(name = "docKey")
private DocumentKey docKey;
@Basic(optional = false)
@Column(name = "inserts")
private int inserts;
@Basic(optional = false)
@Column(name = "deletes")
private int deletes;
@ManyToMany(fetch=FetchType.LAZY, mappedBy="")
@JoinColumn(name="slot_id")
private Collection<TimeSlot> times;
@Basic(optional = false)
@Version
@Column(name = "version")
private int version;
public Document() {
times = new ArrayList<TimeSlot>(0);
inserts = 0;
deletes = 0;
}
@Override
public int hashCode() {
return docKey.hashCode();
}
@Override
public boolean equals(Object object) {
return docKey.equals(object);
}
public int getDeletes() {
return deletes;
}
public void setDeletes(int deletes) {
this.deletes = deletes;
}
public void incrDeletes() {
deletes++;
}
public void incrInserts() {
inserts++;
}
public int getInserts() {
return inserts;
}
public void setInserts(int inserts) {
this.inserts = inserts;
}
public Pair getPair() {
return new Pair(inserts, deletes);
}
@Override
public String toString() {
return docKey.toString();
}
public Collection<ActivityTimeSlot> getTimes() {
return times;
}
public void setTimes(Collection<ActivityTimeSlot>times) {
this.times = times;
}
public DocumentKey getDocKey() {
return docKey;
}
public void setDocKey(DocumentKey docKey) {
this.docKey = docKey;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
}
Новая информация
Я через это случилось
ManyToMany предлагает удалить запись в таблице присоединения
что практически идентично. Просто я не понимаю ответ Артура. Также я заметил, что в состоянии mysql innodb он выполняет внешнее левое соединение ... это действительно необходимо?
Итак, в EntityA у меня должен быть метод add (EntityB), а в EntityB у меня должен быть метод add (EntityA) в этих методах I
public void add(EntityB entity) {
entity.getList().add(this);
getList().add(entity);
}
Я не вижу, как это функционально отличается от того, что у меня есть.