Hibernate JPA Specification重写toPredicate多条件查询

使用手册实体类,省略了getter/setter

@Entity
@Table(name="manual")
public class Manual {
	
	@Id
	@GeneratedValue
	private Long id;
	/**
	 * 文件名称
	 */
	@Column(name="filename")
	private String fileName;

	/**
	 * 应用类型
	 */
	@JsonIgnore
	@ManyToOne(fetch=FetchType.LAZY)
	@JoinColumn(name="applicationid")
	private Application application;

使用手册实体Bean

public class ManualListBean {

	private final Manual manual;
	
	public ManualListBean(Manual manual){
		this.manual = manual;
	}
	@JsonView(DataTablesOutput.View.class)
	public Long getId(){
		return manual.getId();
	}
	@JsonView(DataTablesOutput.View.class)
	public String getFileName(){
		return manual.getFileName();
	}
	
	@JsonView(DataTablesOutput.View.class)
	public String getApplicationName(){
		Application application = manual.getApplication();
		if(application != null){
			return application.getName();
		}
		return "";
	}
}

应用类型实体类,省略了getter/setter

@Entity
@Table(name = "applicationtype")
public class ApplicationType implements java.io.Serializable{

	private static final long serialVersionUID = 899339761892494451L;

	@Id
    	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;
	
	@Column(name = "name")
	private String name;//应用名称

	@JsonIgnore
	@OneToMany(fetch=FetchType.LAZY, mappedBy="applicationType",cascade=CascadeType.ALL)
	private Set<InstructionManual> instructionManualSet = new HashSet<>();
Bean
public class ApplicationListBean extends DataTableBean<Application>{
	@JsonView(DataTablesOutput.View.class)
	public Long getId() {
		return target.getId();
	}
	
	@JsonView(DataTablesOutput.View.class)
	public String getName() {
		return target.getName();
	}

}
ManualController

