2019最新《java基础教程项目实战》

一:搭建hibernate的使用环境

二:对象在hibernate中的三种状态、增(增加完成后可以返回该条数据的主键)删改查、分页查询、总记录查询

三:hibernate中的关系

四:缓存分析

五:事务、延迟加载、乐观锁(version)、C3PO连接池(现在来讲,比较古老了)、两种session的获取与区别

六:总结

一:搭建hibernate的使用环境

要使用hibernate完成对数据库的持久化操作,首先要实现以下配置:
①在eclipse的java Project项目中导入hibernate所必须的jar包;

②在src下新建hibernate.cfg.xml主配置文件----设置数据库连接、配置hibernate具备的属性、导入实体类映射文件等

<?xml version="1.0" encoding="UTF-8"?> com.mysql.jdbc.Driver    jdbc:mysql://localhost:3306/sh?characterEncoding=UTF-8    root    root
<!-- hibernate配置 -->
    <property name="dialect">org.hibernate.dialect.MySQLDialect</property>        
    <property name="current_session_context_class">thread</property>        
    <property name="show_sql">true</property>        
    <property name="hbm2ddl.auto">update</property>
<!-- 映射文件 -->    
    <mapping resource="hibernate/Hero.hbm.xml"/>    
</session-factory>
1
2
3
4
5
6
7
8
此配置中声明了hibernate连接那个数据库,以及对hibernate的设置,
dialect是告诉数据库我连接的是MySQL,请在生成SQL语句或者其他操作时,按照MySQL的语法来执行;

current_session_context_class是hibernate的事务管理方式,即每个线程代表一个事务;

show_sql为true时,是配置了在控制台打印生成的SQL语句;

hbm2ddl.auto这个配置代表自动更新表结构,也就是hibernate可以自动的在数据库中创建表。无需自行创建。

mapping resource指向了实体类与数据库字段做映射的配置文件路径。

③src下新建pojo包,创建实体类Hero.java,设置name和id属性,并给出get、set方法;

④src下新建hibernate文件夹,创建Hero.hbm.xml文件

<?xml version="1.0" encoding="UTF-8"?> package指向的是该实体类所在的包,以src为根目录。
标签即代表一个映射类。在该标签属性中,name属性是对应的package包下的需要进行映射的实体类,table对象数据库中的表名。

在class标签中,必须设置,因为他声明了该表的主键对应实体的那个属性。name是属性名,column代表对应哪个字段,该配置是说该id的增长方式按照配置的数据库的增长方式来(例如数据库中没有该表,则hibernate会创建这个表,并设置id为主键,设置为自增长)

该标签是配置除主键外其他的属性与字段的映射关系,name是属性,column是字段。

⑤src下新建action包,创建Test.java文件

public class Test {
public static void main(String[] args) {
SessionFactory sf = new Configuration().configure().buildSessionFactory();
Session s = sf.openSession();
s.beginTransaction();
Hero hero = new Hero();
hero.setName(“女警”);
s.save(hero);
s.getTransaction().commit();
s.close();
sf.close();
}
}
此时,右键运行该文件,则数据库中会生成hero表,并插入了一条数据。一套完整的hibernate配置搭建就完成了并能够成功运行。此时就能够感受到,hibernate的面向对象的思想,通过操作对象的方式完成对数据的持久化。似不似很方便了。

二:增删改查

对象在hibernate中的三种状态:瞬时、持久、托管。

当对象被new创建,并设置了属性值,没有跟hibernate发生任何关系,JVM停止运行,该对象就烟消云散。此时为瞬时状态
该对象与hibernate发生了关系,并且有对象的session,在数据库中有对应的记录,且该对象存在session的缓存中。则该对象为持久化状态。
该对象在数据库中有对应的一条记录,但是session被关闭了,该对象不存在session的缓存中了。对象不能跟数据库进行通讯,它恢复成了一个普通的对象了。此时为托管状态。例如通过session的get方法获取到id为1的hero对象,然后session关闭了,hero对象虽然有个数据库查询出来的值,但它此时仅仅是一个hero对象,修改它与数据库没有任何关系了。
对于session对象来讲,他就是代表一次程序与数据库的对象,当它开启后,相当于设置了映射关系的对象就可以与数据库进行通讯,通过修改对象完成对数据库的操作。此时对象就是处于持久化的状态。当session关闭后,通讯切断。程序恢复正常。

