美文网首页
IntelliJ IDEA Hibernate 从入门到填坑

IntelliJ IDEA Hibernate 从入门到填坑

作者: Thresh0ld | 来源:发表于2016-11-02 15:51 被阅读9665次

    背景:本文所涉及的IDE如标题所示:IntelliJ IDEA. Java编译器史上最强大的IDE,对,你没有看错,没有之一。没试过的赶紧放下手中的Eclipse去尝试下他吧。我们常见的Android Studio就是基于他定制而来(他本身也可以开发Android)

    一. 项目添加Hibernate框架

    这里没什么好说的,对于新建项目时要勾选Hibernate框架。如果项目已经建好了就在项目上右击Add Framework.
    算了,展开说下吧。也当是个笔记。

    1.新建Hibernate项目

    Paste_Image.png

    下面红框里的文件就是生成的Hibernate配置文件,后期很多配置都需要他。


    Paste_Image.png

    2.在现有项目上添加Hibernate框架

    右击项目,点击 Add Framework Support


    Paste_Image.png

    看下图,记得勾选创建默认Hibernate 配置文件


    Paste_Image.png

    点击OK 下载Hibernate依赖库文件

    Paste_Image.png

    下载依赖库时可能会失败,因为在天朝,原因你我懂的。嗯,相信你已经知道该怎么做了:给IDE设置proxy
    下图是我的项目在下载依赖库时的网络流量情况,很显然需要爬城墙。


    Paste_Image.png

    二. 项目配置

    你以为把Hibernate框架加入就可以用ORM了嘛。 年轻人,naive. 还要加入从maven中获取你所对应的数据库的依赖库,例如我这里的MySQL,那就需要依赖MySQL Connector.其他数据库类似

    选中项目,点击菜单 File ~ Project Structure ~ Libraries ~

    Paste_Image.png Paste_Image.png

    三.hibernate.cfg.xml 配置

    默认生成的hibernate.cfg.xml 内容如下:

    <?xml version='1.0' encoding='utf-8'?>
    <!DOCTYPE hibernate-configuration PUBLIC        
         "-//Hibernate/Hibernate Configuration DTD//EN"        
         "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
    <hibernate-configuration> 
    <session-factory>        
          <property name="connection.url"/>        
          <property name="connection.driver_class"/> 
         <property name="connection.username"/>
         <property name="connection.password"/>  
        <!-- DB schema will be updated if needed -->    
        <!-- <property name="hbm2ddl.auto">update</property> -->  
     </session-factory>
    </hibernate-configuration>
    

    关于Hibernate的配置及其详尽用法,可以自行Google之。

    下面介绍MySql常用的hibernate.cfg.xml配置

    <?xml version='1.0' encoding='utf-8'?>
    <!DOCTYPE hibernate-configuration PUBLIC
            "-//Hibernate/Hibernate Configuration DTD//EN"
            "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
    <hibernate-configuration>
        <session-factory>
            <!-- Database connection settings -->
            <property name="connection.url">jdbc:mysql://127.0.0.1:3306/workdiary?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC</property>
            <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
            <property name="connection.username">root</property>
            <property name="connection.password">123456</property>
    
    
            <!-- JDBC connection pool (use the built-in) -->
            <property name="connection.pool_size">4</property>
    
            <!-- SQL dialect -->
            <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
    
            <!-- Enable Hibernate's automatic session context management -->
            <property name="current_session_context_class">thread</property>
    
            <!-- Disable the second-level cache  -->
            <property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>
            <!--以格式良好的方式显示SQL语句-->
            <property name="format_sql">true</property>
            <!-- Echo all executed SQL to stdout -->
            <property name="show_sql">true</property>
    
            <!-- Drop and re-create the database schema on startup -->
            <property name="hbm2ddl.auto">update</property>
    
            <mapping class="com.threshold.hibernate.bean.DiaryEntity"/>
            <mapping class="com.threshold.hibernate.bean.UserEntity"/>
            <!-- <mapping resource="org/hibernate/tutorial/domain/Event.hbm.xml"/> -->
    
        </session-factory>
    </hibernate-configuration>
    

    注意上面的

    <mapping class="com.threshold.hibernate.bean.DiaryEntity"/>
    <mapping class="com.threshold.hibernate.bean.UserEntity"/> 
    

    这个在你的项目中是需要删除的,不然会报错的(因为你数据库可能没有这两个表)。而且这个也是hibernate自动生成的。下一节我将介绍怎么自动生成。

    还有一点需要注意:那就是每次自动生成实体类后,hibernate.cfg.xml中关于数据库连接那一块总是被替换重置,建议还是改回

         <property name="connection.url"/>        
         <property name="connection.driver_class"/> 
         <property name="connection.username"/>
         <property name="connection.password"/>
    

    这种形式,否则你就会遇到 HHH-000319 HHH-000231 Could not get database metadata 等等奇奇怪怪的报错信息。

    四. hibernate生成数据库实体类

    重点来了,在这一节,我将介绍怎么使用hibernate生成实体类。

    1. 首先将上一节生成的Main.java 重命名一下。

      Paste_Image.png


      将它命名成** HibernateSessionFactory**
      其实这一步可做可不做,只是Main.java 我个人觉得不适合我的项目命名,而且这个Main.java的主要功能就是提供Hibernate的Session的。

    2. 建个entities包,存放数据库的实体类。

    Paste_Image.png
    1. 添加Database连接
      在IDE右侧找到Database标签页。点开


      Paste_Image.png
      Paste_Image.png
      Paste_Image.png

    连接成功:


    Paste_Image.png

    点击OK即可。

    现在我们到IDE左下角找到 Persistence 标签页,并点开它。

    Paste_Image.png

    右击菜单:


    Paste_Image.png

    点击 Generate Persistence Mapping ~ By Database Schema.

    Paste_Image.png

    然后我们再操作一次。注意图中的红框和字。


    Paste_Image.png

    生成成功


    Paste_Image.png

    记得把连接字符串改回来。

    1. 修改HibernateSessionFactory.java 类文件
    public class HibernateSessionFactory {
        private static final Logger logger = Logger.getLogger(HibernateSessionFactory.class.getName());
        private static final SessionFactory ourSessionFactory;
        private static final ServiceRegistry serviceRegistry;
    
        static {
            logger.setLevel(Level.ALL);
            try {
                Configuration configuration = new Configuration();
                configuration.configure();
                //一定要记得在这里把生成的实体类加入到Configuration里。否则调用的时候肯定报错。
              //Hibernate 4.x版本的不需要。5.x才需要这样。而且5.x的hibernate必须要生成.hbm.xml文件,否则还是会报错。4.x只需要把生成的实体类在hibernate.cfg.xml中声明即可。
                configuration.addClass(UserEntity.class)
                        .addClass(DiaryEntity.class);
    
                serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
                ourSessionFactory = configuration.buildSessionFactory(serviceRegistry);
            } catch (Throwable ex) {
                throw new ExceptionInInitializerError(ex);
            }
        }
    
        public static Session getSession() throws HibernateException {
            return ourSessionFactory.openSession();
        }
    
        public static void main(final String[] args) throws Exception {
            final Session session = getSession();
            try {
                session.beginTransaction();
                UserEntity entity = session.load(UserEntity.class, 1);
                //只有在使用对象时,它才发出查询SQL语句,加载对象。
                System.out.println("User.Password="+entity.getPassword());
                logger.log(Level.FINEST, entity.getCellphone());
                //因为此的user为persistent状态,所以数据库进行同步
                entity.setIdentityCard("342401199209081211");
                session.getTransaction().commit();
    //下面的代码是IntelliJ IDEA自动生成的,适用于Hibernate4.x,5.x不再可用,执行会报错。
    //            System.out.println("querying all the managed entities...");
    //            Map<String, ClassMetadata>  map = (Map<String, ClassMetadata>) ourSessionFactory.getAllClassMetadata();
    //            for(String entityName : map.keySet()){
    //                SessionFactoryImpl sfImpl = (SessionFactoryImpl) ourSessionFactory;
    //                String tableName = ((AbstractEntityPersister)sfImpl.getEntityPersister(entityName)).getTableName();
    //                System.out.println(entityName + "\t" + tableName);
    //            }
    //            final Map metadataMap = session.getSessionFactory().getAllClassMetadata();
    //            for (Object key : metadataMap.keySet()) {
    //                final ClassMetadata classMetadata = (ClassMetadata) metadataMap.get(key);
    //                final String entityName = classMetadata.getEntityName();
    //                final Query query = session.createQuery("from " + entityName);
    //                System.out.println("executing: " + query.getQueryString());
    //                for (Object o : query.list()) {
    //                    System.out.println("  " + o);
    //                }
    //            }
            } catch (Exception e) {
                Transaction transaction = session.getTransaction();
                if (transaction != null) {
                    transaction.rollback();
                }
                e.printStackTrace();
            } finally {
                if (session != null && session.isOpen()) {
                    session.close();
                }
            }
    
        }
    }
    

    好了。配置完成了。

    下一节将介绍Hibernate的简单使用方法。

    四. Hibernate简单使用示例

    Paste_Image.png

    泛泛而谈一点吧,以上图为例,dao 就是对数据库表操作的封装类的包。
    先创建接口,再在dao.impl包中创建实现类。

    Paste_Image.png

    就是这么简单。Easy.

    还有个小坑在这里一笔带过一下吧:Hibernate在save(新增插入)数据时,如果这个Entity有自增长主键,那么请不要对这个新建的Entity的主键字段做任何更改,比如题主我就画蛇添足将Entity主键字段设成-1,心想数据库会自增长的嘛,但是Hibernate不这么想,你如果对主键字段设置了值,他就将这个值一并代入并插入数据库,而往往我们不需要这样。

    还有对于更新数据,请先用Session从数据库将这个Entity查出来,再将更改的字段应用到这个查出来的Entity里,最后再调用Hibernate去update这个Entity.千万不要new Entity然后去更新,否则你没更新的字段都会被Hibernate置为null了,这显然和我们想要的不同。

    有时间再开辟新的文章详细叙述吧。

    五. 排错/debug

    1. NoSuchMethodError 错误。
      例如
     java.lang.NoSuchMethodError: org.jboss.logging.Logger.debugf(Ljava/lang/String;I)
    

    你的项目是不是Jersey RESTful架构,是不是用的Glassfish服务器。
    Glassfish 版本是不是4.1.1或者4.1.0 .
    如果是,恭喜你中奖了。jboss-logging在Glassfish服务器的Modules里有jar包。但是跟你lib里的不一致。你需要将项目lib目录中jboss-logging.jar拷贝到Glassfish服务器目录中。

    Paste_Image.png

    就是拷贝替换到这个目录中。

    1. Debug都能查询到数据,但是偏偏Jersey返回json格式数据时就报错。
      还是Glassfish的问题,Glassfish4.1.1有个bug,在返回json数据的时候就报错了,返回TEXT_PLAIN和XML都是没问题的,这个bug官方已经知道了,会在下个版本修复,目前可以使用Glassfish4.1.0版本的。

    关注我的公众号.jpg

    相关文章

      网友评论

          本文标题:IntelliJ IDEA Hibernate 从入门到填坑

          本文链接:https://www.haomeiwen.com/subject/jvmmuttx.html