Проверьте, ли векторное произведение из (b-a) и (c-a) 0, как говорит Darius Bacon, говорит Вам, если точки a, b и c выровненные.
, Но, поскольку Вы хотите знать, ли c между a и b, также необходимо проверить, что скалярное произведение из (b-a) и (c-a) положительно и меньше , чем квадрат расстояния между a и b.
В неоптимизированном псевдокоде:
def isBetween(a, b, c):
crossproduct = (c.y - a.y) * (b.x - a.x) - (c.x - a.x) * (b.y - a.y)
# compare versus epsilon for floating point values, or != 0 if using integers
if abs(crossproduct) > epsilon:
return False
dotproduct = (c.x - a.x) * (b.x - a.x) + (c.y - a.y)*(b.y - a.y)
if dotproduct < 0:
return False
squaredlengthba = (b.x - a.x)*(b.x - a.x) + (b.y - a.y)*(b.y - a.y)
if dotproduct > squaredlengthba:
return False
return True
Когда у вас есть коллекция на основе списка или набора и вы добавляете новый объект в свою коллекцию, Hibernate всегда будет попадать в базу данных, потому что он сравнивает один за другим объекты с использованием реализации равенства перед сохранением или обновление - при использовании Set - или путем сравнения столбца индекса при использовании List. Такое поведение необходимо из-за семантики Set и List. Из-за этого производительность вашего приложения может значительно снизиться, если у вас есть несколько записей.
Некоторые способы решения этой проблемы
1º Шаблон преобразования с использованием инкапсулированной коллекции Bag плюс желаемый набор или список предоставляется как свойство
@Entity
public class One {
private Collection<Many> manyCollection = new ArrayList<Many>();
@Transient
public Set<Many> getManyCollectionAsSet() { return new HashSet<Many>(manyCollection); }
public void setManyCollectionAsSet(Set<Many> manySet) { manyCollection = new ArrayList<Many>(manySet); }
/**
* Keep in mind that, unlike Hibernate, JPA specification does not allow private visibility. You should use public or protected instead
*/
@OneToMany(cascade=ALL)
private Collection<Many> getManyCollection() { return manyCollection; }
private void setManyCollection(Collection<Many> manyCollection) { this.manyCollection = manyCollection; }
}
2º Использовать ManyToOne вместо OneToMany
@Entity
public class One {
/**
* Neither cascade nor reference
*/
}
@Entity
public class Many {
private One one;
@ManyToOne(cascade=ALL)
public One getOne() { return one; }
public void setOne(One one) { this.one = one }
}
3º Кэширование - когда применяется, в зависимости от ваших требований, ваша конфигурация может увеличить или уменьшить производительность вашего приложения. См. здесь
4 ° Ограничение SQL - если вам нужна коллекция, которая ведет себя как Set, вы можете использовать ограничение SQL, которое можно применить к столбцу или набору столбцов ]. См. здесь
Обычно я делаю это, определяя коллекцию как «инверсную».
Это примерно означает: первичное определение ассоциации 1-N делается на конце «N». Если вы хотите добавить что-то в коллекцию, вы изменяете связанный объект подробных данных.
Небольшой пример XML:
<class name="common.hibernate.Person" table="person">
<id name="id" type="long" column="PERSON_ID">
<generator class="assigned"/>
</id>
<property name="name"/>
<bag name="addresses" inverse="true">
<key column="PERSON_ID"/>
<one-to-many class="common.hibernate.Address"/>
</bag>
</class>
<class name="common.hibernate.Address" table="ADDRESS">
<id name="id" column="ADDRESS_ID"/>
<property name="street"/>
<many-to-one name="person" column="PERSON_ID"/>
</class>
, тогда обновление выполняется исключительно в Address:
Address a = ...;
a.setPerson(me);
a.setStreet("abc");
Session s = ...;
s.save(a);
Done. Вы даже коллекцию не трогали. Считайте его доступным только для чтения, что может быть очень практичным для запросов с HQL, а также для его повторения и отображения.
Если я хорошо понимаю вашу потребность:
Рассматривали ли вы сохранение вашей коллекции отключенной ?