通过hibernate完成数据库的操作过程中,大多可遵循以下顺序:

创建sessionFactory, 通过sessionFactory打卡一个session对象,该session对象开启一个事务(相对于开启一个线程)

执行数据库操作逻辑,session对象提交事务,关闭session,关闭sessionFactory。

以增加为例,如下:
public class Test {
public static void main(String[] args) {
//创建sessionFactory
SessionFactory sf = new Configuration().configure().buildSessionFactory();
Session s = sf.openSession();//通过sessionfactory打开一个session对象
s.beginTransaction();//session对象开启一个事务
Hero hero = new Hero();
hero.setName(“女警”);
s.save(hero);//执行数据库操作
s.getTransaction().commit();//session对象提交事务
s.close();//关闭session
sf.close();//关闭sessionfactory
}
}
在此过程中,当session.save方法执行之后,其实可以观察到数据已经传递到数据库那里去了,相当于在程序与数据库之间,有一个中间层,当执行save方法之后,该数据被放到了中间层,只有在session把该事物提交之后,才真正的锤落定音,持久化到了数据库中。之前我们在hibernate.cfg.xml配置文件声明了一个事务一个线程,因为事务具有线程不安全性,所以我们在使用hibernate时,要做到一个数据库操作创建一个session,使用完后关闭掉。

使用save保存一条数据可以通过int id = (Integer)s.save(hero)这种方式获取到save返回来的这条数据的主键。

删除即调用session的delete(hero)即可完成

修改调用update(hero)即可完成,这里通过get(实体类.class,id值)的方式获取id为1的对象,然后修改该对象的属性,执行update完成更新,如下:

public class Test {
public static void main(String[] args) {
SessionFactory sf = new Configuration().configure().buildSessionFactory();
Session s = sf.openSession();
s.beginTransaction();
Hero hero = new Hero();
hero = (Hero)s.get(Hero.class, 1);
hero.setName=“女警改1”;
s.update(hero);
s.getTransaction().commit();
s.close();
sf.close();
}
}
4. 查询就有点多样化了。

①首先可以通过get()或者 load()方法获取,这两种方法的区别会在下面进行介绍。

②通过hql获取,hibernate的专门用于查询的语句,不同于sql,比如hql在查询时,使用类名而不是表明,select Hero where id=1

public class Test {
public static void main(String[] args) {
SessionFactory sf = new Configuration().configure().buildSessionFactory();
Session s = sf.openSession();
s.beginTransaction();
String name = “女”;
Query q =s.createQuery(“from Hero p where p.name like ?”);
q.setString(0, “%”+name+"%");
List ps= q.list();
for (Hero p : ps) {
System.out.println(p.getName());
}
s.getTransaction().commit();
s.close();
sf.close();
}
}
即完成了对hero表中的数据进行模糊查询,并通过q.list(),返回查询到的数据集合。

③SQL,同样使用SQL进行模糊查询如下:

    String name = "女";         
    String sql = "select * from hero  where name like '%"+name+"%'";         
    Query q= s.createSQLQuery(sql);
    List<Object[]> list= q.list();
    for (Object[] os : list) {
        for (Object filed: os) {
            System.out.print(filed+"\t");
        }
        System.out.println();
    }
1
2
3
4
5
6
7
8
9
10
使用SQL查询list返回的是一个object类型的集合。

④Criteria进行查询,这种查询方式是完全面对对象的方式进行查询:

     String name = "女";          
    Criteria c= s.createCriteria(Hero.class);
    c.add(Restrictions.like("name", "%"+name+"%"));
    List<Hero> ps = c.list();
    for (Hero p : ps) {
        System.out.println(p.getName());
    }
