美文网首页
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