	@JsonView(DataTablesOutput.View.class)
	@RequestMapping(value="/manualList.json",method=RequestMethod.POST)
	@ResponseBody
	public DataTablesOutput<ManualListBean> manualList(@Valid DataTablesInput input, HttpServletRequest request){
		Test test = (Test) request.getSession().getAttribute("test");
		List<Application> applications = applicationService.findByApplication(test);
		final Set<Application> applicationSet = new HashSet<>(applications);
		final String name = ".xxx";
		Specification<Manual> additionalSpecification = new Specification<Manual>() {
			@Override
			public Predicate toPredicate(Root<Manual> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				if(applicationSet.size()>0){
					List<Predicate> predicateList = new ArrayList<>();
					Iterator<Application> iterator = applicationSet.iterator();
					while(iterator.hasNext()){ 
						Application application = iterator.next();
						Predicate p1 = cb.equal(root.<Application>get("application"), application);
						predicateList.add(p1);	
					}
					Predicate[] pre = new Predicate[predicateList.size()];
					query.where(predicateList.toArray(pre));
				}else{
					Predicate p1 = cb.equal(root.<String>get("filename"), name);
					query.where(p1);
				}
				return query.getRestriction(); 
			}
		};
		DataTablesOutput<Manual> manualOutput = this.manualService.findAll(input, additionalSpecification);
		DataTablesOutput<ManualListBean> output = new DataTablesOutput<>();
		output.setDraw(manualOutput.getDraw());
		output.setError(manualOutput.getError());
		output.setRecordsFiltered(manualOutput.getRecordsFiltered());
		output.setRecordsTotal(manualOutput.getRecordsTotal());
		List<ManualListBean> listData = new ArrayList<>();
		for (Manual manual : manualOutput.getData()) {
			ManualListBean manualListBean = new ManualListBean(manual);
			listData.add(manualListBean);
		}
		output.setData(listData);
		return output;
	}
	
前端
$(function() {
	$('#form').DataTable({
		serverSide : true,
		destroy : true,
		ajax : {
			url : ctx + '/manual/manualList.json',
			type : "post"
		},
		columns : [
		           {"data" : "id"},
		           {"data" : "fileName"},
		           {"data" : "application.name"},
		           {"data" : "id"}
		],
		columnDefs : [{
		            	    width : '11%',
			       			render : function(data, type, row) {
			       				return data;
			       			},
			       			targets: [0,1]
		               },
		               {
			                width: '20%',
			                render: function (data, type, row) {
			                    return row.applicationName;
			                },
			                targets: [2]
			           },
		               {
			width : '20%',
			render : function(data, type, row) {
			if (data) {var html = '<ul class="icons-list"><li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown">'
			+ '<i class="icon-menu9"></i></a>'
			+ '<ul class="dropdown-menu dropdown-menu-right">'
											
			+ '<li><a href="'+ ctx + '/manual/update/'+ data+ '"><i class="icon-diff-modified"></i>操作</a></li>'
											
			+ '</ul></li></ul>';
									return html;
								} else {
									return '';
								};
							},
							targets : 3,
						}]

	});
});
参考:http://www.knowsky.com/988841.html






### 回答1: JPA Specification是一种用于构建动态查询的API,可以用于多表查询。通过使用Specification,可以根据不同的查询条件动态地构建查询语句,从而实现多表查询。在多表查询中,需要使用Join操作将多个表连接起来,然后根据查询条件进行过滤和排序。使用JPA Specification可以方便地构建这样的查询语句,从而提高查询效率和灵活性。 ### 回答2: JPA Specification是一种规范,允许我们在不暴露数据访问层的情况下执行动态查询。当需要在多张表中查询数据时,JPA Specification同样适用。在多表查询时,我们可以使用Join方式连接多张表。 一个简单的例子是,我们需要根据用户和订单表查询某个用户的订单记录。我们可以使用JPA Specification的Join方法把用户表和订单表连接起来,然后通过where条件来限定用户ID。具体代码如下: ```java public static Specification<Order> findByUserId(Long userId) { return (root, query, cb) -> { Join<Order, User> userJoin = root.join("user", JoinType.LEFT); //建立join关系 return cb.equal(userJoin.get("id"), userId); //指定where条件 }; } ``` 以上代码中,我们通过root.join方法建立了user表和order表的Join关系,然后通过cb.equal方法指定了where条件,即查询用户ID等于指定ID的订单记录。 除此之外,我们还可以进行多表嵌套查询,如查询一个用户的所有订单信息和订单的商品信息。这时,我们需要建立三张表之间的Join关系,并指定查询条件。具体代码如下: ```java public static Specification<Order> findUserOrderWithProduct(Long userId) { return (root, query, cb) -> { Join<Order, User> userJoin = root.join("user", JoinType.LEFT); //建立user表和order表的Join关系 Join<Order, Product> productJoin = root.join("product", JoinType.LEFT); //建立product表和order表的Join关系 query.distinct(true); //去重 return cb.and( cb.equal(userJoin.get("id"), userId), //指定用户ID cb.equal(root.get("status"), Order.Status.COMPLETED), //指定订单状态 cb.equal(productJoin.get("onSale"), true)); //指定商品在售 }; } ``` 以上代码中,我们建立了user表、order表和product表之间的Join关系,并指定了查询条件,即查询某个用户已经完成的订单,并且订单中包含在售商品。注意,我们还使用了query.distinct(true)方法对结果去重。 综上所述,JPA Specification在多表查询时同样适用。我们只需要使用Join方法建立表之间的关联,然后通过where条件指定查询条件即可。如果需要进行多表嵌套查询,则需要在查询条件中同时指定多张表的信息。 ### 回答3: JPA是Java Persistence API的缩写,是Java EE用于管理数据库相关的Java API。JPA Specification则是JPA的规范,它定义了一种标准的Java编程接口,用于实现ORM(对象关系映射)。 多表查询是数据库中常见的查询操作之一,它通过同时查询多个表来获取更多的数据。在JPA中,多表查询可以通过使用JPA Specification来实现。JPA Specification提供了一种标准的API,用于动态构建查询语句,使查询操作更加灵活和可扩展。 在JPA Specification中,可以通过CriteriaQuery和Predicate来实现多表查询。CriteriaQuery是一个查询对象,表示一个查询操作,并在其中定义查询的根实体和查询的列。Predicate则是一个查询条件,用于过滤查询结果。通过将多个Predicate组合在一起,就可以实现复杂的查询条件。 在进行多表查询时,需要先定义多个实体类,并将它们之间的关系映射到数据库中。通过JPA提供的注解,可以将实体类中的字段映射到数据库中的对应列,并定义实体类之间的关联关系。在查询时,就可以通过这些关联关系来进行多表连接查询。 除了使用CriteriaQuery和Predicate进行多表查询外,JPA还提供了JPQL(Java Persistence Query Language)和Native SQL两种查询方式。JPQL类似于SQL,但使用面向对象的语法来查询实体类,更加灵活和方便。Native SQL则直接使用SQL语句来查询数据库,可以处理更复杂的查询操作,但需要手动处理结果集。 在使用JPA Specification进行多表查询时,需要注意查询性能和代码可维护性。多表查询往往会涉及到大量数据,需要合理地设计查询语句和索引,避免出现性能问题。同时,需要确保代码的可读性和可维护性,避免出现过于复杂的查询语句和逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值