jpa vue管理系统_Hibernate中的JPA 2.1条件删除/更新和临时表

jpa vue管理系统

jpa vue管理系统

从JPA 2.0版开始, EntityManager提供了getCriteriaBuilder()方法来动态构建选择查询,而无需使用Java Persistence Query Languge(JPQL)进行字符串连接。 在2.1版中,此CriteriaBuilder提供了两个新方法createCriteriaDelete()createCriteriaUpdate() ,使我们可以使用条件API制定删除和更新查询的方法。

出于说明目的,让我们对两个实体PersonGeek使用简单的继承用例:

@Entity
@Table(name = "T_PERSON")
@Inheritance(strategy = InheritanceType.JOINED)
public class Person {
	@Id
	@GeneratedValue
	private Long id;
	@Column(name = "FIRST_NAME")
	private String firstName;
	@Column(name = "LAST_NAME")
	private String lastName;
	...
}

@Entity
@Table(name = "T_GEEK")
@Access(AccessType.PROPERTY)
public class Geek extends Person {
	private String favouriteProgrammingLanguage;
	...
}

要从我们的数据库中删除所有喜欢Java作为其编程语言的怪胎,我们可以使用EntityManager的新createCriteriaDelete()方法利用以下代码:

EntityTransaction transaction = null;
try {
	transaction = entityManager.getTransaction();
	transaction.begin();
	CriteriaBuilder builder = entityManager.getCriteriaBuilder();
	CriteriaDelete<Geek> delete = builder.createCriteriaDelete(Geek.class);
	Root<Geek> geekRoot = delete.from(Geek.class);
	delete.where(builder.equal(geekRoot.get("favouriteProgrammingLanguage"), "Java"));
	int numberOfRowsUpdated = entityManager.createQuery(delete).executeUpdate();
	LOGGER.info("Deleted " + numberOfRowsUpdated + " rows.");
	transaction.commit();
} catch (Exception e) {
	if (transaction != null && transaction.isActive()) {
		transaction.rollback();
	}
}

与纯SQL一样,我们可以使用from()方法来指定要针对其发出删除查询的表,并可以使用where()来声明谓词。 通过这种方式,标准API允许以动态方式定义批量删除操作,而无需使用过多的字符串连接。

但是,SQL是如何创建的呢? 首先,ORM提供程序必须注意,我们正在使用策略JOINED从继承层次结构中删除,这意味着我们有两个表T_PERSONT_GEEK ,其中第二个表存储对父表的引用。 Hibernate版本4.3.8.Final创建以下SQL语句:

insert 
into
	HT_T_GEEK
	select
		geek0_.id as id 
	from
		T_GEEK geek0_ 
	inner join
		T_PERSON geek0_1_ 
			on geek0_.id=geek0_1_.id 
	where
		geek0_.FAV_PROG_LANG=?;

delete 
from
	T_GEEK 
where
	(
		id
	) IN (
		select
			id 
		from
			HT_T_GEEK
	);

delete 
from
	T_PERSON 
where
	(
		id
	) IN (
		select
			id 
		from
			HT_T_GEEK
	)

delete 
from
	HT_T_GEEK;

如我们所见,Hibernate使用与我们的搜索条件匹配的极客/人员的ID填充了一个临时表。 然后,它从极客表中删除所有行,然后从人员表中删除所有行。 最后,临时表被清除。

删除语句的顺序很明确,因为表T_GEEKT_PERSON表的id列上具有外键约束。 因此,子表中的行必须在父表中的行之前删除。 本文介绍了Hibernate创建临时表的原因。 概括起来,潜在的问题是查询限制了仅在子表中存在的列上要删除的行。 但是子表中的行必须在父表中的相应行之前删除。 删除了子表中的行(即,所有具有FAV_PROG_LANG='Java'的怪胎)之后,由于已经删除了怪胎行,因此无法随后删除所有对应的人员。 解决该问题的方法是临时表,该临时表首先收集应删除的所有行ID。 知道所有ID后,可以使用此信息先从怪胎表中删除行,然后再从人员表中删除行。

上面生成SQL语句当然与标准API的用法无关。 使用JPQL方法会导致生成相同SQL:

EntityTransaction transaction = null;
try {
	transaction = entityManager.getTransaction();
	transaction.begin();
	int update = entityManager.createQuery("delete from Geek g where g.favouriteProgrammingLanguage = :lang").setParameter("lang", "Java").executeUpdate();
	LOGGER.info("Deleted " + update + " rows.");
	transaction.commit();
} catch (Exception e) {
	if (transaction != null && transaction.isActive()) {
		transaction.rollback();
	}
}

当我们将继承策略从JOINED更改为SINGLE_TABLE ,生成SQL语句也更改为单个(此处的鉴别DTYPE列为DTYPE ):

delete 
from
	T_PERSON 
where
	DTYPE='Geek' 
	and FAV_PROG_LANG=?

结论

用于删除和更新的标准API的新增功能使您可以构造SQL语句,而无需任何字符串连接。 但是请注意,从继承层次结构中进行批量删除可能会强制基础ORM使用临时表,以便组装必须事先删除的行列表。

翻译自: https://www.javacodegeeks.com/2015/02/jpa-2-1-criteria-deleteupdate-temporary-tables-hibernate.html

jpa vue管理系统

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值