Сравнительный тест, данный GHad, измеряет много другого материала (такого как отражение, инстанцируя объектов, и т.д.) помимо получения длины. Если мы пытаемся избавиться от этих вещей тогда для одного вызова, я добираюсь следующие разы в микросекундах:
file sum___19.0, per Iteration___19.0 raf sum___16.0, per Iteration___16.0 channel sum__273.0, per Iteration__273.0
Для 100 выполнений и 10 000 повторений я добираюсь:
file sum__1767629.0, per Iteration__1.7676290000000001 raf sum___881284.0, per Iteration__0.8812840000000001 channel sum___414286.0, per Iteration__0.414286
я действительно выполнял следующий измененный код, дающий как аргумент название файла 100 МБ.
import java.io.*;
import java.nio.channels.*;
import java.net.*;
import java.util.*;
public class FileSizeBench {
private static File file;
private static FileChannel channel;
private static RandomAccessFile raf;
public static void main(String[] args) throws Exception {
int runs = 1;
int iterations = 1;
file = new File(args[0]);
channel = new FileInputStream(args[0]).getChannel();
raf = new RandomAccessFile(args[0], "r");
HashMap<String, Double> times = new HashMap<String, Double>();
times.put("file", 0.0);
times.put("channel", 0.0);
times.put("raf", 0.0);
long start;
for (int i = 0; i < runs; ++i) {
long l = file.length();
start = System.nanoTime();
for (int j = 0; j < iterations; ++j)
if (l != file.length()) throw new Exception();
times.put("file", times.get("file") + System.nanoTime() - start);
start = System.nanoTime();
for (int j = 0; j < iterations; ++j)
if (l != channel.size()) throw new Exception();
times.put("channel", times.get("channel") + System.nanoTime() - start);
start = System.nanoTime();
for (int j = 0; j < iterations; ++j)
if (l != raf.length()) throw new Exception();
times.put("raf", times.get("raf") + System.nanoTime() - start);
}
for (Map.Entry<String, Double> entry : times.entrySet()) {
System.out.println(
entry.getKey() + " sum: " + 1e-3 * entry.getValue() +
", per Iteration: " + (1e-3 * entry.getValue() / runs / iterations));
}
}
}
Ненавижу говорить вам это, но у вас здесь двусторонние отношения. Человек ссылается на Сердце и Печень, и каждый из них имеет обратную ссылку на Человека. Аннотации, которые вы настроили для свойств Id ваших Heart и Liver, конкретно говорят о том, что они получают значение своего свойства Id, делегируя его свойству Person. В показанных вами примерах, которые не работают, вы еще не установили свойство Person для этих парней, и поэтому они, очевидно, не могут получить значение своего идентификатора.
Вы можете установить это отношение как истинное. однонаправленный OneToOne, который задокументирован в документации аннотаций Hibernate:
@Entity
public class Body {
@Id
public Long getId() { return id; }
@OneToOne(cascade = CascadeType.ALL)
@PrimaryKeyJoinColumn
public Heart getHeart() {
return heart;
}
...
}
@Entity
public class Heart {
@Id
public Long getId() { ...}
}
, или вы можете немного изменить наши объекты сущностей, чтобы упростить подключение обеих сторон отношения, например:
@Entity
public class Person {
public long personId;
private String name;
public Heart heart;
public Liver liver;
// other fields
@Id
@GeneratedValue
public long getPersonId() {return personId;}
@OneToOne(cascade = CascadeType.ALL)
@PrimaryKeyJoinColumn
public Heart getHeart() {return heart;}
public void setHeart(Heart heart){
this.heart = heart;
this.heart.setPerson(this);
}
@OneToOne(cascade = CascadeType.ALL)
@PrimaryKeyJoinColumn
public Liver getLiver() {return liver;}
public void setLiver(Liver liver){
this.liver = liver;
this.liver.setPerson(this);
}
// other getters and setters and constructors
}
Я не пробовал, но могу сказать, что ....
Разница между обеими сторонами в том, что у класса Person
нет mappedBy
в его отображении.
Итак, для каждого One-To-One, Person
имеет эталонное значение, которое Hibernate считает официальным. Напротив, для других объектов mappedBy
указывает Hibernate не использовать значение, а перейти к этому объекту и рассмотреть сопоставленное свойство этого объекта.
Чтобы проверить, я правильно, вы можете установить только те значения, которые не имеют mappedBy
, и сохранить объект Person
(потому что это тот, который имеет каскады), и посмотреть, верен ли результат. .; -)