对象导航检索方式: 主要针对关联集合对象的
查询(针对多表) 查找目标表数据再访问其关联的集合对象属性的时候,自动发送sql语句
注意:导航检索必须是持久态对象,否则不能导航, 解决办法 : 在session关闭之前,对对象中集合或者对象初始化
默认情况下,关联属性是延迟加载的,只有在访问其关联属性的时候才发出SQL从数据库查询,导致查询两张表数据时,至少发出两部分SQL语句,一个是主对象查询语句,一个是关联属性的语句。
OID检索方式:
session.get(entity.class,id),session.load(entity.class,id)(单表 byid)
HQL检索方式:session.createQuery(hql).list(),uniqu…// 面向对象
SQL检索方式(Native Query):session.createSQLQuery(sql).addEntity().list(),
QBC检索方式:(Query by Criteria):session.createCriteria(Entity.class).list()// 面向对象
HQL\QBC和SQL的区别?
HQL\QBC 面向类和属性,由hibernate自动生成sql语句,效率低
SQL 面向表和字段, 不会去组建sql语句,效率高
条件查找
public void testQueryByCondition(){
Session session = HibernateUtil. openSession();
session.beginTransaction();
/**HQL*/
Customer c1 = (Customer) session.createQuery( "from Customer where name=?")
// .setParameter(0, "tom");
.setString(0, "tom")
.uniqueResult();
System. out.println(c1 );
/**SQL*/
Customer c2 = (Customer) session.createSQLQuery( "select * from t_customer where name=:name").addEntity(Customer. class)
// .setParameter("name", "tom")
.setString( "name", "tom" )
.uniqueResult();
System. out.println(c2 );
/**QBC*/
Criteria criteria = session.createCriteria(Customer. class);
List<Customer> list = criteria.add(Restrictions.like("name" , "%o%" )).list();
System. out.println(list );
session.getTransaction().commit();
session.close();
}
1
:name .setString("name","db");
HQL检索: session.createQuery("from 实体 where name=?").setParameter(0,"name").uniqueResult();
SQL检索 : session.createSQLQuery("select * from 表 where name=?").addEntity(实体.class).setParameter(0,"name").uniqueResult();
QBC检索: criteriy= session.createCriteria(实体.class);
criteriy.add(Restricions.eq("name","db"));
criteriy.uniqueResult();
排序
Session session = HibernateUtil. openSession();
session.beginTransaction();
/**HQL*/
List<Customer> list = session.createQuery("from Customer order by id desc").list(); // 此id为实体类中的对象id
System. out.println(list );
/**SQL*/
List<Customer> list2 = session.createSQLQuery("select * from t_customer order by id desc").addEntity(Customer. class).list();// 此id为数据库属性
System. out.println(list2 );
/**QBC*/
List<Customer> list3 = session.createCriteria(Customer.class).addOrder(org.hibernate.criterion.Order. desc("id")).list() ;
System. out.println(list3 );
session.getTransaction().commit();
session.close();
分页查询:
// 当前页
int pageNo = 2;
// 每页显示的数量
int pageCount = 10;
// 下标计算公式
int index = (pageNo -1)*pageCount ;
Session session = HibernateUtil. openSession();
session.beginTransaction();
/**HQL*/
List<Order> list = session.createQuery("from Order")
.setFirstResult( index)
.setMaxResults( pageCount).list();
System. out.println(list );
/**之前的SQL*/
List<Order> list2 = session.createSQLQuery("select * from t_order limit ?,?").addEntity(Order. class).setParameter(0, index).setParameter(1, pageCount).list();
System. out.println("old" +list2 );
/**SQL*/
List<Order> list3 = session.createSQLQuery("select * from t_order").addEntity(Order. class).setFirstResult(index).setMaxResults(pageCount).list() ;
System. out.println("new" +list3 );
/**QBC*/
List<Order> list4 = session.createCriteria(Order.class).setFirstResult( index).setMaxResults(pageCount).list();
System. out.println(list4 );
//oracle:写的技巧:先在 sql编辑器中写好,再复制进来改一改就行了。
List<Order> list2 = session.createSQLQuery("SELECT * FROM (SELECT t.*,ROWNUM r FROM t_order t WHERE ROWNUM<="+(firstResult+maxResults)+") t2 WHERE t2.r>="+(firstResult+1)).addEntity(Order.class).list();
System.out.println(list2);
投影查询: 查询结果仅包含实体的部分属性, 即只查询表中的部分指定字段的值,不查询全部
用List<Object[]> 接收 , 非受管对象,不受session管理,不会在一级缓存中存在,一般不用, 一般都查所有的
经过投影查询的结果,默认 都不会封装到实体类型中, 而是根据实际查询的结果自动封装(object[]),如查询id和name,返回的object[]的list集合。
最大的坏处:一级缓存不存放该对象。无法使用hibernate的一些特性,比如快照等等。
【注意】查询之后封装到Object[]数组中的这些数据,称之为散装数据,不会存放于一级缓存,所以未来需要用的时候,还要查询,尽量少用
Session session = HibernateUtil. openSession();
session.beginTransaction();
/**HQL*/
//此时不再封装成实体对象,而是返回Object[]的散装数据
List<Object[]> list = session.createQuery("select c.name,c.city from Customer c where c.id=?").setParameter(0, 1).list() ;
for (Object[] object : list ) {
System. out.println(object [0]+":" +object [1]);
}
/**SQL*/
//此时不再封装成实体对象,而是返回Object[]的散装数据
List<Object[]> list2 = session.createSQLQuery("select c.name,c.city from t_customer c where c.id=:id").setParameter("id" , 1).list();
for (Object[] o : list2 ) {
System. out.println(o [0]+":" +o [1]);
}
/**QBC*/
//此时不再封装成实体对象,而是返回Object[]的散装数据
List<Object[]> list3 = session.createCriteria(Customer.class)
.setProjection(Projections. projectionList()
.add(Property. forName("name"))
.add(Property. forName("city")))
.add(Restrictions. eq("id", 1)).list() ;
for (Object[] o : list3 ) {
System. out.println(o [0]+":" +o [1]);
}
session.getTransaction().commit();
session.close();
投影查询也可以封装成对象, 但是对象必须要有对应参数的构造方法
HQL:
List<Customer> list4 = session.createQuery( "select new Customer(c.id,c.name) from Customer c").list() ;
QBC
Criteria criteria = session.createCriteria(Customer. class);
criteria.setProjection(Projections. projectionList()
.add(Property. forName("name").as( "name"))
.add(Property. forName("city").as( "city")));
criteria.setResultTransformer( new AliasToBeanResultTransformer(Customer.class ));
List<Customer> list = criteria .list();
或者
criteria.setResultTransformer(Transformers.aliasToBean(Customer.class))
聚合函数count查询
Session session = HibernateUtil. openSession();
session.beginTransaction();
/**HQL*/
Long obj = (Long) session.createQuery( "select count(*) from Customer c").uniqueResult();
System. out.println(obj );
/**SQL*/
BigInteger count = (BigInteger) session.createSQLQuery( "select count(*) from t_customer").uniqueResult();
System. out.println(count );
/**QBC*/
Long num = (Long) session.createCriteria(Customer. class)
.setProjection(Projections. rowCount())//相当于 count(*)
.setProjection(Projections. count("name")) // 相当于 count(name)
.uniqueResult();
System. out.println(num );
session.getTransaction().commit();
session.close();
命名查询:是将sql或hql语句写入配置文件中,为该语句起个名字,在程序中通过名字来访问sql或hql语句
第一步:在hbm中配置命名查询的名字和语句(支持HQL或Sql)
第二步:在程序中通过session.getNamedQuery(命名查询的名字)来直接获取Query或SQLQuery对象,进行操作
<!-- 命名查询 --> 在class中命名
<query name= "query1">
from Customer where name=? and city=?
</query>
</class > // class外命名
<sql-query name= "cn.itcast.a_oneToMany.Customer.query2" >
select * from t_customer where name = ? and city = ?
</sql-query>
/**HQL*/
Customer c = (Customer) session.getNamedQuery("cn.itcast.a_oneToMany.Customer.query1" ).setParameter(0, "tom")
.setParameter(1, "上海").uniqueResult();
System. out.println(c );
/**SQL*/
SQLQuery query = (SQLQuery) session.getNamedQuery("cn.itcast.a_oneToMany.Customer.query2" );
query.addEntity(Customer. class);
query.setParameter(0, "tom");
query.setParameter(1, "上海");
Customer c2 = (Customer) query.uniqueResult();
System. out.println(c2 );
离线查询: DetachedCriteria 脱离离session,在service层拼接条件,传到dao层, dao层只需一个方法
Criteria:在线查询方式:依赖session,有了session之后,才能去创建Criteria对象,然后才可以添加条件
DetachedCriteria:离线查询方式:不依赖session创建,自身内部含有创建方式,可以在没有session的情况下,自由的组装各种条件,然后在发送给session执行
通过静态方法 DetachedCriteria.forClass(PO.class)来实例化
通过detachedCriteria.getExecutableCriteria(session)方法与session关联
/**Service层*/
//离线查询(先拼装查询条件,然后再用Session去查询数据库)
DetachedCriteria criteria = DetachedCriteria.forClass(Customer.class);
criteria.add(Restrictions. like("name", "%o%"));
criteria.add(Restrictions. eq("city", "上海"));
/**传递Dao层*/
Session session = HibernateUtil. openSession();
session.beginTransaction();
Customer c = (Customer) criteria.getExecutableCriteria(session ).uniqueResult();
System. out.println(c );
session.getTransaction().commit();
session.close()
内连接和迫切连接fetch
相同点:都是只需要发出一条SQL就可以将两个表的数据一次性查询出来。
不同点:返回的结果的默认封装方式不同:
内连接将结果封装为List<Object[]>,Object[]中再封装了实体对象。非受管对象。
迫切内连接将结果封装为List<主表的实体>,这里是List<Customer>,其从表数据 被封装到主表实体中的关联属性中了。而且是受管对象
HQL
List list15 = session .createQuery("from Customer c left join c.orders").list();
List list15 = session.createQuery( "select distinct c from Customer c left join fetch c.orders").list();
SQL:
List<Object[]> list = session.createSQLQuery("select c.id as cid,c.name as cname,c.city,o.id as oid,o.name as oname,o.price from t_customer c inner join t_order o on c.id=o.cid").list();
QBC:
criteria. createCriteria("orders",CriteriaSpecification. LEFT_JOIN);
criteria.createCriteria( "orders",org.hibernate.sql.JoinType.LEFT_OUTER_JOIN);//表示左外连接,默认是内连接
Query功能扩展: 也可以完成增删改
int rows = session.createQuery("update Customer set name = ' Jattt' where id = ?").setParameter(0, 2) .executeUpdate()
JPA注解:
注解要么都放属性上,要么都放getter上,不能混着用
@Entity // 将当前类标识为一个实体类,表名默认是类名
@Table(catalog="user" ,name="t_book" ) //catalog数据库名 name为表名
public class Book {
@Id // 指定该字段是主键, 注解也可以写在getter方法上
@GeneratedValue(strategy=GenerationType.AUTO) // 默认是自动增长,主键生成策略 auto相当于native
// @GenericGenerator(name="myidGenerator",strategy="assigned")// HIbernate的主键策略生成器,name主键生成器名字, strategy:生成策略
// @GeneratedValue(generator="myidGenerator") // 使用自定义扩展主键生成器
private Integer id ;
@Column(name= "name",length=30,nullable=false,unique=true)
private String name ;
@Column(name= "price",unique=false )
@Basic // 表示该字段有效,数据库会生成队列(默认) 不写则默认为@Basic
private Double price ;
@Transient // 控制数据库不生成队列
private String stat ;
一对多
@Entity
@Table(name="t_customer" )
public class Customer {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Integer id;
private String name ;
private String city ;
@OneToMany(mappedBy="customer" ,// 相当于inverse=true放弃外键维护权,配置当前Customer对象在Order实体中的名称
fetch=FetchType. LAZY, // 设置是否延迟加载
cascade=CascadeType. ALL, // 设置级联
targetEntity=Order. class // 设置集合中放入的目前实体的类型,基本上可以忽略
)
private Set<Order> orders = new HashSet<Order>();
@Entity
@Table(name="t_order" )
public class Order {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Integer id ;
private String name ;
private Double price ;
@ManyToOne
@JoinColumn(name="cid" )// 设置外键
private Customer customer ;
// 配置映射文件
<mapping class= "cn.jpa.oneToMany.Customer" />
<mapping class= "cn.jpa.oneToMany.Order" />
多对多:
@Entity
@Table(name="t_course" )
public class Course {
@Id
@GeneratedValue (strategy=GenerationType.AUTO)
private Integer id ;
private String name ;
@ManyToMany(mappedBy="courses" )// 放弃外键维护权
private Set<Student> students = new HashSet<Student>();
@Entity
@Table(name="t_student" )
public class Student {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Integer id ;
private String name ;
@ManyToMany(cascade=CascadeType.ALL)
@JoinTable(name="t_s_c" ,
joinColumns= @JoinColumn(name="sid" ),// 配置Student对象在关系表中的外键名
inverseJoinColumns= @JoinColumn(name="cid" ))// 配置放弃外键维护权一方在关系表中的外键名
private Set<Course> courses = new HashSet<Course>();
测试:
Session session = HibernateUtil. openSession();
Transaction tran = session.beginTransaction();
Student s = new Student();
s.setName( "杨过");
Course c = new Course();
c.setName("java" );
s.getCourses().add( c);
//c.getStudents().add(s);
session.save( s);
//session.save(c);
tran.commit();
session.close();
注解命名查询:
HQL:
@NamedQuery(name="Student.findAll" ,query="from Student" )
@NamedQueries(value={
@NamedQuery(name="query1" ,query="from Student" ),
@NamedQuery(name="query2" ,query="from Student" ),
@NamedQuery(name="query3" ,query="from Student" )
})
@Entity
@Table(name="t_student" )
public class Student {}
List<Student> list = session.getNamedQuery( "Student.findAll").list();
System. out.println(list .get(0).getCourses());
List<Student> list = session.getNamedQuery( "query1").list();
System. out.println(list .get(0).getCourses());
SQL
//sql
@NamedNativeQuery(name="Customer.findcount" ,query="select count(*) from t_customer")//配置一个
@NamedNativeQueries({@NamedNativeQuery (name="Customer.findcount" ,query="select count(*) from t_customer"),@NamedNativeQuery(name= "Customer.findcount2",query="select count(*) from t_customer" )})
网友评论