文章目录
持久化类的配置文件
class元素
<class> 元素用于指定类和表之间的映射。
name - 设定类名(包含路径);
table - 设定表名,默认以类名作表名。
<class>元素包含一个子元素及多个<property>子元素。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.hibernate.entity">
<!-- 类与表的映射 -->
<class name="User" table="USER">
<!-- 上面的类名与数据库名之所以可以简写,是因为 hibernate-mapping package属性规定了文件所处的包名 -->
<!-- 主键的映射,必选 -->
<id name="id">
<!-- 数据库的字段 -->
<column name="ID"></column>
<generator class="native"/>
</id>
<!--column可以通过嵌套的形式放在id标签里面 ,和上面那种形式等价
<id name="id" column="ID">
<generator class="native"/>
</id>
-->
<!-- id标签只有一个,且必须在property标签上面 -->
<property name="name" column="NAME" type="java.lang.String"></property>
<property name="password" column="PASSWORD"></property>
</class>
</hibernate-mapping>
id元素
<id> 子元素设定持久化类的 OID(对象标识符) 和表的主键的映射关系。
column – 指定表字段的名称;
generator – 元素指定 OID 的生成器。
property元素
<property>子元素设定类的其它属性和表的字段的映射关系。
name – 对应类的属性名称;
type – 指定属性的类型;可选
column – 指定表字段的名称;
not-null – 指定属性是否允许为空。
type的String类型因为是引用类型,所以得用全线命名java.lang.String,但是基本类型不需要,直接写int,char 什么的就行
column也是可选的,前提是字段名与属性名时一致的。即name属性值与column属性值时一样的
增删改查操作的实现
package com.hibernate.ui;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.hibernate.entity.User;
import com.hibernate.util.HibernateUtil;
public class Test {
public static void main(String[] args) {
// saveUser();
// getUserById();
updateUser();
//deleteUser();
//关闭SessionFactory
HibernateUtil.closeSessionFactory();
}
/*
* 增添操作
* */
public static void saveUser() {
Session session = null;
Transaction tx = null;
try {
//1. 打开Session
session=HibernateUtil.openSession();
//2. 开启数据库事务
tx = session.beginTransaction();
//3. 保存操作
User user=new User();
user.setName("李四");
user.setPassword("LiSi");
session.save(user);
//4. 提交事务
tx.commit();
} catch (Exception e) {
//捕获异常,事务回滚
tx.rollback();
} finally {
//5. 关闭Sesson,回收资源
session.close();
}
}
/*
* 查询操作
* */
public static void getUserById() {
//得到Session对象
Session session=HibernateUtil.openSession();
//参数1:要查询的对象类型,参数2:主键数值,最好是引用类型而不是基本类型
User user=session.get(User.class,new Integer(2));
System.out.println(user);
//打印时候为了美观,记得重写User类的toString方法
session.close();
}
/*
* 更新操作
* */
public static void updateUser() {
Session session = null;
Transaction tx = null;
try {
//1. 打开Session
session=HibernateUtil.openSession();
//2. 开启数据库事务
tx = session.beginTransaction();
//3. 更新操作(先查询,再修改,最后更新)
User user=session.get(User.class, new Integer(2));
user.setPassword("LiSi-2");
session.update(user);
//update方法更新时候,那条数据的所有项都更新了,哪怕没有变化
session.save(user);
//4. 提交事务
tx.commit();
} catch (Exception e) {
//捕获异常,事务回滚
tx.rollback();
} finally {
//5. 关闭Sesson,回收资源
session.close();
}
}
/*
* 删除操作
* */
public static void deleteUser() {
Session session = null;
Transaction tx = null;
try {
//1. 打开Session
session=HibernateUtil.openSession();
//2. 开启数据库事务
tx = session.beginTransaction();
//3.删除操作(先找到,再删除),实际删除的是数据库中的那条记录
User user=session.get(User.class, new Integer(1));
session.delete(user);
//4. 提交事务
tx.commit();
} catch (Exception e) {
//捕获异常,事务回滚
tx.rollback();
} finally {
//5. 关闭Sesson,回收资源
session.close();
}
}
}
单实体的属性映射
如果实体化类里没有相应的get与set方法是,就会找不到对性的数据进而无法实现实例化,这是Hibernate的默认访问对象属性的方法
实体类属性与表字段不对称时映射
需要查询非直接数据库数据时
例如,在user表中添加了totalOrders属性,需要查询订单表中的所有消费总额。
先创建订单数据库表,orders,属性为:
然后在user用户对象中增添上totalPrice属性,并设置相应的get与set方法,并且重写构造方法与toString方法,
在持久化类的配置文件中增添相应的属性
因为修改的是查询操作,所以在测试类中每当使用查询操作时候就可以看到效果了。
Hibernate的初始化
单实体的对象标识符映射
自然组件:例如学生的学号,具有一定的实际意义。
代理主键方式更常见。
Hibernate对象标识符 OID (区分对象)
帮助Hibernate区分在内存中这两个对象是不是同一个对象。
U1查询时第一次,内存无,是真正的查询
U2会判断内存有无结果,因为U1=U2所以,U2不查询,直接赋U1值
因为包装里面都是引用类型,所以为了方便定义OID时候采用包装器类型。
因为主键唯一,所以OID也唯一。
映射文件中OID的配置
generator 规定了OID的生成方式
Hibernate 自带了很多种标识符生成器:
increment 采用 Hibernate 数值递增的方式;
identity 采用数据库提供的自增长方式;
assigned 主键由应用逻辑产生;
---------上面三种是重点
sequence 采用数据库提供的序列方式;
hilo 通过hi/lo算法 // Hibernate 5.0 以后不支持;,高低位算法
seqhilo 通过hi/lo算法;
native 自动选择合适的标识符生成器;
uuid.hex 通过uuid算法。
increment标识符适用范围
由Hibernate程序生成;
先查数据库主键最大值,最大值+1在存入数据库新的数据。
SQL语句里有拼接的主键
identity标识符适用范围
SQL语句里没有ID字段,因为数据库可以自动递增主键
assigned 标识符适用范围
由程序内部赋值,插入之前需要手动赋值,不赋值的话不会执行插入语句。
这种方式强烈不建议,人为操作可能出现重复。
在程序内部赋值
注解映射单实体
注解映射配置的时候,只需要修改实体化类就可以,不用再创建实体化类的配置文件了。
不推荐,因为不美观,不清晰,重点还是上面的XML配置
@Entity:声明一个实体类。
@Table(name="table_name"):为实体类指定对应的数据库表。name就是表的名字
@Id:声明实体类的OID属性。
@GeneratedValue(generator="increment_generator"):声明OID的生成策略。
@GenericGenerator(name="increment_generator", strategy="increment"):使用Hibernate提供的生成策略。
先定义生成器,选择生存策略,然后被上面的注解调用。
映射什么属性,就加上什么Column注解
属性名与数据库字段名一致时也可以省略
配置映射文件源
package com.hibernate.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.annotations.GenericGenerator;
@Entity
//声明一个实体类
@Table(name="CUSTOMER")
//为实体类指定对应的数据库
public class Customer {
private Integer id;
private String name;
private int age;
//创建两个构造方法,一个有参数,一个无参数,缺一不可
public Customer() {
super();
}
public Customer(Integer id, String name, int age) {
super();
this.id = id;
this.name = name;
this.age = age;
}
@Id
//定义生成策略与别名,注意位置,在get,set方法之上
@GeneratedValue(generator = "linshi")
//应用下面定义的策略
@GenericGenerator(strategy="increment",name = "linshi")
//私有属性的get set方法
// @Column(name="id") 主键id自增长,所以可以注释掉
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@Column(name="name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Column(name="age")
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
@Override
public String toString() {
return "Customer [sum=" + sum + "]";
}
@Formula(value="(select sum(o.age) from customer as o where o.id>10)")
public int getSum() {
return sum;
}
public void setSum(int sum) {
this.sum = sum;
}