1
2
3
4
5
6
7
有关更多Criteria的使用方法,可以查询hibernate的官方文档或者论坛使用手册。

对于分页查询和总记录查询:
可以事情hql查询,调用q.uniqueResult()方法获取总数。

    String name = "女";         
    Query q =s.createQuery("select count(*) from Hero  where name like ?");
    q.setString(0, "%"+name+"%");
    long total= (Long) q.uniqueResult();
    System.out.println(total);
1
2
3
4
5
hibernate的分页查询,hibernate使用Criteria来进行分页查询,使用十分的简单。

c.setFirstResult(2); 表示从第3条数据开始
c.setMaxResults(5); 表示一共查询5条数据

    String name = "女";       
    Criteria c= s.createCriteria(Hero.class);
    c.add(Restrictions.like("name", "%"+name+"%"));
    c.setFirstResult(2); //表示从第三条数据开始,相当于limit的第一个参数
    c.setMaxResults(5);  //显示5条数据,相当于limit的第二个参数
1
2
3
4
5
三:hibernate中的关系

多对一、一对多、多对多关系。

多对一:
多个Product对应一个Category ,大致理解就是,在product类中增加Category属性,在保存该product时,设置setCategory属性。此时通过配置映射文件中的多对一关系,会在product表中自动添加cid(cid的值为该Category对象的主键)作为该表的外键。

创建Product、Category类,并配置映射文件。在Product.hbm.xml文件中配置增加多对一关系。代表Product类中的category属性对应的是Category这个映射类,并对应product数据库中的cid。

将这两个映射文件添加到hibernate.cfg.xml中,在test类中,此时更新p时,p的cid即为c对象的主键id。
    Category c =new Category();
    c.setName("c1");
    s.save(c); 
    Product p = (Product) s.get(Product.class, 8);
    p.setCategory(c);
    s.update(p);
1
2
3
4
5
6
一对多
一个Category对应多个Product ,大概意思就是一个分类中有多个产品,在Category实体中增加属性set products代表这个Category对象中的product集合。在Category映射文件中配置了一对多关系后,查询一条Category对象的值,通过获取products属性,就可以获取到product表中cid的值为该Category对象主键的所有product记录。

配置文件如下:通过标签进行设置,因为我们的products属性是set类型的。name为该属性的名。lazy为是否延迟加载,有关延迟加载后面会有介绍。key代表这个表对应的外键是cid,为配置一对多关系,class为一对多的多是那个类。

在test.java 中,查询id为1的Category对象记录,并获取products属性,将该属性遍历输出,即可得到product表中所有cid为1的product记录。
    Category c = (Category) s.get(Category.class, 1);
    Set<Product> ps = c.getProducts();
    for (Product p : ps) {
        System.out.println(p.getName());
    }
1
2
3
4
5
多对多
①一个用户User可以购买多个Product,一个product可以被多个User用户购买,则user和product为多对多关系。

②创建user类,user类中添加set products。product中添加set users属性。

③在user.hbm.xml中:设置多对多关系,也就是相当于给products这个属性设置多对多关系。并告诉数据库,user与product的对应关系保存在user_product这张表中。

key代表这个对象在user_product表中的主键,也就是说获取一条user对象时,然后查看他买了哪些product。需要去user_product表中寻找uid为user的主键的对应的所有pid记录,即该用户对应的多个product是哪些。

many-to-many中设置了class,也就是这个products集合属性对应的哪个类,column的意思是在user_product表中创建字段pid,当插入一个user记录时,获取到user中所有product对象,把对象的Product类中映射对应的主键,插入到这个pid中。一个uid可以对应多个pid。在数据库中形成一对多关系

代表user的id为1的对象对应了id为2,3,4,5的四个product对象。
--------------------- 
 

猜你喜欢

转载自blog.csdn.net/a879795296/article/details/89763797