Hibernate学习笔记3

时间:2023-03-08 19:29:31

---恢复内容开始---

一、hibernate如何转化jdbc代码实例【通过hibernate构建jdbc后往数据库传对象】

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.jdbc.Work;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.***.bean.User;
/**
*通过hibernate构建jdbc后往数据库传对象
* @author Victor
*
*/
public class JdbcHibernate {
private SessionFactory sf;
private Session session;
private Transaction tran;
@Before
public void before(){
Configuration con=new Configuration().configure();
sf=con.buildSessionFactory();
session=sf.openSession();
tran=session.beginTransaction();
}
@After
public void after(){
//把SQL语句刷到数据库,执行的是单纯的SQL语句
//把对象刷到数据库中,调用对象的get方法
//给?占位符赋值
tran.commit();
//关闭session【因为session不安全】
//也会提交事务
session.close();
}
@Test
public void AutoCreateTable() {
try {
Configuration con=new Configuration().configure("/hibernate.cfg.xml");
SchemaExport create=new SchemaExport(con);
create.create(false, true);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
@Test//传单个对象【通过JDBC传对象】
public void hibernate_jdbcInsertSingle(){
//session.connection();
try {//内部类实现
session.doWork(new Work() {
@Override
public void execute(Connection conn) throws SQLException {
// TODO Auto-generated method stub
Statement sts=conn.createStatement();
String sql="insert into s_user values(1,'briup',1)";
//写死的SQL语句只能插入一个对象
sts.execute(sql);
}
});
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}

}
@Test//传多个对象【通过JDBC传对象】
public void hibernate_jdbcInsertMany(){
User u=new User();
u.setId(1);
u.setName("舒肤佳");
u.setGender(true);
JdBC_WorkImpl work=new JdBC_WorkImpl(u);
session.doWork(work);
User u1=new User();
u1.setId(2);
u1.setName("舒肤佳");
u1.setGender(true);
JdBC_WorkImpl work1=new JdBC_WorkImpl(u1);
session.doWork(work1);
}
class JdBC_WorkImpl implements Work{
private User user;
public JdBC_WorkImpl(User user){
this.user=user;
}
@Override
public void execute(Connection conn) throws SQLException {
// TODO Auto-generated method stub
int a;
if(user.getGender()==true){
a=1;
}else {
a=0;
}
Statement sts=conn.createStatement();
String sql="insert into s_user values("+user.getId()+",'"+user.getName()+"',"+a+")";
sts.execute(sql);
}
}
}

二、操作hibernate二级缓存实例

import org.hibernate.CacheMode;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.***.bean.User;
/**
* hibernate二级缓存操作
* @author Victor
*
*/
public class HibernateSessionFactory {
private SessionFactory sf;
private Session session;
private Transaction tran;
@Before
public void before(){
Configuration con=new Configuration().configure();
sf=con.buildSessionFactory();
session=sf.openSession();
tran=session.beginTransaction();
}
@After
public void after(){
//把SQL语句刷到数据库,执行的是单纯的SQL语句
//把对象刷到数据库中,调用对象的get方法
//给?占位符赋值
tran.commit();
//关闭session【因为session不安全】
//也会提交事务
session.close();
}
@Test
public void AutoCreateTable() {
Configuration con=new Configuration().configure("/hibernate.cfg.xml");
SchemaExport create=new SchemaExport(con);
create.create(false, true);
}
@Test
public void cache_sendSessionFactory(){
try {
User u=new User();
u.setName("lisi");
u.setGender(true);
//save 把对象放到session缓存中,
//同时调用insert语句
session.save(u);
//session.clear();
//sf.evict(User.class);
User s=(User) session.get(User.class, 1L);
System.out.println(s);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
@Test
public void cache_sendSessionFactory1(){
User u=new User();
u.setName("lisi");
u.setGender(true);
//save 把对象放到session缓存中,
//同时调用insert语句
session.save(u);
//tran.commit();
//sf.evict(User.class);
//session.clear();
//把只能读的内容放在二级缓存中去
session.setCacheMode(CacheMode.GET);
//把写的内容写到二级缓存中
//session.setCacheMode(CacheMode.PUT);
User s=(User) session.get(User.class, 1L);
System.out.println(s);
}
}

.cfg.xml配置文件:

<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- 数据库的方言 -->
<property name="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</property>
<property name="hibernate.hbm2ddl.auto">create</property>
<!-- 数据库的四要素 -->
<property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="hibernate.connection.username">victor</property>
<property name="hibernate.connection.password">victor</property>
<property name="hibernate.connection.url">jdbc:oracle:thin:@localhost:1521:XE</property>
<property name="current_session_context_class">thread</property>
<property name="hibernate.cache.use_second_level_cache">true</property>
<property name="hibernate.cache.provider_class">org.hibernate.cache.HashtableCacheProvider</property>

<class-cache usage="read-only" class="com/***/bean/User.hbm.xml"/>
<property name="hibernate.show_sql">true</property>
<property name="format SQL in log and console hibernate.format_sql">true</property>
<mapping resource="com/***/subgroup/Animal.hbm.xml"/>
<mapping resource="com/***/subgroup/Customer.hbm.xml"/>
<mapping resource="com/***/bean/User.hbm.xml"/>
<mapping resource="com/***/bean/Person.hbm.xml"/>
</session-factory>
</hibernate-configuration>

三、openSession和getSession测试实例

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.After;
import org.junit.Before;
/**
*getCurrentSession()获取测试实例
*Session session=sf.openSession();和Session session1=sf.getCurrentSession();
*开启的session和获取的session不是同一个session
*因为在获取getCurrentSession()时会创建一个新的session
*前提是配置#current_session_context_class thread
* @author Victor
*
*/
public class GetCurrentSessionTest {
private SessionFactory sf;
private Session session;
private Transaction tran;
@Before
public void before(){
Configuration con=new Configuration().configure();
sf=con.buildSessionFactory();
session=sf.openSession();
tran=session.beginTransaction();
}
@After
public void after(){
//把SQL语句刷到数据库,执行的是单纯的SQL语句
//把对象刷到数据库中,调用对象的get方法
//给?占位符赋值
tran.commit();
//关闭session【因为session不安全】
//也会提交事务
session.close();
}
@org.junit.Test
public void getCurrentSession(){
//获取session
try {
Session session1=sf.getCurrentSession();
Session session2=sf.getCurrentSession();
Session session3=sf.getCurrentSession();
Session ss1=sf.openSession();
Session ss2=sf.openSession();
Session ss3=sf.openSession();
System.out.println(session1==session2);
System.out.println(session2==session3);
System.out.println(session1==session3);
System.out.println("---------------");
System.out.println(ss1==ss2);
System.out.println(ss2==ss3);
System.out.println(ss1==ss3);
System.out.println("+++++++++++++++");
Session ss4=sf.openSession();
Session s4=sf.getCurrentSession();
System.out.println(ss4==s4);
System.out.println(ss4.getClass());
System.out.println(s4.getClass());
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}

四、组件映射测试实例

<一>

测试类:

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.***.subgroup.Address;
import com.***.subgroup.Customer;
/**封装组件测试实例component【属性封装】并获取对象信息
* @author Victor
*
*/
public class CustomerTest {
private SessionFactory sf;
private Session session;
private Transaction tran;
@Before
public void before(){
Configuration con=new Configuration().configure();
sf=con.buildSessionFactory();
session=sf.openSession();
tran=session.beginTransaction();
}
@After
public void after(){
//把SQL语句刷到数据库,执行的是单纯的SQL语句
//把对象刷到数据库中,调用对象的get方法
//给?占位符赋值
tran.commit();
//关闭session【因为session不安全】
//也会提交事务
session.close();
}
@Test
public void AutoCreateTable() {
Configuration con=new Configuration().configure("/hibernate.cfg.xml");
SchemaExport create=new SchemaExport(con);
create.create(false, true);
}
@Test
public void insert(){
Customer customer=new Customer();
Address addr=new Address();
customer.setName("sichuan");
customer.setAddr(addr);
addr.setCity("cc");
addr.setProvince("vv");
addr.setStreet("bb");
session.save(customer);
//Customer c=(Customer) session.get(Customer.class, 1L);
Customer c=(Customer) session.load(Customer.class, 1L);
System.out.println(c);
/*String hql="from Customer";
Query query=session.createQuery(hql);
List<Customer> list=query.list();
for(Customer c1:list){
System.out.println(c1);
}*/
}
}

实体类

package com.***.subgroup;

public class Customer {
private long id;
private String name;
private Address addr;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddr() {
return addr;
}
public void setAddr(Address addr) {
this.addr = addr;
}
@Override
public String toString() {
//return "Customer [id=" + id + ": name=" + name + ": addr=" + addr + "]";
return id+"--"+name+"--"+addr.getCity()+"--"+addr.getProvince()+"--"+addr.getStreet();
}
}

封装类:

package com.***.subgroup;

public class Address {
private String province;
private String city;
private String street;
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
}

.hbm.xml配置文件:

<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.***.subgroup.Customer" table="s_customer">
<id name="id">
<generator class="native"></generator>
</id>
<property name="name"/>
<component name="addr" class="com.***.subgroup.Address">
<property name="province"/>
<property name="city"/>
<property name="street"/>
</component>
</class>
</hibernate-mapping>

<二>

测试类:

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.briup.subgroup.Dog;
import com.briup.subgroup.Pig;
/**
* 继承组件测试实例【子类继承父类】subclass
* @author Victor
*
*/
public class AnimalTest {
private SessionFactory sf;
private Session session;
private Transaction tran;
@Before
public void before(){
Configuration con=new Configuration().configure();
sf=con.buildSessionFactory();
session=sf.openSession();
tran=session.beginTransaction();
}
@After
public void after(){
//把SQL语句刷到数据库,执行的是单纯的SQL语句
//把对象刷到数据库中,调用对象的get方法
//给?占位符赋值
tran.commit();
//关闭session【因为session不安全】
//也会提交事务
session.close();
}
@Test
public void AutoCreateTable() {
Configuration con=new Configuration().configure("/hibernate.cfg.xml");
SchemaExport create=new SchemaExport(con);
create.create(false, true);
}
@Test
public void insert(){
try {
Dog dog=new Dog();
dog.setName("dog");
dog.setHeight(14);
Pig p=new Pig();
p.setName("pig");
p.setWeight(180.5);
session.save(dog);
session.save(p);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}

实体类【父类】:

package com.***.subgroup;
public class Animal {
private long id;
private String name;
private long gender;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getGender() {
return gender;
}
public void setGender(long gender) {
this.gender = gender;
}
}

实体类【子类一】:

package com.***.subgroup;

public class Pig extends Animal{
private Double weight;
public Double getWeight() {
return weight;
}
public void setWeight(Double weight) {
this.weight = weight;
}
}

实体类【子类二】:

package com.***.subgroup;

public class Dog extends Animal{
private double height;
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
}

.hbm.xml配置文件:

<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.***.subgroup.Animal" table="s_animal">
<id name="id">
<generator class="native"/>
</id>
<discriminator column="type" type="string"/>
<property name="name"/>
<property name="gender"/>
<subclass name="com.***.subgroup.Dog" discriminator-value="D">
<property name="height" column="height"/>
</subclass>
<subclass name="com.***.subgroup.Pig" discriminator-value="P">
<property name="weight" column="weight"/>
</subclass>
</class>
</hibernate-mapping>

总结:

hibernate一级缓存
一级缓存很短和session的生命周期一致,
一级缓存也叫
session级的缓存或事务级缓存

哪些方法支持一级缓存:
* get()
* load()
如何管理一级缓存:
* session.clear(),session.evict()
如何避免一次性大量的实体数据入库导致内存溢出
* 先flush,再clear
如果数据量特别大,考虑采用jdbc实现,如果jdbc也不能满足
要求可以考虑采用数据本身的特定导入工具

hibernate二级缓存

二级缓存也称进程级的缓存或SessionFactory级的缓
存,
二级缓存可以被所有的session共享
二级缓存的生命周期和SessionFactory的生命周期
一致
,SessionFactory可以管理二级缓存

二级缓存的配置和使用:
* 将echcache.xml文件拷贝到src下
* 开启二级缓存,修改hibernate.cfg.xml文件
<property name="hibernate.cache.use_second_level_cache">true</property>
* 指定缓存产品提供商,修改hibernate.cfg.xml文件
<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
* 指定那些实体类使用二级缓存(两种方法)
* 在映射文件中采用<cache>标签
* 在hibernate.cfg.xml文件中,采用<class-cache>标签

二级缓存是缓存实体对象的

了解一级缓存和二级缓存的交互
hibernate如何转化jdbc代码;

id的增长策略
gengerate表示id的自动生成器,class表示id的生成策略(以什么方式生成id)
1.assigned手动设置,也是默认的设置,
主键由外部程序负责生成,无需Hibernate参与。----如果要由程序
代码来指定主键,就采有这种
<id name="id" column="id" type="string">
<generator class="assigned" />
</id>
2.increment id自动增长,每次在最大的基础之上自动加一
对 long , short 或 int 的数据列生成自动增长主键。
increment主键生成方式的特点是与底层数据库无关性,
大部分数据库如 Mysql,MSSQL 和ORACLE等都支持
increament生成方式。
此方式的实现机制为在当前应用实例中维持一个变量,
以保存着当前的最
大值,之后每次需要生成主键的 时候将此值加1作为主键。
increment方式
的不足之处是当多个线程并发对数据库表进行写操作时
,可能出现相同的
主键值,发生主键重复的冲突,因此多线程并发操作时,
不应该使用此方法。
<id name="id" column="id">
<generator class="increment" />
</id>
3.sequence 默认使用sequence的序列生成id值,默认使用Hibernate_sequence的
3.1我们可以指定序列
在ORACLE等数据库中使用sequence生成主键。sequence的特点是
于数据库的相关性,
seqhio要求底层能支持sequence,列如Oracle。
数据库中的语法如下:
Oracle:create sequence seq_name increment by 1 start with 1;
需要主键值时可以调用seq_name.nextval或者seq_name.curval得到,数据库会帮助我们维护这个sequence序列,保证每次取到的值唯一,如:
insert into tbl_name(id, name) values(seq_name.nextval, ‘terry ren’);
<id name="id" column="id" type="long">
<generator class="sequence">
<param name="sequence">seq_name</param>
</generator>
</id>
4.identity自动增长策略,
如果数据列的类型是 long, short 或 int ,可使用主键生成器生
成自动增长Hibernate主键。与底层数据库有关,
要求数据库支持identify,如MySQL中是auto_increment,SQL Server
中是Identify.支持的数据库
有MySQL,SQL Server,DB2,Sybase和HypersonicSQL.(
好像不支持oracle) 无需Hibernate和用户的干涉,
使用较为方便,但不便于在不同的数据库之间移植程序。
identity的优点是不会发生 increment方式的并发错做问题。
数据库涉及到的表要设置自动增长。
<id name="id" column="id" type="long">
<generator class="identity" />
</id>
5.native根据本地数据库类型自己选择认为合适一种类型,默认悬着sequence则略
由Hibernate根据不同的数据库方言,
自行判断采用identity、hilo、sequence其中一种作为
Hibernate主键生成方式,native的 优点是与底层性无关,
便于不同数据库之间的移植,由Hibernate根据不同数据库选
择主键的生成方式。在oracle中需要创建叫
Hibernate_sequence名字的sequence,
如果设置了Hibernate.hbm2ddl.auto属性,
不需要手动建立序列,前提
是数据库帐号必须有Create Sequence这种高级权限。
mysql等数据库则不用建立sequence。
<id name="id" column="id">
<generator class="native" />
</id>
6.hilo id值通过高低位运算得到,
1.在数据库中,要有一张表来维护高位的值
2在数据库中地位我们需要指点一个范围循环,1-5
一般会从0或1到指定值循环,这要看数据库
id=hi*(max_lo+1)+lo lo值在0或1到最大max_lo之间循环,
lo每循环一圈,hi值加1

获得链接或用户自定义提供的链接中,不要使用这种生成器。
hilo方式需要维护表信息,
因此对数据的影响的要率会造成一定影响。
create table hi_value(next_hi number not null);
insert into hi_value(next_hi) values(1);
commit;
<id name="id" column="id">
<generator class="hilo">
<param name="table">hi_value</param>
<param name="column">next_hi</param>
<param name="max_lo">100</param>
</generator>
</id>

7.seqhilo 和上面不同的是,从序列中拿到一个高为的值
与hilo 类似,通过hi/lo 算法实现的主键生成机制,
只是主键历史状态保存在Sequence中,
适用于支持Sequence的数据库,
如Oracle。如果数据列的类型是 long, short 或 int可使用
该主键生成器。
<id name="id" column="id">
<generator class="seqhilo">
<param name="sequence">seq_name</param>
<param name="max_lo">100</param>
</generator>
</id>
8.uuid

9.guid
注意:如果想要使用uuid或guid就要把id改为String类型

hibernate对象的状态
1.瞬时态/*态,Transient
由new操作符创建(刚刚new出来的对象,在session缓存中还不存在),且尚未与hibernate session关联的对象
这种状态的对象也称为临时对象。
特点:不处于session的缓存中,即不被任何一个session实例关联,在数据库中没有记录关联

2、持久态,
对象已经被持久化,加入到session的缓存中,处于持久化状态的java对象被称为持久化对象
特点:处于一个session对象的缓存中,持久化对象在数据库中有对应的记录
session在清理缓存时(flush),会根据持久化对象的属性的变化来同步更新数据库;
3.脱管态/游离态Detached
对象已经被持久化,但不处于session的缓存中,处于
托管状态的java对象称为游离对象。
特点:不在位于session缓存中,机不被session关联
游离对象是由持久化对象转变过来的,因此存在数据库有相应的记录
和其对应

瞬时态对象和游离对象的比较
相同点:session缓存中没有这些对象,hiberntae不会保证
他们的属性变化与数据库保持同步。
不同点:前者在数据库中没有与之对应的记录,后者
由持久化对象转变而来,因此数据库中可能还存在与之对应的记录

注意:
hibernate只会保证持久态的对象属性的变化和数据库同步
,因此持久态对象在session的缓存中存在;

总结:hibernate只能管理做了映射的类的对象,对于一个
实体类的对象
1.session缓存中有没有这个对象
2.数据库中有没有这个对象对应的记录

注意:用主键的值来判断这两个问题十分成立,然后在根据这两个问题的结果来判断对象的状态

怎么判断一个对象在session的缓存中有没有,
看这个对象的主键值和session的缓存中对象的主键值有
没有相同的的,如果有说明这个对象在session的缓存中存在

怎么判断一个对象在数据库中有没有对应的记录,
看这个对象的主键值和数据库表中数据的主键值有没有相同的,如果有,则说明这个数据在数据库中有对应的记录

组件映射:继承和封装

---恢复内容结束---