• Java框架之Hibernate(一)


    一、Hibernate - 核心接口

    它是  JBoss Community team (社区团队) 开发的。Hibernate 是一个开源的,对象关系模型框架 (ORM),它对JDBC进行了轻量的封装, 使java程序员可以面对象的方式进行数据库操作。Hibernate 一共有5个核心接口   

    1.Session 

    用于连接数据库,相当于 jdbc 中的 Connection (它和 servlet 中 的Session  一点关系也没有),负责执行对象的CRUD操作 ,它是非线程安全的。

    2.SessionFactory //用于得到 Session ,相当于jdbc中 DriverManager

    3.Transaction //用于事务管理

    4.Query 和 Criteria //主要用于查询数据

    5.Configuration //用于得到配置信息

    二、Hibernate - 类库简介

    Hibernate3.jar

    antlr-2.7.6.jar(必需):Hibernate使用ANTLR来产生查询分析器,这个类库在运行环境下时也是必需的。

    dom4j(必需):Hibernate使用dom4j解析XML配置文件和XML映射元文件。

    commons-collections-3.1,CommonsLogging(必需):Hibernat使用ApacheJakartaCommons项目提供的多个工具类库。

    dom4j-1.6.1(可选):Hibernate使用CommonsLoggingAPI,它也可以依次使用Log4j作为底层实施log的机制。

    如果上下文类目录中存在Log4j库,则CommonsLogging使用Log4j和并它在上下文类路径中寻找的log4j.properties文件。

    你可以使用在Hibernate发行包中包含中的那个示例Log4j的配置文件。这样,把log4j.jar和它的配置文件(位于src/目录中)拷贝到你的上下文类路径下,就可以在后台看到底程序如何运行的。

    javassist-3.12.0.GA 一个开源的分析、编辑和创建Java字节码的类库

    slf4j-api-1.6.1 为java提供的简单日志Facade。Facade:门面,更底层一点说就是接口

    jta-1.1.jar  Java事务API( Java Transaction API )

    其他文件是不是必需的:请察看Hibernate发行包中的lib/README.txt文件,这是一个Hibernate发行包中附带的第三方类库的列表,他们总是保持最新的。你可以在那里找到所有必需或者可选的类库(注意:其中的 "buildtimerequired" 指的是编译Hibernate时所需要而非编译你自己的程序所必需的类库)。

    三、第一个Hibernate 程序

    1) 导包

    2) 配置文件

    1)Hibernate 的主配置文件

     <?xml version='1.0' encoding='UTF-8'?>
           <!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="show_sql">true</property>  //把生成的sql显示出来
                        <property name="dialect">org.Hibernate.dialect.MySQLDialect</property>   //指定数据库用的方言
                        <property name="connection.url">jdbc:mysql://localhost:3306/shop</property>
                        <property name="connection.username">root</property>
                        <property name="connection.password">root</property>
                        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
                        <property name="myeclipse.connection.profile">mysql_cat</property>
                        
                        <mapping resource="cat/beans/AdminInfo.hbm.xml" /> //引入一个映射文件
                    
               </session-factory>
                
    </Hibernate-configuration>

    可以查找 Hibernate-3.6.10.FinalprojectetcHibernate.properties  这个文件,找到相应的配置项和内容。

    2) 实体类

    public class AdminInfo {
                        private int id;
                        private String adminName;
                        private String password;
                        private String note;
                        ... get   set 方法
                    }

    3) 生成实体类的映射文件  AdminInfo.hbm.xml

    <?xml version="1.0"?>
          <!DOCTYPE Hibernate-mapping PUBLIC
                    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
                    "http://Hibernate.sourceforge.net/Hibernate-mapping-3.0.dtd">
                        
                <Hibernate-mapping package="cat.beans">
                    <class name="AdminInfo">
                            
                           <id name="id" >
                               <generator class="native"/>  <!-- 指明主键的生成策略 -->
                           </id>
                                
                                <property name="adminName" />
                                <property name="password" />
                                <property name="note" />
                                
                    </class>
    </Hibernate-mapping>

    3)测试

    public class Test {
                public static void main(String[] args) {
                    test(); 
                }
                //可能出现的问题
                //1  Unknown entity: cat.beans.AdminInfo 原因是没有把映射文件引入到主配置文件
                //2  为什么没有真正的添到数据库中呢,因为没有开启事务
                public static void test(){
                    //读配置文件
                    Configuration cxf=new Configuration(); 
                    cxf.configure(); //会去读配置文件,扩号中可以写上配置文件的名称,也可以不写,如果不写,默认读  Hibernate.cfg.xml 这个文件
                    
                    //创建SessionFactory对象        
                    SessionFactory sessionFactory=cxf.buildSessionFactory();
                    
                    //创建Session对象
                    Session session= sessionFactory.openSession();  
                    
                    //开启事务
                    Transaction tx= session.beginTransaction();
                    AdminInfo admin=new AdminInfo();
                    admin.setAdminName("管理员Hibernate");
                    admin.setPassword("adminaaa");
                    admin.setNote("这是第一个用户用Hibernate添加的");
                    session.save(admin);
                    
                    //提交事务
                    tx.commit();                
                    session.close();
                    
                    System.out.println("操作成功");
                    System.out.println(admin.getId());  //它居然能得到id
                    
                }
            }

    说明: 对于 beans 中的 实体类(AdminInfo) ,没有什么特别的要求(但必须要有get 和set  ),但必须有一个无参的构造方法,最好不要声明为 final 的, 对懒加载有影响。对映射文件的要求和简单说。

    1) 通常,命名是 类名.hbm.xml => AdminInfo.hbm.xml

    2) 可以在一个映射文件中,映射多个类,但通常不推荐这么做

    3)

    <Hibernate-mapping package="cat.beans">  //这里的package可以不写,但如果不写,下面的 要写成全类名
          <class name="AdminInfo" >  如果上面的package不写,这里要写成      <class name="cat.beans.AdminInfo" > 
          ....

    4) 一些属性是有默认值的,可以明确的指定值,也可以使用默认值

    <class name="AdminInfo" table="adminInfo" >
           <id name="id" >
               <generator class="native" />   //native 主键生成器,会根据不同的数据库选择不同的主键生成方式
           </id>
                                        
                <property name="adminName" column="aminName"  type="string"/>
                <property name="password" />
                <property name="note" />            
    </class>

    四、工具类和标准的代码
    工具类代码实例

    package cat.hibutils;
                
    import org.Hibernate.Session;
    import org.Hibernate.SessionFactory;
    import org.Hibernate.cfg.Configuration;
                
                public class HibUtil {
                    private HibUtil(){}  //防止别人创建本类的实例
                    private static SessionFactory _factory;
                    
                    static{
                        Configuration cxf=new Configuration();
                        cxf.configure();
                        _factory=cxf.buildSessionFactory();
                    }
                    
                    //得到Session
                    //Session 对象是线程不安全的
                    public static Session getSession(){
                        return _factory.openSession();
                    }
                    
                    //得到 SessionFactory
                    public SessionFactory getSessionFactory(){
                        return _factory;
                    }
                    
                    //关闭连接
                    public static void close(Session s){
                        if(s!=null){
                            s.close();
                        }
                    }
                
                }
                
                //标准的添加方法
                public static void main(String[] args) {
                    AdminInfo admin=new AdminInfo();
                    admin.setAdminName("标准方法添的用户");
                    admin.setPassword("123");
                    add(admin);
                    
                    System.out.println("用户添加成功");
                }
                
                //标准的add方法
                public static void add(AdminInfo admin){
                    Session s=null;
                    Transaction tx=null;
                    try{
                        s=HibUtil.getSession();
                        tx=s.beginTransaction();
                        s.save(admin); 
                        tx.commit();
                    }
                    catch(Exception ex){
                        if(tx!=null){
                            tx.rollback();
                        }
                        ex.printStackTrace();
                    }finally{
                        HibUtil.close(s);
                    }    
                }
    
                //精简的写法
                public static void simpleAdd(AdminInfo admin){
                    Session s=null;
                    Transaction tx=null;
                    try {
                        s=HibUtil.getSession();
                        tx=s.beginTransaction();
                        s.save(admin);
                        tx.commit();
                    }
                    finally{
                        HibUtil.close(s);
                    }
                }

    五、使用 threadLocal

    public class HibUtil {
                    private HibUtil(){}  //防止别人创建本类的实例
                    private static SessionFactory _factory;
                    private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();
                    
                    static{
                        Configuration cxf=new Configuration();
                        cxf.configure();
                        _factory=cxf.buildSessionFactory();
                    }
                    
                    //得到Session
                    //Session 对象是线程不安全的
                    public static Session getSession(){
                        //return _factory.openSession();
                        Session s=threadLocal.get();
                        if(s == null){
                             s=_factory.openSession();
                             threadLocal.set(s);
                        }    
                        return s;
                    }
                    
                    //得到 SessionFactory
                    public SessionFactory getSessionFactory(){
                        return _factory;
                    }
                    
                    //关闭连接
                    public static void closeSession(){
                        Session s=threadLocal.get();
                        threadLocal.set(null);
                        
                        if(s!=null){
                            s.close();
                        }
                    }
                }
                
                public static void simpleAdd(AdminInfo admin){
                    Session s=null;
                    Transaction tx=null;
                    try {
                        s=HibUtil.getSession();
                        tx=s.beginTransaction();
                        s.save(admin);
                        tx.commit();
                    }
                    finally{
                        HibUtil.closeSession();  //关连接的时候,可以这样关
                    }
                }

    六、Session接口

    几个常用的方法

    1) save , persist 保存数据,  persist 在事务外不会产生insert语句

    2) delete 删除对象

    3) update 更新一个对象,如果数据库中没有对应的记录,将出错

    4) get 根据ID查询对象,会立刻访问数据库

    5) load 根据ID查询对象 (返回的是代理对象,不会立即访问数据库,懒加载)

    6) saveOrUpdate (根据ID和version来决定是要保存还是要更新) , merge (调用 merge 你的对象还是脱管的)

    7) lock 把对象变成持久对象,但不会同步对象的状态

     //例子,使用get查询用户
     
    public static void main(String[] args) {
                        AdminInfo admin=getAdmin(89);
                        System.out.println(admin);
                    }
        
    public static AdminInfo getAdmin(int id){    
                        try{
                            Session s=HibUtil.getSession();
                            return (AdminInfo)s.get(AdminInfo.class, id);
                            
                        }finally{
                            HibUtil.closeSession();
                        }
                    }
    //例子,使用load方法进行查询
    public static AdminInfo loadAdmin(int id){    
                    try{
                        Session s=HibUtil.getSession();
                        AdminInfo admin= (AdminInfo)s.load(AdminInfo.class, id);        
                        return admin;   //如果这里不直接访问 admin 对象,则返回的是代理,并不是真正查询出来的数据
                        
                    }finally{
                        HibUtil.closeSession();
                    }
                }
                
    public static void main(String[] args) {
                        AdminInfo admin=loadAdmin(89);
                        System.out.println(admin.getAdminName()); //could not initialize proxy - no Session 不能初始化代理对象,因为没有session了
                }

    七、对象状态   

    1.瞬时 (transien) : 数据库中没有数据与之对应,超过作用域就失效,会被垃圾回收器回收。一般的 new 出来的对象,且与session无关

    2.持久 (persistent): 数据库中有数据与之对应,与 Session有关联,而且相关的Session没有关闭,事务还没有提交, 持久对象的状态发生改变, 在事务提交的时候,会保存到数据库 (Hibernate会检测到)

    3.脱管 (detached) ,数据库中有数据与之对应, 但当前没有Session与之关联, 脱管对象状态发生改变也不会影响到数据库

    瞬时: 自由人

    持久: 法庭上被审问中的人,有案底 , 所有的话都是呈堂证供

    脱管: 审完了,放了的人 , 有案底,但言论自由

    八、封装简单的操作到HibUtil

    //增加 
            public static  void add(Object obj){
                Session s=null;
                Transaction tx=null;
                try{
                    s=getSession();
                    tx=s.beginTransaction();
                    s.save(obj);
                    tx.commit();
            
                }finally{
                    closeSession();
                }
            }
            
            //删除
            public static void del(Object obj){
                try{
                    Session s=getSession();
                    Transaction tx=s.beginTransaction();
                    s.delete(obj);
                    tx.commit();
                    
                }finally{
                    closeSession();
                }
            }
            
            //修改
            public static void  update(Object  obj){
                Session s=null;
                Transaction  tx=null;
                try{
                    s=getSession();
                    tx=s.beginTransaction();
                    s.update(obj);
                    tx.commit();
                    
                }finally{
                    closeSession();
                }
            }
            
            //查询 
            public static Object get(Class  clazz, Serializable id){
                try{
                    Session s=getSession();
                    return s.get(clazz, id);
                }finally{
                    closeSession();
                }    
            }

    九、HQL

    public class AdminDao {        
                //根据用户名和密码查询用户
                public AdminInfo getLoginAdmin(String adminName,String password){
                    try{
                        Session s=HibUtil.getSession();
                        String hql="from AdminInfo a where a.adminName= ? and a.password= ?";   //AdminInfo 必须是对象名,不能是表名
                        Query q=s.createQuery(hql);
                        q.setString(0, adminName);   //注意,它是从0开始的
                        q.setString(1, password);
                        
                        AdminInfo admin= (AdminInfo)q.uniqueResult();  //只返回一对象,如果返回的不是一条数据,将出现异常 query did not return a unique result 54
                        return admin;
                        
                    }finally{
                        HibUtil.closeSession();
                    }
                }
                
                //查询所有用户
                @SuppressWarnings("unchecked")
                public List<AdminInfo> getAllAdmin(){
                    try{
                        Session s=HibUtil.getSession();
                     /* Query q =s.createQuery("from AdminInfo");
                        return  q.list();  //返回一个列表
                      */    
                        return s.createQuery("from AdminInfo").list();
                        
                    }finally{
                        HibUtil.closeSession();
                    }
                }
            }

    生成测试用例 :

    在类上,右键, new 输入 other , 搜索 junit 然后一步步添加即可。

    public class AdminDaoTest {    
                    private AdminDao dao;
                    
                    @BeforeClass  //注解
                    public static void setUpBeforeClass() throws Exception {
                        //主要用于对静态成员进行初始化
                    }
                
                    @AfterClass
                    public static void tearDownAfterClass() throws Exception {
                    }
                
                    @Before  //表示在执行之前做的处理
                    public void setUp() throws Exception {
                        dao=new AdminDao();
                    }
                
                    @After  //执行之后做的处理
                    public void tearDown() throws Exception {
                        System.out.println("测试完毕");  //在每个方法执行完后都会调用
                    }
                    
                    @Test
                    public void testGetLoginAdmin() {
                        AdminInfo admin=dao.getLoginAdmin("aaaaaaa", "aaa");
                        
                        if(admin==null){
                            System.out.println("没查到");
                        }
                        else{
                            System.out.println(admin);
                        }    
                    }
                
                    @Test
                    public void testGetAllAdmin() {
                        List<AdminInfo> list=dao.getAllAdmin();
                        
                        for (AdminInfo a:list) {
                            System.out.println(a);
                        }
                    }
                }

    HQL 的补充说明

    1)上面的写法

    String hql="from AdminInfo a where a.adminName= ? and a.password= ?";

    也可以不用别名,如下:

    String hql="from AdminInfo  where adminName= ? and password= ?"

    2) 可以使用命名参数

    String hql="from AdminInfo a where a.adminName=:aname and a.password= :pwd ";   //AdminInfo 必须是对象名,不能是表名
                        Query q=s.createQuery(hql);
                        q.setString("aname", adminName);   //注意,它是从0开始的
                        q.setString("pwd", password);

    3) Query 接口有个种set 方法, 可以对指定类型的参数进行传入

    4) 可以使用  setFirstResult  和  setMaxResults 进行结果集过滤,实现分页查询

    public List<AdminInfo> getAdminList(int beginRow,int pageSize){
                        try{
                                Session s=HibUtil.getSession();
                                Query q=s.createQuery("from AdminInfo");
                                q.setFirstResult(beginRow);
                                q.setMaxResults(pageSize);
                                
                                return q.list();
                                
                            }finally{
                                HibUtil.closeSession();
                            }
                        }

    5) 查询数据行数

    public int getAdminCount(){
                        try{
                            Session s=HibUtil.getSession();
                            Query q=s.createQuery("select count(*) from AdminInfo");  //后面是对象名,
                            long count=(Long)q.uniqueResult();
                            return new Integer(count+"");
                            
                        }finally{
                            HibUtil.closeSession();
                        }
                    }

    补充:HQL 常见的查询

    // 使where 
            Query q=s.createQuery("from AdminInfo where id not between 10 and 20");  //查询id不在10 到20之间的
            
    // 使用in 
          Query q=s.createQuery("from AdminInfo where AdminName in('张三','李四','王五')"); //只要在这个('张三','李四','王五')集合中含有的,就查出来
          
    // 使用 like 
            Query q=s.createQuery("from AdminInfo where AdminName like %赵%");    // 查询名字中含有赵的所有用户
              
    // 使用 null 
            Query q=s.createQuery("from AdminInfo where note is null");     //查询所有备注为null的用户        
                
    // 使用 and 
              Query q=s.createQuery("from AdminInfo where note is null and id<5");       //查询备注信息是null而且id<5的用户
              
    // 执行删除
            Query q=s.createQuery("from AdminInfo where password is null");
             
    // 批量删除:
            public void delAdmins(String password){
                    try{
                        Session s=HibUtil.getSession();
                        Transaction tx=s.beginTransaction();
                        Query q=s.createQuery("delete from AdminInfo where password= :pwd");
                        q.setString("pwd", password);
                        q.executeUpdate();  //执行删除
                        
                        tx.commit();
                        
                    }finally{
                        HibUtil.closeSession();
                    }        
                }
  • 相关阅读:
    阿里云物联网 .NET Core 客户端 | CZGL.AliIoTClient:8. 委托事件
    阿里云物联网 .NET Core 客户端 | CZGL.AliIoTClient:7. 服务调用
    Git
    Git
    Git
    Git
    Git
    Git
    Git
    Delphi
  • 原文地址:https://www.cnblogs.com/1693977889zz/p/8204140.html
Copyright © 2020-2023  润新知