orm:对象映射
默认值问题
在数据库中,某个表的某个属性有默认值的情况下。在不用set方法赋值的情况下,默认值不生效为空。需要改动.cfg.xml中表的属性。Dynamic-update=”true”
举例:
<class name="wyn.hibernate.entity.User" table="user" catalog="book" optimistic-lock="version" dynamic-insert="true">
3 hibernate的一级缓存(session缓存,只支持对象缓存(非list),不支持查询缓存)
(验证:(未开启二级缓存的情况下)先查询全体成员,再查询单个成员(如果再次查 询全体,则执行2次sql语句),最后关闭session。
结果:sql一句只执行一次(查询全体的),查询单个成员时,会先从session中查 找(session中已有全部的成员信息),找到之后就不会再从数据库中寻找。如果 未找到,再从数据库中查找。)举例:
未关闭session时:sql语句只执行一次。
举例:
Query q=session.createQuery("from User");
List<User> users=q.list();
System.out.println("一级缓存测试........................"+users.size());
User user1=(User) session.get(User.class,1);
System.out.println(user1.getUsername());
session.close();
关闭session时:sql语句执行2次
Query q=session.createQuery("from User");
List<User> users=q.list();
System.out.println("一级缓存测试........................"+users.size());
session.close();
session=sf.openSession();
User user1=(User) session.get(User.class,1);//对象缓存
System.out.println(user1.getUsername());
session.close();
session的3种状态
3.1 临时(瞬时)状态(User user=new User(),不被session关联)
3.2 持久化状态(调用save或者save0rUpdate方法或者直接调用get方法等,并commit)
持久化状态session域中的数据是在被提交时更新(即和数据库中的数据同步),在此之前 连续对某个属性的更改,并不会全部被变为sql语句执行,只会执行最后一条更该语句。
数据存放在sesion中,如果不close()掉,则会一直存在,可以直接使用,一直和session 关联
3.3游离状态(在close()之后,不被session关联)
4 hibernate的延时加载
4.1 Hibernate默认情况下是不会查询所有外键关联的表的数据的(在从表中设置中lazy属性为false就可延时查询外键关联表的数据)(多对一的情况)
在hbm.xml文件中关联外键的表
<many-to-one name="teacher" class="wyn.hibernate.entity1.Teacher" fetch="select" lazy="false">
<column name="tid" /></many-to-one>
在test(实现类中)的代码:
public static void main(String [] args){
Configuration cfg=new Configuration().configure();
ServiceRegistry sr=new ServiceRegistryBuilder() .applySettings(cfg.getProperties()).buildServiceRegistry();
//SessionFactory类似数据库库的一个Connection
SessionFactory sf =cfg.buildSessionFactory(sr);
Session session=sf.openSession();
//开启一个事务
Transaction t=session.beginTransaction();
Student s=(Student) session.get(Student.class,1);
t.commit();
System.out.println(s.getName());
session.close();
System.out.println(s.getTeacher().getName());
}
4.2 在主表中,实现延时查询
<set name="students" table="student" inverse="true" lazy="false" fetch="select">
<key>
<column name="tid" />
</key>
<one-to-many class="wyn.hibernate.entity1.Student" />
</set>
(一对多,此时这个one并没有layz这个属性,需要在set属性中修改,并且在Teacher这个类中会自动生成private Set students = new HashSet(0);)
5 主表和从表
主表(父表)
在数据库中建立的表格即Table,其中存在主键(primary key)用于与其它表相关联,并且作为在主表中的唯一性标识。
从表(子表)
以主表的主键(primary key)值为外键 (Foreign Key)的表,可以通过外键与主表进行关联查询。从表与主表通过外键进行关联查询。
关系及用法概述
从表数据依赖于主表,一般最后查询数据时把主表与从表进行关联查询。
6 hql(hibernate query language) 跨数据库语言的查询方式
第一种方式
Query q=session.createQuery("from Student where name='王'");//Student是javabean的类名,而不是数据库的表名
List<Student> lists=q.list();
System.out.println(lists.size());
第二种方式
Student student=new Student();
student.setChengji(100.0);
String sql="from Student where 1=1 ";//记得”1=1”后边留空格
if(!student.equals("")||student!=null){
if(student.getChengji()!=null){
sql+=" and chengji='"+student.getChengji()+"'";
}//记得’and’之前留空格
Query q1=session.createQuery(sql);
List<Student> lists1=q1.list();
System.out.println(lists1.size());
第三种方式,根据位置绑定数据/根据名称绑定数据
Query q1=session.createQuery("from Student where chengji=?
//根据位置
and kecheng=:a ");//根据名称
q1.setDouble(0, 100.0);
q1.setString("a", "高数");
List<Student> lists1=q1.list();
System.out.println(lists1.size());
第四种方式 分页查询
Query q1=session.createQuery("from Student where chengji=? and kecheng=:a ");
q1.setFirstResult(0);//从查询结果中的哪一行开始结算
q1.setMaxResults(8);//从查询结果中取出多少行结算
q1.setDouble(0, 100.0);
q1.setString("a", "高数");
List<Student> lists1=q1.list();
for(Student student:lists1){
System.out.println(student.getName());
}
System.out.println(lists1.size());
7 Hbc javabean的查询方式
Cri.add//后面添加约束条件(就像sql中where条件后的语句)
第一种方式(等值查询)
Criteria cri=session.createCriteria(Student.class);
cri.add(Restrictions.eq("kecheng", "高数"));//等值查询
List<Student> lists=cri.list();//查询结过、果被封装成javabean
System.out.println(lists.get(1).getName());
第二种方式(模糊查询)
Criteria cri=session.createCriteria(Student.class);
cri.add(Restrictions.like("kecheng", "高%"));
List<Student> lists=cri.list();//查询结过果被封装成javabean
System.out.println(lists.size());
for(Student student:lists){
System.out.println(student.getName());
}
第三种方式 between
cri.add(Restrictions.between("id", 0, 10));
第四种方式 in
cri.add(Restrictions.in("kecheng", new String[]{"高数 ","java"}));
第五种方式 组合查询条件
方法1第五种方式 组合查询条件
cri.add(Restrictions.like("name", "王%"));
cri.add(Restrictions.eq("kecheng", "高数"));
方法2
cri.add(Restrictions.and(Restrictions.like("name"," 王%"),Restrictions.eq("kecheng", "高数")));
方法3
cri.add(Restrictions.or(Restrictions.like("name", " 王%"),Restrictions.eq("kecheng", "java")));
//and和or的区别:and满足所有条件的行,or每一个满足条件的 行集合
List<Student> lists=cri.list();//查询结过果被封装成javabean
System.out.println(lists.size());
for(Student student:lists){
System.out.println(student.getName());
}
7 <!--是否将运行期生成的SQL输出到日志以供调试-->
<property name="hibernate.show_sql">true</property>
8 hibernate的数据库连接池
8.1导入jar包(3个c3p0包)
8.2 在hibernate.cfg.xml中配置数据库连接池必要的配置
<!--****************** 【连接池配置】****************** -->
<!-- 配置连接驱动管理类 -->
<property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionPro<!--是否将运行期生成的SQL输出到日志以供调试-->
vider</property>
<!-- 配置连接池参数信息 -->
<!-- 连接池中数据库连接的最小数目 -->
<property name="hibernate.c3p0.min_size">2</property>
<!--连接池中数据库连接的最大数目? -->
<property name="hibernate.c3p0.max_size">4</property>
<!-- 获得连接的超时时间,如果超过这个时间,会抛出异常,单位毫秒 -->
<property name="hibernate.c3p0.timeout">5000</property>
<!-- 可以被缓存的PreparedStatement实例的最大数目。
缓存适量的PreparedStatement实例,能够大大提高Hibernate的性能。 -->
<property name="hibernate.c3p0.max_statements">10</property>
<!-- 在使数据库连接自动生效之前处于空闲状态的时间,以秒为单位 -->
<property name="hibernate.c3p0.idle_test_period">30000</property>
<!-- 当连接池里面的连接用完的时候,C3P0一下获取的新的连接数 -->
<property name="hibernate.c3p0.acquire_increment">2</property>
9 hibernate二级缓存(sessionFactory缓存,支持可插拔式的缓存,支持查询缓存)
9.1 导二级缓存需要的jar包(3个ehcache包)
9.2 在hibernate.cfg.xml文件中配置开启二级缓存的语句
<!--****************** 【二级缓存配置】****************** -->
<!-- 开启二级缓存 -->
<property name="hibernate.cache.use_second_level_cache">true</property>
<!-- 开启查询缓存 -->
<property name="hibernate.cache.use_query_cache">true</property>
<!-- 二级缓存的提供类 在hibernate4.0版本以后我们都是配置这个属性来指定二级缓存的提供类-->
<property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
<!-- 二级缓存配置文件的位置 -->
<property name="hibernate.cache.provider_configuration_file_resource_path">ehcache.xml</property>
9.3 在数据库中对象的映射xml文件中配置语句
<!-- 配置二级缓存开启的条件 -->
<cache usage="read-write"/>
9.4 在调用sql语句的后面开启二级缓存
Query q=session.createQuery("from User").setCacheable(true);
List<User> users=q.list();
System.out.println("一级缓存测试........................"+users.size());
session.close();
session=sf.openSession();
Query q2=session.createQuery("from User").setCacheable(true);
//开启自己的二级缓存,从上面语句的二级缓存中查询值
List<User> users1=q2.list();
System.out.println("一级缓存测试2........................"+users1.size());
/*User user1=(User) session.get(User.class,1);
System.out.println(user1.getUsername());*/
session.close();
10 当hibernate通过id访问数据库对象的时候,先从session中查找,然后从二级缓存中查找,再从数据库中查找