在JAVA中已检查异常和位未检查异常是啥?二者有何区别?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在JAVA中已检查异常和位未检查异常是啥?二者有何区别?相关的知识,希望对你有一定的参考价值。

参考技术A

1、含义不同:检查异常就是编译器要求你必须处置的异常。不知道你编程的时候有没有遇到过,你写的某段代码,编译器要求你必须要对这段代码trycatch,或者throwsexception。

非检查异常是编译器不要求强制处置的异常,虽然有可能出现错误,但是不会在编译的时候检查。

2、运行时情况不同:运行时异常都是RuntimeException类及其子类异常,如NullPointerException(空指针异常)、IndexOutOfBoundsException(下标越界异常)等,这些异常是非检查异常,程序中可以选择捕获处理,也可以不处理。

这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。

运行时异常的特点是Java编译器不会检查它,也就是说,当程序中可能出现这类异常,即使没有用try-catch语句捕获它,也没有用throws子句声明抛出它,也会编译通过。

运行时异常是RuntimeException以外的异常,类型上都属于Exception类及其子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。

如IOException、SQLException等以及用户自定义的Exception异常,一般情况下不要自定义检查异常。

3、解决方式不同:检查异常继续抛出,消极的方法,一直可以抛到java虚拟机来处理,就是通过throwsexception抛出。用try...catch捕获。注意,对于检查的异常必须处理,或者必须捕获或者必须抛出。

对未检查的异常捕获;继续抛出;不处理。

一般是不处理的,因为你很难判断会出什么问题,而且有些异常你也无法运行时处理,比如空指针,需要人手动的去查找,而且,捕捉异常并处理的代价远远大于直接抛出。

扩展资料:

所有异常类型都是Throwable类的子类,它包含Exception类和Error类,Exception又包括checkedexception和uncheckedexception。

uncheckedexception:Java编译器不要求对未检查异常一定捕获或抛出,可以不做处理。此类异常通常是在逻辑上有错误,可以通过修改代码避免。在eclipse中(保存即编译)编译后此类异常发生处会报错。

checkedexception:Java编译器要求对检查异常必须捕获或抛出,代码逻辑没有错误,但程序运行时会因为IO等错误导致异常,你在编写程序阶段是预料不到的。

如果不处理这些异常,程序将来肯定会出错。所以编译器会提示你要去捕获并处理这种可能发生的异常,不处理就不能通过编译。

参考资料:百度百科-Java

在Hibernate中,为什么saveOrUpdate在数据库中已存在对象时给出异常

以前,当我使用Hibernate向数据库添加实体时,我常常检查它是否已经添加。但是为了提高性能,我忘记了这个检查,只是尝试添加而不检查,因为我使用saveOrUpdate()我的理解,如果Hibernate发现它已经添加它只会更新和我的保存所做的更改。

但相反,它失败了

