1、看看JDBC(Java Database Connector)的一些缺点:
缺点
1.编程的时候很繁琐,用的try和catch比较多(需要关闭ResultSet rs ,Statement stmt,Connection conn)。
2.jdbc没有做数据的缓存(如果我们要实现每10s查询1000万条数据,没有缓存会挂掉)。
3.没有做到面向对象编程(我们操作数据库,每次都要先拿到connect,在创建sql发送对象,执行sql,关闭对象,没有面向对象).
4.sql语句的跨平台性很差(如果我们用mysql,后面需要切换到oracle,因为sql语句都不一样,移植很麻烦)
优点
效率比较高(封装度越高肯定会牺牲效率的,因为hibernate底层也是用到jdbc。所以对性能要求比较高可以直接使用jdbc)。
2、看看Hibernate的一些优缺点:
hibernate的优点
1.完全的面向对象编程(我们只要配置好xml,使用直接调用API就可以,不用写sql语句,hibernate会拼接)
2.hibernate的缓存很厉害(一级缓存,二级缓存,查询缓存 )
3.编程的时候就比较简单了
4.跨平台性很强(我们替换数据库,只需要改配置文件,hibernate会拼接对应数据库的sql语句)
5.使用场合就是企业内部的系统(因为hibernate操作数据库大于1000万条的时候会有问题,所以只适合企业内部使用,数据量不那么大)。
hibernate的缺点
1.效率比较低
2.表中的数据如果在千万级别,则hibernate不适合
3.如果表与表之间的关系特别复杂,则hibernate也不适合
3、Hibernate使用步骤:
a.创建一个工程。
就创建一个java工程就OK
b.导入jar包。
扩展知识
代理对象的三种创建方式:
1、jdkproxy(基于接口的,代理对象实现目标对象相同的接口)
2、cglib(第三方的,基于子类,代理对象是目标的子类)
3、javassist
c.hibernate.cfg.xml。
主要的用途:
告诉hibernate连接数据库的信息,用的什么样的数据库(方言)
根据持久化类和映射文件生成表的策略
/src/hibernate.cfg.xml
<hibernate-configuration>
<session-factory>
<property name="connection.username">rootproperty>
<property name="connection.password">rootproperty>
<property name="connection.driver_class">
com.mysql.jdbc.Driver
property>
<property name="connection.url">
jdbc:mysql://localhost:3306/example_hibernate
property>
<property name="dialect">
org.hibernate.dialect.MySQLDialect
property>
<property name="hbm2ddl.auto">updateproperty>
<property name="show_sql">trueproperty>
<mapping
resource="com/example/hibernate/domain/Person.hbm.xml" />
session-factory>
hibernate-configuration>
d.编写持久化类。
持久化类:说白了就是数据库中表的体现,字段和表中一一对应,并且有关联表的持久化类在里面。
com.example.hibernate.domain.Person
/**
* 实现了Serializable的主要的作用是为了在网络上传输,实现了这个接口,jvm会把对象转化为二进制数据,便于传输。
*/
public class Person implements Serializable{
//字段名称和数据库的表字段对应
private Long pid;
private String name;
private String description;
public Person(){}
public Long getPid() {
return pid;
}
public void setPid(Long pid) {
this.pid = pid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
e.编写映射文件。
com.example.hibernate.domain.Person.hbm.xml
<hibernate-mapping>
<class name="com.example.hibernate.domain.Person" table="person">
<id name="pid" column="pid" length="5">
<generator class="increment">generator>
id>
<property name="name" length="20" type="string">property>
<property name="description" length="50" type="java.lang.String">property>
class>
hibernate-mapping>
f.生成表。
com.example.hibernate.db.CreateTable
public class CreateTable {
@Test
public void testCreateTable(){
Configuration configuration = new Configuration();
configuration.configure();
configuration.buildSessionFactory();
}
}
这样就可以在数据中产生一个空的person表了
g.现在都配置好了,可以使用hibernate进行crud(create,retieve,update,delete)操作了。
com.example.hibernate.crud.PersonDao
public class PersonDao {
/**
* 保存person
*/
@Test
public void testSavePerson(){
//加载了hibernate的配置文件
Configuration configuration = new Configuration();
configuration.configure();
//configuration.configure("");//按照指定的路径加载指定的配置文件
SessionFactory sessionFactory = configuration.buildSessionFactory();
//产生session
Session session = sessionFactory.openSession();
//产生事务
Transaction transaction = session.beginTransaction();
//创建一个对象
Person person = new Person("aa");
person.setName("zhangsan");
person.setDescription("man");
//保存该对象
session.save(person);
//事务提交,session关闭
transaction.commit();
session.close();
}
@Test
public void testGetPersonById(){
Configuration configuration = new Configuration();
configuration.configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
/**
* 第一个参数为持久化类的class形式
* 第二个参数为主键的值
*/
Person person = (Person)session.get(Person.class, 1L);
System.out.println(person.getName());
session.close();
}
@Test
public void testUpdate(){
/**
* 1、先根据ID把要修改的对象查询出来
* 2、对对象进行修改
*/
Configuration configuration = new Configuration();
configuration.configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
/**
* 先根据主键把其中的一行数据查询出来,查询出来的就是一个对象
*/
Person person = (Person)session.get(Person.class, 1L);
/**
* 修改person对象
*/
person.setDescription("super man");
//执行修改操作
session.update(person);
transaction.commit();
session.close();
}
@Test
public void testDelete(){
/**
* 1、根据id把对象查询出来
* 2、删除该对象
*/
Configuration configuration = new Configuration();
configuration.configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
/**
* 把pid为1的对象提取出来
*/
Person person = (Person)session.get(Person.class, 1L);
//删除一个对象
session.delete(person);
transaction.commit();
session.close();
}
}
注意:
1.配置文件可以随意放,查看源码可以看到configure也是调用了带参的 configuration.configure("");
4、sessionFactory对象介绍:
SessionFactory接口负责初始化Hibernate。它充当数据存储源的代理,并负责创建Session对象。
读取hibernate.cfg.xml的时候就初始化好了。
特点:
1.hibernate中的配置文件、映射文件、持久化类的信息都在sessionFactory中
2.sessionFactory中存放的信息都是共享的信息
3.sessionFactory本身就是线程安全的(如果在tomcat中,在启动的时候就已经加载好了,所以是线程安全的)
4.一个hibernate框架sessionFactory只有一个
5.sessionFactory是一个重量级别的类
5、session对象介绍:
提起来Session的话,首先想到的是http的session,在hibernate中的session并不是http中所说的session。
一般把HttpSession对象称为用户会话,而hibernate中的Session是用来表示,应用程序和数据库的一次交互(会话)。
通常将每个Session实例和一个数据库事务绑定,也就是每执行一个数据库事务,都应该先创建一个新的Session实例,
在使用Session后,还需要关闭Session。
特点:
1、得到了一个session,相当于打开了一次数据库的连接
2、在hibernate中,对数据的crud操作都是由session来完成的
6、transaction对象介绍:
hibernate中的事务默认不是自动提交的。
只有产生了连接,才能进行事务的操作。所以只有有了session以后,才能有transaction
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();//看底层源码,设置了JDBC的connection的setAutoCommit为false
.
.
.
transaction.commit();
session.close();
8、hibernate配置文件中的类型:
a.hibernate类型
这个效率比较低,因为内部还需要转化。
b.java类型
该种类型的效率比较高
在hibernate内部,为了一张表,这张表中有如下的映射关系:
hibernate类型 java类型 数据库的字段的类型
string java.lang.String varchar
例如:Person.hbm.xml
<hibernate-mapping>
<class name="com.itheima12.hibernate.domain.Person" table="person">
<id name="pid" column="pid" length="5">
<generator class="increment">generator>
id>
<property name="name" length="20" type="string">property>
<property name="description" length="50" type="java.lang.String">property>
class>
hibernate-mapping>
一般我们用java类型就好了。
9、hibernate中主键产生机制
在配置文件 Person.hbm.xml 中配置主键的类型,我们默认使用increment。
下面介绍几种不同的类型之间的区别
先创建一个Utils的工具类
com.itheima12.hibernate.utils.HibernateUtils
public class HibernateUtils {
public static SessionFactory sessionFactory;
static{
Configuration configuration = new Configuration();
configuration.configure();
sessionFactory = configuration.buildSessionFactory();
}
}
a.increment
/**
* select max(pid) from person
* 先找到主键的最大值,在最大值基础上加1
* 所以该主键必须是数字类型,对应的持久化类里面的字段需要是数字类型
*/
@Test
public void testIncrement(){
Session session = HibernateUtils.sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
Person person = new Person();
person.setName("123");
session.save(person);
transaction.commit();
session.close();
}
b.assigned
/**
* 在程序中手动的设置主键的值
*/
@Test
public void testAssigned(){
Session session = HibernateUtils.sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
Person person = new Person();
person.setName("123");
person.setPid(2L);//如果不手动分配主键值,就会报错
session.save(person);
transaction.commit();
session.close();
}
c.identity
/**
* 表的自动增长机制
* 主键必须是数字类型
* 该效率比increment要高,但是id值不连续
*/
@Test
public void testIdentity(){
Session session = HibernateUtils.sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
Person person = new Person();
person.setName("123");
session.save(person);
transaction.commit();
session.close();
}
d.uuid
/**
* uuid的字符串是由hibernate内部生成的
* 要求主键必须是字符串类型
*/
@Test
public void testUUID(){
Session session = HibernateUtils.sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
Person person = new Person();
person.setName("aaa");
session.save(person);
transaction.commit();
session.close();
}
10、hibernate对象的状态(3种状态)
a.临时状态:new出来的对象在内存中
b.持久化状态:将对象加载进hibernate框架中
c.脱管状态:session使用完了,对象重新回到内存,可被GC回收。
各状态的简单示意图
现在看看session的各种方法,对象的状态是怎么转化的
持久化类,配置文件,Utils的代码同上。
a.save
//该方法可以把一个对象从临时状态转换成持久化状态
@Test
public void testSave(){
SessionFactory sessionFactory = HibernateUtils.sessionFactory;
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
Person person = new Person();
person.setName("123");
session.save(person);
transaction.commit();
session.close();
}
b.get
//从数据库中根据主键提取出一个对象,该对象就是一个持久化状态的对象
@Test
public void testGet(){
SessionFactory sessionFactory = HibernateUtils.sessionFactory;
Session session = sessionFactory.openSession();
Person person = (Person)session.get(Person.class, 1L);//持久化状态
session.close();
}
c.update
//把一个对象变成持久化状态
@Test
public void testUpdate(){
SessionFactory sessionFactory = HibernateUtils.sessionFactory;
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
Person person = (Person)session.get(Person.class, 1L);//持久化状态
person.setDescription("111");
//session.update(person);//update方法就是把一个对象的状态变成持久化状态,person对象已经是持久化状态了,所以这行代码不需要写
transaction.commit();
session.close();
}
d.evict
//把一个对象从持久化状态转化为脱管状态
@Test
public void testEvict(){
SessionFactory sessionFactory = HibernateUtils.sessionFactory;
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
Person person = (Person)session.get(Person.class, 1L);//持久化状态
person.setDescription("111");
session.evict(person);//该方法可以把一个持久化状态变成脱管状态
session.update(person);//由脱管状态的对象变成持久化状态
transaction.commit();
session.close();
}
e.clear
//把所有的hibernate中的持久化对象都转换成脱管状态的对象
@Test
public void testClear(){
SessionFactory sessionFactory = HibernateUtils.sessionFactory;
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
Person person = (Person)session.get(Person.class, 1L);//持久化状态
person.setDescription("111");
Person person2 = new Person();
person2.setName("88");
session.save(person2);//person2是一个持久化状态的对象
session.clear();//把hibernate里面的所有的对象都变成脱管状态的对象
transaction.commit();
session.close();
}
11、hibernate中的对象副本。
hibernate中只要是查询,就会创建对象的副本。副本中的数据和数据库里面的数据保持一致。
Person person = (Person)session.get(Person.class, 1L);//持久化状态
为什么要创建副本呢?
我们不希望频繁的和数据库交互,这样效率很低。比如我们查询了一个数据,我们没有修改或者修改的值和副本中的一样,
我们就没必要把数据再重新插入到数据库了,这样就减少了和数据库的交互,虽然会牺牲点内存。