在我们正在开发的这个应用程序中,我们注意到一个视图特别慢.我分析了视图并注意到hibernate执行了一个查询,即使数据库中只有两个对象要获取,也需要10秒.所有OneToMany和ManyToMany关系都是懒惰的,所以这不是问题.在检查正在执行的SQL时,我注意到查询中有超过80个连接.
进一步检查这个问题,我注意到问题是由实体类的深层次结构OneToOne和ManyToOne关系引起的.所以,我想,我只是让他们变得懒惰,这应该解决问题.但是,无论是标注@OneToOne(fetch=FetchType.LAZY)或@ManyToOne(fetch=FetchType.LAZY)似乎不工作.我得到一个异常,或者它们实际上并没有被代理对象替换,因此是懒惰的.
任何想法我将如何让这个工作?请注意,我不使用persistence.xml定义关系或配置细节,一切都在java代码中完成.
我有2张桌子:Order [OrderId(PK), OrderShipmentCode, ...]和Shipment[ShipmentId(PK), ShipmentCode, ...].
在Order课堂上,我声明shipment了如下字段:
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "OrderShipmentCode", referencedColumnName = "ShipmentCode", insertable = false, updatable = false, nullable = false)
private Shipment shipment;
Run Code Online (Sandbox Code Playgroud)
当我得到列表时Order,Shipment也会加载(我看到很多单独的SELECT查询).但是我希望它Shipment是懒惰的,而不是与它一起提取Order.
对于其他表,如果引用的列是主键,则结果与预期一致(使用延迟加载).在我的情况下,ShipmentCode不是Shipment表的主键,并且Hibernate不使用延迟加载.
你能告诉我如何实现这个目标吗?
编辑: 查询代码如下:
Criteria criteria = HibernateUtil.getSessionFactory().getCurrentSession().createCriteria(Order.class);
List result = criteria.list();
Run Code Online (Sandbox Code Playgroud)
SQL查询是:1 Order表的SELECT语句和一堆SELECT语句Shipment
我有2个班:司机和汽车.汽车表在单独的过程中更新.我需要的是在驱动程序中拥有属性,允许我读取完整的汽车描述并只写入指向现有汽车的Id.这是一个例子:
@Entity(name = "DRIVER")
public class Driver {
... ID and other properties for Driver goes here .....
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name = "CAR_ID")
private Car car;
@JsonView({Views.Full.class})
public Car getCar() {
return car;
}
@JsonView({Views.Short.class})
public long getCarId() {
return car.getId();
}
public void setCarId(long carId) {
this.car = new Car (carId);
}
}
Run Code Online (Sandbox Code Playgroud)
Car对象只是典型的JPA对象,没有对Driver的反向引用.
所以我试图通过这个实现:1)我可以使用详细的JSON View 2)阅读完整的汽车描述或者我只能阅读简短的JsonView 3中的汽车ID而且最重要的是,当创建新的驱动程序我只是想要传递汽车的JSON ID.这样我就不需要在持久化期间为汽车执行不必要的读取操作,而只是更新Id.
我得到以下错误:"对象引用未保存的瞬态实例 - 在刷新之前保存瞬态实例:com.Driver.car - > com.Car"
我不想在DB中更新Car的实例,而只是从Driver中引用它.知道怎么做到我想要的吗?
谢谢.
更新:忘记提及我在创建驱动程序期间传递的汽车ID是DB中现有汽车的有效ID.
我有一些麻烦要让@ManyToOne关联加载lazilly.我正在使用fetch = LAZY但是当主键列没有进行连接时它不起作用.
我知道这个问题已被提出但我认为没有得到妥善回答,因此我提供了详细信息以澄清问题.
这是我的模特:
DummyB -> DummyA
Run Code Online (Sandbox Code Playgroud)
这些是表格:
create table dummyA (
id number(18,0), --pk
name varchar2(20) -- unique field
);
create table dummyB (
id number(18,0),
dummya_id number(18,0),
dummya_name varchar2(20)
);
Run Code Online (Sandbox Code Playgroud)
这些是实体:
@Entity
public class DummyA implements Serializable {
private Long id;
private String name;
@Id
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = …Run Code Online (Sandbox Code Playgroud) 看来@Basicjava变量上的注释只声明该变量必须保存为具有NOT NULL约束的列.那是对的吗 ?
这篇文章说的@Basic(optional = false) @Column(nullable = false) The @Basic annotation marks the property as not optional on the Java object level. The second setting, nullable = false on the column mapping, is only responsible for the generation of a NOT NULL database constraint. The Hibernate JPA implementation treats both options the same way in any case, so you may as well use only one of the annotations for this purpose.
我很迷惑.这意味着什么 - The …
在遗留系统中,我们有1个表(实体)和1个视图(UserDetail),没有约束但有关系.
Entity
| Id | Desc | Created_By |...
UserDetail
| UserId | F_Name | L_Name |...
Run Code Online (Sandbox Code Playgroud)
CreatedBy具有创建该实体的用户的用户标识.我们在Entity.java中有一个单向映射,如下所示.
@OneToOne
@JoinColumn(name = "CREATED_BY", referencedColumnName = "USER_ID")
private UserDetail createdBy;
Run Code Online (Sandbox Code Playgroud)
问题
但由于它是一个遗留系统,我们无法控制它并且用户被硬删除.
调用entityReposity.findAll时,将引发以下错误
org.springframework.orm.jpa.JpaObjectRetrievalFailureException: Unable to find com...UserDetail with id 92237; nested exception is javax.persistence.EntityNotFoundException: Unable to find com...UserDetail with id 92237
Run Code Online (Sandbox Code Playgroud)
题
如何让JPA认为这种关联是可选的,或者在JPA中有什么方法可以忽略它(比如Hibernate中的@NotFound)?
试着
@NotFound有效,但我们需要将@OneToOne破解为@ManyToOne.我们还想要一个独立于实现的解决方 注意到这个错误,https://hibernate.atlassian.net/browse/ANN-725
optional = true - 如果这可以按照它应该如何表现的语法含义工作,我就不会写这个.
还尝试了UserDetails.java中的postLoad().
@PostLoad解决方案我们有一个异常的异常处理程序,并且在调用Entity类中的@PostLoad之前会捕获异常.
在Entity.java中
@PostLoad
public void postLoad(){
try {
System.out.println(this.getCreatedBy()); //Before control comes here, it goes to aop …Run Code Online (Sandbox Code Playgroud) 我有一个巨大的实体,我想加载它的子集(ID和baz属性):
@Entity
public class GiganticEntity {
@Id Long id;
@OneToOne(mappedBy = "giganticEntity")
Foo foo;
@OneToOne(mappedBy = "giganticEntity")
Bar bar;
@OneToOne(mappedBy = "giganticEntity")
Baz baz;
// default constructor + getters/setters
public GiganticEntity(Long id, Baz baz) {
this.id = id;
this.baz = baz;
}
}
Run Code Online (Sandbox Code Playgroud)
我尝试使用以下JPA查询,但是baz属性将为null:
"SELECT new package.GiganticEntity(ge.id, ge.baz) " +
"FROM GiganticEntity ge WHERE ge.id = 1";
Run Code Online (Sandbox Code Playgroud)
我尝试添加一个显式连接,但它也导致了null:
"SELECT new package.GiganticEntity(ge.id, b) FROM GiganticEntity ge " +
"LEFT JOIN ge.baz as b " +
"WHERE ge.id = 1";
Run Code Online (Sandbox Code Playgroud)
如果我只选择这样一个巨大的实体,那么一切正常(但我试图保存一些连接):
"SELECT …Run Code Online (Sandbox Code Playgroud) 这类似于带有继承的 JPA 映射视图和表,但由于接受的答案不能满足我,我决定提出自己的问题。
我有一个基础类,它包含所有实体的公共字段
@MappedSuperclass
@Access(AccessType.FIELD)
public abstract class CommonFields{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
protected Long id;
(...)
}
Run Code Online (Sandbox Code Playgroud)
假设我有一个名为 Table 的实体
@Entity
@Table(name = "my_table")
public class Table extends CommonFields{
(..)
}
Run Code Online (Sandbox Code Playgroud)
这对我来说非常有效。我创建了视图,它将一列添加到my_table. 我是这样映射的:
@Immutable
@Entity
@Table(name = "my_table_plus_view")
public class TableView extends Table{
(..)
}
Run Code Online (Sandbox Code Playgroud)
TableView是只读的。这很简单Table带有用于演示目的的附加信息。
此应用程序在 Tomcat 和 Postgres DB 上运行。服务器启动时没有错误,但是当我尝试从视图中获取所有记录时,我收到一个错误,即我的Table不包含DTYPE列。我知道它是什么以及它是如何工作的,但因为我不需要它,所以我不想要它。
我想像Table现在一样读/写我的,但我不知道如何映射我的TableViewJPA 查询可以使用它。我做了一些努力,InheritanceType但没有成功。如果我从Tableto复制所有字段,TableView那么我的应用程序将按预期运行,但这不适合我。如何映射我的视图以便我可以使用继承?
我正在使用这种方法从我的DAO中的数据库中检索一些数据:
@Override
@Transactional
public List<History> findLastHistoriesByCount(int gHistoriesCount) {
List<History> result = new ArrayList<History>();
result = entityManager
.createQuery(
"SELECT h FROM History h ORDER BY h.eventDate DESC",
History.class).setMaxResults(gHistoriesCount).getResultList();
return result;
}
Run Code Online (Sandbox Code Playgroud)
这是我的历史课:
public class History implements Serializable {
...
@ManyToOne
@JoinColumn(name = "ID_CONTRACT_HISTORY", nullable = true)
private ContractHistory contractHistory;
@ManyToOne
@JoinColumn(name = "ID_SALARY_HISTORY", nullable = true)
private SalaryHistory salaryHistory;
...
}
Run Code Online (Sandbox Code Playgroud)
但我面临着这个例外:
javax.persistence.EntityNotFoundException:无法找到ID为108的com.xxx.model.ContractHistory
虽然我确定我在表ContractHistory的数据库中有该行
编辑
我已经看过带有@NotFound注释的解决方案了,我不想要它,因为它对我来说只是一个旁路,因为我的数据在那里!我想撤退。
编辑2 ** ContractHistory:**
public class ContractHistory extends implements Serializable {
private static final …Run Code Online (Sandbox Code Playgroud) hibernate ×9
jpa ×9
java ×7
one-to-one ×2
lazy-loading ×1
many-to-one ×1
mapping ×1
mysql ×1
oracle11g ×1
orm ×1
view ×1