18/08/2018 21.58.34:BST:Errors:addError:SEVERE: Adding Error:Database Error:Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [com.jthink.songlayer.MusicBrainzReleaseWrapper#95f6f584-407f-4b26-9572-bb8c6e9c580a]
java.lang.Exception
    at com.jthink.songkong.analyse.general.Errors.addError(Errors.java:28)
    at com.jthink.songkong.exception.ExceptionHandling.handleHibernateException(ExceptionHandling.java:209)
    at com.jthink.songkong.db.ReleaseCache.addToDatabase(ReleaseCache.java:394)
    at com.jthink.songkong.db.ReleaseCache.add(ReleaseCache.java:65)




@Entity
    public class MusicBrainzReleaseWrapper
    {
        @Id
        private String guid;

        @Version
        private int version;

        @org.hibernate.annotations.Index(name = "IDX__MUSICBRAINZ_RELEASE_WRAPPER_NAME")
        @Column(length = 1000)
        private String name;

        @Lob
        @Column(length = 512000)
        private String xmldata;

        public String getGuid()
        {
            return guid;
        }

        public void setGuid(String guid)
        {
            this.guid = guid;
        }

        public String getName()
        {
            return name;
        }

        public void setName(String name)
        {
            this.name = name;
        }

        public String getXmldata()
        {
            return xmldata;
        }

        public void setXmldata(String xmldata)
        {
            this.xmldata = xmldata;
        }
    }

    private static boolean addToDatabase(Release release)
        {
            Session session = null;
            try
            {
                session = HibernateUtil.beginTransaction();
                //Marshall to String
                StringWriter sw = new StringWriter();
                Marshaller m = jc.createMarshaller();
                m.marshal(release, sw);
                sw.flush();

                MusicBrainzReleaseWrapper wrapper = new MusicBrainzReleaseWrapper();
                wrapper.setGuid(release.getId());
                wrapper.setName(release.getTitle().toLowerCase(Locale.UK));
                wrapper.setXmldata(sw.toString());
                session.saveOrUpdate(wrapper);
                session.getTransaction().commit();
                MainWindow.logger.info("Added to db release:" + release.getId() + ":" + release.getTitle());
                return true;
            }
            catch (ConstraintViolationException ce)
            {
                MainWindow.logger.warning("Release already exists in db:"+release.getId()+":"+release.getTitle());
                return true;
            }
            catch(GenericJDBCException jde)
            {
                MainWindow.logger.log(Level.SEVERE, "Failed:" +jde.getMessage());
                ExceptionHandling.handleDatabaseException(jde);
            }
            catch(HibernateException he)
            {
                MainWindow.logger.log(Level.SEVERE, "Failed:" +he.getMessage());
                ExceptionHandling.handleHibernateException(he);
            }
            catch(Exception e)
            {
                MainWindow.logger.log(Level.WARNING,"Failed AddReleaseToDatabase:"+release.getId()+ ':' +e.getMessage(),e);
                throw new RuntimeException(e);
            }
            finally
            {
                HibernateUtil.closeSession(session);
            }
            return false;
        }

用于在调用addToDatabase之前先检查

        if(ReleaseCache.get(release.getId())==null)
        {
            addToDatabase(release)
        }        
答案

您遇到的问题与通过MusicBrainzReleaseWrapper上的@Version注释启用的乐观锁定直接相关。 saveOrUpdate确实可以添加或更新实体,但这只有在实体版本与您尝试添加或合并的分离对象的实体版本相同时。

在您的特定示例中,分离对象的版本在数据库中的最后一个版本之前,因此无法对过时数据执行操作。

更新:

MusicBrainzReleaseWrapper wrapper = session.get(release.getId()):
//the wrapper is managed object
if (wrapper == null) {
  //initilize wrapper with the values from release
  .......
  session.save(wrapper)
}
else {
   // do not set ID here. ID is aready present!!!
   //  never manuay set the version field here
   wrapper.setName(release.getTitle().toLowerCase(Locale.UK));
   wrapper.setXmldata(sw.toString());
   session.saveOrUpdate(wrapper);
   //In case you don't need update logic at all
   // remove the @Version field from the entity
   // and do othing in the else clause , or throw exception
   // or log error or anything you see fit
}
另一答案

Hiberante对象有一个实体的3个状态。它们是: - Transient或New - Detached(从DB获取对象并关闭hibernate会话) - Persistent(从DB获取对象并打开hibernate会话)在saveOrUpdate方法中,它要么保存瞬态对象,要么更新分离的/持久对象。在您的代码中,您尝试创建Transient / New对象并在其中设置旧ID。这就是你遇到错误的原因。首先使用id获取对象然后更新它的正确方法。

另一答案

不.saveOrUpdate方法用于将实体持久化或合并到当前会话。它不符合你的期望。保存或更新实体是应用程序的特定逻辑。 Hibernate不执行任何应用程序的特定逻辑。

另一答案

Session.merge()可以直接保存以前未知的实例,但请注意,它不一定会避免针对数据库的额外选择。

@Pavan对Hibernate(或JPA)术语中的瞬态或分离实体是正确的。这两种状态都意味着Hibernate在其会话中(在StatefulPersistenceContext中)尚未获得对该实体实例的引用,但是分离显然意味着数据库已知它。

  • merge()指示Hibernate停止并检查分离的实例。第一次检查是在会话中的@Id值,但如果它还没有,它必须命中数据库。
  • saveOrUpdate()指示Hibernate,调用者知道只检查StatefulPersistenceContext@Id是安全的。如果它不存在,则假定该实体是瞬态的(即新的),并且Hibernate将继续进行插入操作。

saveOrUpdate()适用于会话已知的实例(有或没有@Id值)。

在你的情况下,显然Hibernate不知道分离的实例,所以你需要使用merge()。但这也意味着Hibernate必须检查数据库中之前没有见过的实例 - 如果实体具有@Id值。

要回到您问题中的原始意图,更新而不选择更难...

对于更新,Hibernate喜欢知道实体的先前状态。如果它使用动态更新(因此不更新所有列),这是有道理的,但否则你会认为它可以直接进行更新。我知道的唯一选择是直接更新查询(通过HQL或JPQL),但如果您有实体实例,这几乎不方便。也许别人知道怎么做。

以上是关于在JAVA中已检查异常和位未检查异常是啥?二者有何区别?的主要内容,如果未能解决你的问题,请参考以下文章

异常抛出与捕获的思考

视图中已使用的组件的 JSP 异常

在Hibernate中,为什么saveOrUpdate在数据库中已存在对象时给出异常

Java检查型异常和非检查型异常

如何在java中识别已检查和未检查的异常?

java 检查异常 和 非检查异常