一.Hibernate测试代码
直接上代码,具体解释见代码注释
Hibernate主配置文件hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- 必须导入约束文件hibernate-configuration-3.0.dtd -->
<!-- 约束文件路径
...\hibernate-release-5.0.7.Final\project\hibernate-core\src\main\resources\org\hibernate\hibernate-configuration-3.0.dtd
-->
<!-- 导包后,可以从下面路径的文件中复制约束声明
hibernate-core-5.0.7.Final.jar/org/hibernate/hibernate-configuration-3.0.dtd -->
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<!-- hibernate的主配置文件,必须放在src目录下,命名为hibernate.cfg.xml -->
<hibernate-configuration>
<session-factory>
<!-- 关于配置的文件描述,hibernate提供了hibernate.properties文件
路径:...\hibernate-release-5.0.7.Final\project\etc
-->
<!-- #hibernate.dialect org.hibernate.dialect.MySQLDialect
#hibernate.dialect org.hibernate.dialect.MySQLInnoDBDialect
#hibernate.dialect org.hibernate.dialect.MySQLMyISAMDialect
#hibernate.connection.driver_class com.mysql.jdbc.Driver
#hibernate.connection.url jdbc:mysql:///test
#hibernate.connection.username gavin
#hibernate.connection.password -->
<!-- 数据库驱动 -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<!-- 数据库url -->
<property name="hibernate.connection.url">jdbc:mysql:///my?useUnicode=true&characterEncoding=utf-8</property>
<!-- url后设置的是读取使用的编码,必须于数据库一致。其中 amp; 不能省略,原因未知-->
<!-- 数据库连接用户名 -->
<property name="hibernate.connection.username">root</property>
<!-- 数据库连接密码 -->
<property name="hibernate.connection.password">password</property>
<!-- 数据库方言 不同的数据库中,sql语法略有区别.
指定方言可以让hibernate框架在生成sql语句时.针对数据库的方言生成.
sql99标准: DDL 定义语言 库表的增删改查 DCL 控制语言 事务 权限 DML 操纵语言 增删改查
注意: MYSQL在选择方言时,请选择最短的方言. -->
<property name="hibernate.dialect">
org.hibernate.dialect.MySQLDialect
</property>
<!-- #hibernate.show_sql true
#hibernate.format_sql true-->
<!-- 将hibernate生成的sql语句打印到控制台 -->
<property name="hibernate.show_sql">true</property>
<!-- 将hibernate生成的sql语句格式化(语法缩进) -->
<property name="hibernate.format_sql">true</property>
<!-- ## auto schema export
#hibernate.hbm2ddl.auto create-drop
#hibernate.hbm2ddl.auto create
#hibernate.hbm2ddl.auto update
#hibernate.hbm2ddl.auto validate-->
<!-- ## auto schema export 自动导出表结构. 自动建表
#hibernate.hbm2ddl.auto create 自动建表.每次框架运行都会创建新的表.以前表将会被覆盖,表数据会丢失.(开发环境中测试使用)
#hibernate.hbm2ddl.auto create-drop 自动建表.每次框架运行结束都会将所有表删除.(开发环境中测试使用)
#hibernate.hbm2ddl.auto update(推荐使用) 自动生成表.如果已经存在不会再生成.如果表有变动.自动更新表(不会删除任何数据).
#hibernate.hbm2ddl.auto validate 校验.不自动生成表.每次启动会校验数据库中表是否正确.校验失败. -->
<property name="hibernate.hbm2ddl.auto">update</property>
<!-- 指定hibernate操作数据库时的隔离级别## specify a JDBC isolation level
#hibernate.connection.isolation 1|2|4|8
二进制
0001 1 读未提交
0010 2 读已提交
0100 4 可重复读 mysql默认
1000 8 串行(xing)化
-->
<property name="hibernate.connection.isolation">4</property>
<!-- 指定session与当前线程绑定.hibernate.properties文件中没有描述,要背下来名称-->
<!-- 加入此项后getCurrentSession方法才能使用,否则会报错 -->
<property name="hibernate.current_session_context_class">thread</property>
<!-- 引入orm元数据 路径书写: 填写src下配置的xml文件的路径 -->
<property name="dialect"></property>
<mapping resource="cjx/user/Hibernate.xml" />
</session-factory>
</hibernate-configuration>
POJO类User.java
public class User {//实体类
/*实体(bean)类创建规则
* 1.持久化类提供无参数构造
* 2.成员变量私有,提供公有get/set方法访问
* 3.持久化类中的属性,应尽量使用包装类型.(jdk有自动装箱和拆箱功能,基本类型没有null值)
* 4.持久化类需要提供oid(与主键对应的属性).与数据库中的主键列对应.(如果一个表没有主键,hibernate不能使用)
* 5.不要用final修饰class().(hibernate使用cglib代理生成代理对象.代理对象是继承被代理对象.如果被final修饰.将无法生成代理.)
*/
private String id;
private String username;
private String password;
private String test;
public String getTest() {
return test;
}
public void setTest(String test) {
this.test = test;
}
public String getUsername() {
return username;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String toString() {
return "User [id=" + id + ", username=" + username + ", password=" + password + "]";
}
}
Hibernate映射文件Hibernate.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- 必须导入约束文件hibernate-mapping-3.0.dtd -->
<!-- 约束文件路径
...\hibernate-release-5.0.7.Final\project\hibernate-core\src\main\resources\org\hibernate\hibernate-mapping-3.0.dtd
-->
<!-- 导包后,可以从下面路径的文件中复制约束声明
hibernate-core-5.0.7.Final.jar/org/hibernate/hibernate-mapping-3.0.dtd -->
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- hibernate的orm元数据配置文件-->
<!-- 配置表与实体对象的关系 -->
<!-- package属性(可选):填写一个包名.
好处:在元素内部凡是需要书写完整类名的属性,可以直接写简单类名. -->
<hibernate-mapping package="cjx.user">
<!-- class元素: 配置实体bean与表的对应关系. name: 完整类名 table:数据库表名 -->
<class table="user" name="cjx.user.User">
<!-- id元素:配置主键映射的属性 name: 填写主键对应bean的属性名
column(可选): 填写表中的主键列名.默认值:列名会默认使用属性名
type(可选):填写列(属性)的类型.hibernate会自动检测实体的属性类型.
每个类型有三种填法: java类型|hibernate类型|数据库类型
not-null(可选):配置该属性(列)是否不能为空. 默认值:false
length(可选):配置数据库中列的长度. 默认值:使用数据库类型的最大长度 -->
<id name="id">
<!-- generator:主键生成策略 -->
<!-- 每条记录录入时,主键的生成规则,适用于代理主键 -->
<!--
* 主键生成策略:
* 1.自然主键
* assigned:自然主键生成策略. hibernate不会管理主键值.由开发人员自己录入.
* 2.代理主键
* identity : 主键自增.由数据库来维护主键值.录入时不需要指定主键(指定了主键也无效).
* sequence: Oracle中的主键生成策略.
* increment(了解)(线程不安全): 主键自增.由hibernate来维护.每次插入前会先查询表中id最大值.+1作为新主键值主键类型必须为整型.
* hilo(了解): 高低位算法.主键自增.由hibernate来维护.开发时不使用.
* native:hilo+sequence+identity 自动三选一策略.
* uuid: 产生随机字符串作为主键. 主键类型必须为string 类型.
-->
<generator class="assigned"></generator>
</id>
<!-- property元素:除id之外的普通属性映射
name: 填写属性名
column(可选): 填写列名
type(可选):填写列(属性)的类型.hibernate会自动检测实体的属性类型.
每个类型有三种填法: java类型|hibernate类型|数据库类型
not-null(可选):配置该属性(列)是否不能为空. 默认值:false
length(可选):配置数据库中列的长度. 默认值:使用数据库类型的最大长度 -->
<property name="username" column="username"/>
<property name="password" column="password"/>
<!-- 用于演示hibernate的自动建表功能:hibernate.hbm2ddl.auto
<property name="test" column="test"/>
-->
</class>
</hibernate-mapping>
测试代码Hibernate.java
public class Hibernate {
@Test
//hibernate操作代码演示
public void funone(){
//1.创建,调用空参构造
/* Configuration conf = new Configuration();
* 读取指定主配置文件 => 空参加载方法,加载src下的hibernate.cfg.xml文件
* conf.configure();
* 读取指定orm元数据(扩展),如果主配置中已经引入映射配置.不需要手动加载
* conf.addResource(resourceName);
* conf.addClass(persistentClass);
*/
// Configuration对象功能: 配置加载类.用于加载主配置,orm元数据加载
Configuration config = new Configuration().configure();
//2.根据配置信息,创建 SessionFactory对象
/* SessionFactory对象功能: 用于创建操作数据库核心对象session对象的工厂.创建session对象
注意:1.SessionFactory 负责保存和使用所有配置信息.消耗内存资源非常大.
2.SessionFactory属于线程安全的对象设计.
结论: 保证在web项目中,只创建一个sessionFactory.
*/
SessionFactory sessionFactory = config.buildSessionFactory();
//3.获得session.打开一个新的session对象
/*session对象功能: 表达hibernate框架与数据库之间的连接(会话).
session类似于JDBC的connection对象. 还可以完成对数据库中数据的增删改查操作.
session是hibernate操作数据库的核心对象
* 扩展
获得一个与线程绑定的session对象
sessionFactory .getCurrentSession();
*/
Session session = sessionFactory.openSession();
//4. session获得操作事务的Transaction对象
/*获得操作事务的transaction 对象
* Transaction transaction = session.getTransaction();
* 开启事务并获得操作事务的transaction 对象(建议使用)
*Transaction tx2 = session.beginTransaction();
*/
Transaction transaction = session.beginTransaction();
// //----------------------------------------------
// //session的增加//web开发时可以使用beanutil.populate()将参数封装到对象
User uz = new User();//瞬时状态
uz.setId("123456");//瞬时状态
uz.setUsername("check is ok");//瞬时状态
uz.setPassword("123456");//瞬时状态
session.save(uz);//将瞬时状态转换为持久化状态
// //----------------------------------------------
// //----------------------------------------------
// //session的修改
// //1.获得要修改的对象
// // 2.修改
// //3 执行update
// User ux= session.get(User .class, "1");//此时得到的是持久化状态
// ux.setUsername("i have change it");
// ux.setPassword("11111111");
// session.update(ux);//因为是持久化状态,所以不写此句也可以修改
//持久化状态对象的任何变化都会在事务提交时自动同步到数据库中
/*三个对象状态:瞬时状态,持久化状态,游离(托管)状态
* 瞬时状态:没有id,不在session缓存中
* 持久化状态:有id,在session缓存中
* 游离(托管)状态:有id,不在session缓存中
* 注:有id指的是有与数据库对应的id值
* 三个对象状态可以通过这些方法进行转换
* 瞬时状态:new(得到瞬时状态),save(转换为持久化状态)
* 持久化状态:get(得到持久化状态),delete(转换为瞬时状态),close(转换为游离状态)
* 游离(托管)状态:update(转换为持久化状态)
* 拓展:session.saveOrUpdate(object);方法可以直接将对象转换为持久化状态
*/
// //----------------------------------------------
// //----------------------------------------------
// //session的删除
// //1.获得要修改的对象
// //2.调用delete删除对象
// User ud = session.get(User.class, "545654654564as");
// session.delete(ud);
// //----------------------------------------------
// //----------------------------------------------
// //session的查询
// User uc= session.get(User .class, "1");
// User uc1= session.get(User .class, "1");
// User uc2= session.get(User .class, "1");
/*1.关于缓存,此处证明缓存存在,用于查询
* SQL语句只会执行一次,得到的对象相同
* 查询时:第一次查询会将对象放入session缓存,再次查询时,会先查找session缓存
*2.关于快照,快照是指修改数据库数据时的缓存,用于修改
*提交事务时会将快照与数据库对比,如果数据不同就会修改数据库数据
*修改时:使用快照对比实体类对象和数据库数据的属性区别,只执行一次修改
*正因为有缓存(快照)存在,所以才有持久化状态
*/
// System.out.println(uc);
// System.out.println(uc==uc1);
// System.out.println(uc1==uc2);
/*load方法和get方法
* get方法:调用方法时直接返回查询结果
* load方法:使用对象时才返回查询结果
* load方法又叫延迟加载,可以配置lazy属性进行控制
* lazy:true加载时不查询,使用时才查询
* lazy:false加载时立即查询
*/
// //----------------------------------------------
transaction.commit();//提交事务时会自动关闭资源
// transaction.rollback();//回滚事务
session.close();//释放资源
sessionFactory.close();//释放资源
}
@Test
//测试主键生成策略,保存用户
public void funtwo(){
/*关于主键
* 主键:不能为空,不能重复
*
* 主键类型:
* 1.自然主键:数据库表中有可以代表主键的列,如身份证号
* 2.代理主键:数据库表中没有可以代表主键的列,创建一个没有意义的列作为主键
*
* 主键生成策略:
* 1.自然主键
* assigned:自然主键生成策略. hibernate不会管理主键值.由开发人员自己录入.
* 2.代理主键
* identity : 主键自增.由数据库来维护主键值.录入时不需要指定主键.
* sequence: Oracle中的主键生成策略.
* increment(了解)(线程不安全): 主键自增.由hibernate来维护.每次插入前会先查询表中id最大值.+1作为新主键值.
* hilo(了解): 高低位算法.主键自增.由hibernate来维护.开发时不使用.
* native:hilo+sequence+identity 自动三选一策略.
* uuid: 产生随机字符串作为主键. 主键类型必须为string 类型.
*/
//1.获得session
Session session = HibernateUtil.openSession();
//2.控制事务
Transaction tx = session.beginTransaction();
//3.执行操作
User uz = new User();
uz.setUsername("test and test");
// uz.setPassword("123456");
session.save(uz);
//4.提交事务,关闭资源
tx.commit();
session.close();
}
@Test
//测试事务操作
public void funthree(){
Session session = HibernateUtil.openSession();
Transaction tx = session.beginTransaction();
try {
User uz = new User();
uz.setId("123456");
uz.setUsername("test and test");
session.save(uz);
int i=1/0;//被除数不能为0
System.out.println(i);
} catch (Exception e) {
tx.rollback();//回滚事务
System.out.println("?????????");
}
tx.commit();
session.close();
}
}
工具类HibernateUtil.java
public class HibernateUtil {
// 用于测试的主函数
// public static void main(String[] args) {
// System.out.println(HibernateUtil.openSession());
// }
private static SessionFactory sf;
static{
//1.创建,调用空参构造
Configuration conf = new Configuration().configure();
//2.根据配置信息,创建 SessionFactory对象
sf = conf.buildSessionFactory();
}
//获得session => 获得全新session
public static Session openSession(){
Session session = sf.openSession();
return session;
}
//获得session => 获得与线程绑定的session
public static Session getCurrentSession(){
Session session = sf.getCurrentSession();
return session;
}
}
查询测试代码HibernateCheck.java
public class HibernateCheck {
@Test
//HQL查询-hibernate Query Language(多表查询,但不复杂时使用)
public void funone(){
Session session = HibernateUtil.openSession();
Transaction tx = session.beginTransaction();
//1.写HQL语句
//HQL语句不能出现数据库信息,要使用实体类的信息
// String hql="from cjx.user.User";//完整写法
String hql="from User order by id";//简单写法,基本查询,查询所有user对象
// String hql="from User where id = 1";//条件查询
// String hql="from User where id = ?";//问号占位符查询
// String hql="from User where id = :name ";//命名占位符查询,冒号+自定义的名字
//2.创建查询对象
Query query = session.createQuery(hql);
// query.setParameter(0, "1");//问号占位符查询设置参数,位置+参数
// query.setParameter("name", "1");//命名占位符查询设置参数,名字+参数
/*分页查询 */
//设置分页信息
// query.setFirstResult(0);//开始的索引
// query.setMaxResults(1);//要获取几条索引
//3.获得查询结果
List<User> list = query.list();//返回list结果
// Object uniqueResult = query.uniqueResult();//返回唯一结果
System.out.println(list);
/*统计查询
* count 计数
* sum 求和 select sum(id) from User
* avg 求平均数
* max 求最大
* min 求最小
*/
}
@Test
//Criteria查询(单表条件查询),无语句面向对象查询
public void funtwo(){
Session session = HibernateUtil.openSession();
Transaction tx = session.beginTransaction();
Criteria criteria = session.createCriteria(User.class);//基本查询,查询所有user对象
/*扩展 */
// criteria.add(Restrictions.eq("id", "1"));//条件查询,直接调用Restrictions方法
/*关于Restrictions方法
* >:gt
* >=:ge
* <:lt
* <=:le
* ==:eq
* !=:ne
* in:in
* is null:isNull等等
*/
/*扩展 */
/*分页查询 */
//设置分页信息
// criteria.setFirstResult(1);//开始的索引
// criteria.setMaxResults(1);//要获取几条索引
/*分页查询 */
List<User> list = criteria.list();
System.out.println(list);
/*使用函数*/
// criteria.setProjection(Projections.rowCount());//设置查询的聚合函数=》总行数
// long x=(long) criteria.uniqueResult();//此处用int会报错
// System.out.println(x);
/*使用函数 */
tx.commit();
session.close();
/*离线的criteria
* criteria可以脱离session创建,组装查询条件,直接在web层查询
DetachedCriteria dc=DetachedCriteria.forClass(User.class);//创建离线criteria
dc.add(Restrictions.eq("id", "1"));//组装查询条件
Criteria c=dc.getExecutableCriteria(session);//关联session
List<User> clist = c.list();
System.out.println(clist);
*/
}
@Test
//原生SQL查询(复杂的业务查询)
public void funthree(){
Session session = HibernateUtil.openSession();
Transaction tx = session.beginTransaction();
/*基本查询*/
String sql="select * from user";
SQLQuery query = session.createSQLQuery(sql);
/*条件查询*/
// String sql="select * from user where id=?";
// SQLQuery query = session.createSQLQuery(sql);
// query.setParameter(0, "1");
/*条件查询*/
/*分页查询*/
// String sql="select * from user limit ?,?";
// SQLQuery query = session.createSQLQuery(sql);
// query.setParameter(0, 0);
// query.setParameter(1, 1);
/*分页查询*/
/*不指定类型时*/
// List<Object[]> list = query.list();//注意泛型要用<Object[]>
// for (Object[] obj : list) {
// System.out.println(Arrays.toString(obj));
// }
/*不指定类型时*/
System.out.println("————————————————");
/*指定类型时*/
query.addEntity(User.class);//指定将结果集封装到哪个对象中
List<User> list2 = query.list();
System.out.println(list2);
/*指定类型时*/
tx.commit();
session.close();
}
}