Hibernate持久化类编写的规则
持久化:将内存当中的一个对象持久化到数据库当中的过程。Hibernate框架就是用来进行持久化的框架。
持久化类:一个Java对象与数据库的表建立了映射关系,那么这个类在Hibernate当中就可以称为持久化类
持久化类 = Java类 + 映射文件
(1)对持久化类提供一个无参数的构造方法 :Hibernate底层需要通过反射来生成实例
例如:
(2)对属性需要私有,对私有属性提供共有的get和set方法 :Hibernate当中要获取,设置这个对象的值。
(3)对持久化类通过一个唯一的标识OID与数据库的主键对应:Java当中通过对象的地址来区分是否是同一个对象,数据库当中通过主键来确定是否是同一个记录,在Hibernate当中通过持久化类的OID的属性来区分是否是同一个对象。
(4)持久化类当中的属性尽量要使用包装类的类型。Integer Long Double :因为基本数据类型的默认值是0,那么这个0就会有很多的歧义。(包装类的类型默认是null)
(5)持久化类不要使用final进行修饰:延迟加载本身是Hibernate的一个优化的手段。返回的是一个代理对象(Javassist可以对没有实现接口的类来产生代理—使用了十分底层的字节码增强的技术来,继承这个类进行代理,如果该类使用final就不能被继承,也就不能产生代理对象,延迟加载也就失效了,Hibernate的优化也就失效了,load方法就会和get方法变得一样)。
测试该特性
public final class Customer {
private Long cust_id;
private String cust_name;
private String cust_source;
private String cust_industry;
private String cust_level;
private String cust_phone;
private String cust_mobile;
public Long getCust_id() {
return cust_id;
}
public void setCust_id(Long cust_id) {
this.cust_id = cust_id;
}
public String getCust_name() {
return cust_name;
}
public void setCust_name(String cust_name) {
this.cust_name = cust_name;
}
public String getCust_source() {
return cust_source;
}
public void setCust_source(String cust_source) {
this.cust_source = cust_source;
}
public String getCust_industry() {
return cust_industry;
}
public void setCust_industry(String cust_industry) {
this.cust_industry = cust_industry;
}
public String getCust_level() {
return cust_level;
}
public void setCust_level(String cust_level) {
this.cust_level = cust_level;
}
public String getCust_phone() {
return cust_phone;
}
public void setCust_phone(String cust_phone) {
this.cust_phone = cust_phone;
}
public String getCust_mobile() {
return cust_mobile;
}
public void setCust_mobile(String cust_mobile) {
this.cust_mobile = cust_mobile;
}
public Customer() {
// TODO Auto-generated constructor stub
}
public Customer(Long cust_id, String cust_name, String cust_source, String cust_industry, String cust_level,
String cust_phone, String cust_mobile) {
super();
this.cust_id = cust_id;
this.cust_name = cust_name;
this.cust_source = cust_source;
this.cust_industry = cust_industry;
this.cust_level = cust_level;
this.cust_phone = cust_phone;
this.cust_mobile = cust_mobile;
}
@Override
public String toString() {
return "Customer [cust_id=" + cust_id + ", cust_name=" + cust_name + ", cust_source=" + cust_source+ ", cust_industry=" + cust_industry + ", cust_level=" + cust_level + ", cust_phone=" + cust_phone+ ", cust_mobile=" + cust_mobile + "]";
}
}
并且这时返回的对象是真实的对象不是代理对象
@Test
// 查询:
public void demo02() {
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();// 创建数据库事务对象开启事务
// 使用load方法查询
Customer customer = session.load(Customer.class, 2l);
System.out.println(customer);
tx.commit();// 提交事务// load方法发送SQL语句
session.close();
}
A、自然主键
自然主键:主键的本身就是表当中的一个字段(实体当中的具体的属性)。
a、创建一个人员表、人员都会有一个身份证号(唯一的不可重复的),使用了身份证号作为主键的,这种主键就称为的自然主键。
B、代理主键:主键的本身不是表中必须的一个字段(不是实体当中某个具体的属性)。
a、创建一个人员表,没有使用人员当中的身份证号,用了一个与这个表不相关的字段ID,(PND)。这种主键称为代理主键。
b、在实际的开发当中,尽量要使用代理主键。
c、一旦自然主键参与到业务逻辑当中。后期就有可能修改源代码。(好的程序的设计要满足OCP原则:对程序的一个扩展是open的。对修改原码是close的)
在实际开发中一般是不允许用户手动设置主键,一般会将主键数据库,手动编写程序进行设置。
在hibernate当中为了减少程序的编写,提供了很多的主键生成的策略。
A、increment:hibernate中提供的一个自动增长的一个机制。(mysql当中不会选自动增长,使用的Hibernate当中的)适用于short,int,long类型的主键。
在单线程的程序当中使用
a、首先发送一条语句,select max(id) from 查到表id:然后让id+1作为下一条记录的一个记录的主键。
B:identity:适用于short、int、long类型的主键,使用的是数据库底层的自动增长的机制。适用于有自动增长机制的数据库(MySQL,MSSQL)但是Oracle没有找到增长机制的。
C:sequnence:序列 适用于short、int、long类型的主键,采用的是序列的方式。(Oracle支持序列)。MySQL就不能使用sequnence
D : uuid:适用于字符串主键。使用Hibernate当中一种随机方式生成字符串类型的主键
E:native:本地策略,可以在identity和sequnence之间来进行自动切换
F:assigned:Hibernate会放弃外键的管理,需要通过自己手动编写程序或者用户自己进行设置。
G:foreign:外部的。一对一的一种关联映射的情况下使用。(例如两个表的主键是一一对应的)
A、increment:
在映射文件当中修改对应的生成键策略对应的class
public class HibernateUtils {
public static final Configuration cfg;
public static final SessionFactory sf;
static {
cfg = new Configuration().configure();
sf = cfg.buildSessionFactory();
}
public static Session openSession() {
return sf.openSession();
}
}
public class HibernateDemo1 {
@Test
// 保存一条记录
//演示increment
public void demo01() {
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
Customer customer = new Customer();
customer.setCust_name("王细");
session.save(customer);
transaction.commit();
session.close();
}
@Test
// 保存一条记录
//演示increment
public void demo02() {
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
Customer customer = new Customer();
customer.setCust_name("王被");
session.save(customer);
transaction.commit();
session.close();
}
}
1、使用Debug模式分别调试两个方法,分别在不同的线程当中调试
当第一个方法执行时
会先查询表当中的id的值,然后加1
将对应的属性的值放入到加1的id对应的表的项内
此时将数据插入到对应的表当中后,不提交事务
2、开始用第二个方法
会先查询表当中的id的值,然后加1
将对应的属性的值放入到加1的id对应的表的项内
对应相同的id上插入对应的数据,然后会报错
B:identity:
在映射文件当中修改对应的生成键策略对应的class
@Test
// 保存一条记录
//演示identity
public void demo03() {
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
Customer customer = new Customer();
customer.setCust_name("王被");
session.save(customer);
transaction.commit();
session.close();
}
D : uuid:
将Customer的id改为String类型的
在映射文件当中修改对应的生成键策略对应的class
@Test
// 保存一条记录
//演示uuid
public void demo04() {
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
Customer customer = new Customer();
customer.setCust_name("王被");
session.save(customer);
transaction.commit();
session.close();
}
F:assigned:
在映射文件当中修改对应的生成键策略对应的class
直接执行会报错,因为,没有设置主键的值,需要手动设置
@Test
// 保存一条记录
//演示assigned
public void demo05() {
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
Customer customer = new Customer();
customer.setCust_id(4556L);
customer.setCust_name("王被");
session.save(customer);
transaction.commit();
session.close();
}
一般用native和identity的比较多(int Long 的主键)
映射文件当中
Hibernate是持久层的一个框架,通过持久化类完成ORM操作。Hibernate为了更好的管理持久化类,就将持久化类分为三种状态。
持久化类=Java类+映射
这种对象没有唯一的标识OID,没有被session所管理。
这种对象有唯一的标识OID,被session所管理,这种对象就是持久态的对象。
持久化类的持久态对象。可以自动更新数据库,
这种对象有唯一标识的OID,没有被session管理,这个就称为托管态的对象。
A :获得瞬时态对象
获得:将与表建立好映射的类,new创建该类的对象,就创建了session的瞬时太对象
在这里为
Customer customer = new Customer();
B:状态转换
瞬时态,可以转换成为持久态(瞬时态->持久态)
save(Object obj);//通过save方法将瞬时态转换成为持久态
saveOrUpdate(Object obj);
瞬时太,可以转换成为托管态(瞬时太->托管态)
customer.setCust_id(1);//对象设置了id
A :获得持久态对象
get(Object.class,id);
Customer customer = session.get(Customer.class,1L);//直接获得持久态对象
load(Object.class,id);
Customer customer = session.load(Customer.class, 2l);
find(Object.class,id);
Customer customer = session.find(Customer.class, 2l);
iterate(Object.class,id);
Customer customer = session.iterate(Customer.class, 2l);
B:状态转换
持久态,可以转换成为瞬时态(持久态->瞬时态)
delete();、
session.delete(Object obj);
持久态,可以转换成为托管态(持久态->托管态)
close();
session.close();
clear();
session.clear();
evict(Object obj);
session.evict();
A :获得托管态对象
Customer customer = new Customer();
customer.setCust_id(1L);
B:状态转换
托管态,可以转换成为持久态(托管态->持久态)
update(Object obj);
session.update(Object obj);
saveOrUpdate(Object obj);
session.saveOrUpdate(Object obj);
Customer customer = new Customer();
customer.setCust_id(null);
@Test
// 持久态对象可以自动更新数据库----》依赖了Hibernate里面的一级缓存
public void demo02() {
Session session = HibernateUtils.openSession();// 链接数据库开启session域
Transaction transaction = session.beginTransaction();// 开启事务
//获得持久态对象
Customer customer = session.get(Customer.class, 1l);//持久态对象可以自动更新数据库
//当对应更改的数据与数据库当中的数据不同的时候,就不会更改数据库当中的数据
//当对应数据的数据与数据库当中的数据不同的时候就会更改其中的数据
customer.setCust_name("王南");
//这里可以不用去更新数据库
//session.update(customer);
transaction.commit();
session.close();// 关闭session对象,销毁对象
}