У меня есть проект spring boot (1.5.4.RELEASE) с использованием Java 8. У меня есть сущность и связанный с ней класс домена следующим образом:
@Entity
@Table(name = "Foo", schema = "dbo")
public class FooEntity implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "Id")
private int id;
@Column(name="Name")
private String name;
@Column(name="Type")
private String type;
@Column(name="Color")
private String color;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "Car")
private Car car;
//getter and setter
}
public class Foo {
private int id;
private String name;
private String type;
private String color;
private Car car;
//Constructors and getters
}
Я хочу создать репозиторий, который извлекает этот объект Foo из БД, но только извлекает сложные поля, если пользователь просит их предотвратить ненужные заявления о соединении. Репо выглядит следующим образом:
import static com.test.entities.QFooEntity.fooEntity;
import static com.test.entities.QCarEntity.carEntity;
@Repository
public class FooRepository {
private final JPAQuery<FooEntity> query = createQuery().from(fooEntity);
public FooRepository getFooByName(String name) {
query.where(fooEntity.name.eq(name));
return this;
}
public FooRepository withCar() {
query.leftJoin(fooEntity.car, carEntity).fetchJoin();
return this;
}
public Foo fetch() {
FooEntity entity = query.fetchOne();
return FooMapper.mapEntityToDomain().apply(entity);
}
}
Таким образом, вызов barebone для объекта Foo возвращает объект Entity со значениями для всех полей, за исключением поля автомобиля. Если пользователь хочет получить информацию о машине, то они должны явно называть withCar
.
Вот пример:
public class FooMapper {
public static Function<FooEntity, Foo> mapEntityToDomain() {
return entity -> {
return new Foo(e.getId(), e.getName(), e.getType(), e.getColor(), e.getCar());
};
}
}
Проблема заключается в том, что вы делаете e.getCar()
, если значение не существует (т.е. присутствует прокси). JPA выйдет и выберет его для вас. Я не хочу, чтобы это было так. Он просто захватит значения и сопоставляет их эквиваленту домена, если он там не будет null
.
Одно из решений, которое я слышал (и пыталось), вызывает em.detach(entity);
, однако это не работает так, как я думал, потому что он генерирует исключение при попытке доступа к getCar
, и я также слышал, что это не лучшая практика.
Итак, мой вопрос - это лучший способ создать репо с использованием шаблона построителя на сущности JPA и не вызвать вызов DB при попытке сопоставить.