1. Specifications动态查询
1.1 dao接口实现的JpaSpecificationExecutor中有哪些方法
import java.util.List;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
/**
* JpaSpecificationExecutor中定义的方法
**/
public interface JpaSpecificationExecutor<T> {
//根据条件查询一个对象
T findOne(Specification<T> spec);
//根据条件查询集合
List<T> findAll(Specification<T> spec);
//根据条件分页查询
Page<T> findAll(Specification<T> spec, Pageable pageable);
//排序查询查询
List<T> findAll(Specification<T> spec, Sort sort);
//统计查询
long count(Specification<T> spec);
}
可以看到Specification是个很重要的参数,可以理解为查询条件
1.2 demo
//依赖注入customerDao
@Autowired
private CustomerDao customerDao;
@Test
public void testSpecifications() {
//使用匿名内部类的方式,创建一个Specification的实现类,并实现toPredicate方法
Specification <Customer> spec = new Specification<Customer>() {
// Specification中只有这一个方法
public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
//root:从实体Customer对象中按照custName属性进行查询
//cb:构建查询,添加查询方式
return cb.like(root.get("custName").as(String.class), "jerry%");
}
};
Customer customer = customerDao.findOne(spec);
System.out.println(customer);
}
1.3 分页查询
@Test
public void testPage() {
//构造查询条件
Specification<Customer> spec = new Specification<Customer>() {
public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
return cb.like(root.get("custName").as(String.class), "jerry%");
}
};
/**
* 构造分页参数
* Pageable : 接口
* PageRequest实现了Pageable接口,调用构造方法的形式构造
* 第一个参数:页码(从0开始)
* 第二个参数:每页查询条数
*/
Pageable pageable = new PageRequest(0, 5);
/**
* 分页查询,封装为Spring Data Jpa 内部的page bean
* 此重载的findAll方法为分页方法需要两个参数
* 第一个参数:查询条件Specification
* 第二个参数:分页参数
*/
Page<Customer> page = customerDao.findAll(spec,pageable);
// 页数
int pageNums = page.getTotalPages();
// 记录数量
int count = page.getTotalElements();
// 列表数据
List<Customer> customers = page.getContent();
}
2. 多表查询
2.1 一对一查询
以People
和Address
为例:
@Entity
@Table("people")
public class People {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;//id
@Column(name = "name")
private String name;//姓名
@Column(name = "sex")
private String sex;//性别
@OneToOne // 标注这是1对1
@JoinColumn(name = "address_id", referencedColumnName = "id")//people中的address_id字段参考address表中的id字段
private Address address;//地址
}
@Entity
public class Address {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false)
private Long id;//id
@Column(name = "phone", nullable = true, length = 11)
private String phone;//手机
}
2.2 一对多查询
@Entity//表示当前类是一个实体类
@Table(name="cst_customer")//建立当前实体类和表之间的对应关系
public class Customer implements Serializable {
@Id//表明当前私有属性是主键
@GeneratedValue(strategy=GenerationType.IDENTITY)//指定主键的生成策略
@Column(name="cust_id")//指定和数据库表中的cust_id列对应
private Long custId;
//配置客户和联系人的一对多关系
@OneToMany(targetEntity=LinkMan.class)
@JoinColumn(name="lkm_cust_id",referencedColumnName="cust_id")
private Set<LinkMan> linkmans = new HashSet<LinkMan>;
}
@Entity
@Table(name="cst_linkman")
public class LinkMan implements Serializable {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="lkm_id")
private Long lkmId;
//多对一关系映射:多个联系人对应客户
@ManyToOne(targetEntity=Customer.class)
@JoinColumn(name="lkm_cust_id",referencedColumnName="cust_id")
private Customer customer;//用它的主键,对应联系人表中的外键
}
注解说明:
-
@OneToMany
:建立一对多的关系targetEntityClass
:指定多的一方的类的字节码mappedBy
:指定从表实体类中引用主表对象的名称cascade
:指定使用的级联操作fetch
:是否采用延迟加载orphanRemoval
:是否使用孤儿删除
-
@ManyToOne
:建立多对一的关系targetEntityClass
:指定一的一方的类的字节码cascade
:指定使用的级联操作fetch
:是否采用延迟加载optional
:关联是否可选
-
JointColumn
:用于定义主键字段和外键字段的关系name
:外键字段的名称referencedColumnName
:引用主表的主键字段名称unique
:是否唯一nullable
:是否允许为空insertable
:是否允许擦汗如updatetable
:是否允许更新columnDefinition
:列的定义信息
// 插入操作
public class Test {
@Autowired
private CustomerDao customerDao;
@Autowired
private LinkManDao linkManDao;
@Transactional //开启事务
@Rollback(false)//设置为不回滚
@Test
public void test() {
Customer cust = new Customer();
// set操作
LinkMan link = new LinkMan();
// set操作
c.getLinkMans.add(link);
l.setCustomer(c);
customerDap.save(cust);
linkManDao.save(link);
}
}
2.3 多对多查询
/**
* 用户的数据模型
*/
@Entity
@Table(name="sys_user")
public class SysUser implements Serializable {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="user_id")
private Long userId;
//多对多关系映射
@ManyToMany(mappedBy="users")
private Set<SysRole> roles = new HashSet<SysRole>(0);
}
/**
* 角色的数据模型
*/
@Entity
@Table(name="sys_role")
public class SysRole implements Serializable {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="role_id")s
private Long roleId;
//多对多关系映射
@ManyToMany
@JoinTable(name="user_role_rel",//中间表的名称
//中间表user_role_rel字段关联sys_role表的主键字段role_id
joinColumns={
@JoinColumn(name="role_id",referencedColumnName="role_id")},
//中间表user_role_rel的字段关联sys_user表的主键user_ssid
inverseJoinColumns={
@JoinColumn(name="user_id",referencedColumnName="user_id")}
)
private Set<SysUser> users = new HashSet<SysUser>(0);
}
注解说明:
ManyToMany
:多对多映射cascade
:配置级联操作fetch
:是否采用延迟加载targetEntity
:配置目标的实体类
@JoinTable
:中间表配置name
:中间表的名称joinColumns
:中间表的外键字段关联当前实体类所对应的主键字段inverseJoinColumn
:中间表的外键字段关联对方表的主键字段
@JointColumn
:同上面的