休眠异常处理 [英] Hibernate exception handling

查看:125
本文介绍了休眠异常处理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个复杂的问题。



我正在使用Hibernate / JPA与DB进行交易。



我不是DBA,客户端使用我的应用程序,一个RESTful Web服务。我的问题是DB被改变(不是很频繁,但它仍然改变)。此外,客户端并不总是尊重我的应用程序的输入(长度,类型等)。当这种情况发生时,Hibernate会引发异常。例外是很难从日志中翻译和阅读,因为它有嵌套的异常并且包含很多文本:像我说的那样很难理解。



我想知道是否可以处理实体级别的异常,抛出可能的定制异常。



我非常感谢你的耐心和提前的帮助。

编辑:



Fianlly我设法做我想要的,不知道是否完成



App.java

  package com.mc; 

import org.hibernate.Session;
import com.mc.stock.Stock;
import com.mc.util.HibernateUtil;
import javax.persistence.EntityManager;

public class App {

public static void main(String [] args){
Set< ConstraintViolation< Stock>>违规行为;
validator = Validation.buildDefaultValidatorFactory()。getValidator();
扫描仪扫描=新扫描仪(System.in);

EntityManager em = null;

System.out.println(Hibernate one to many(Annotation));
会话session = HibernateUtil.getSessionFactory()。openSession();

session.beginTransaction();


股票股票=新股票();
String nextLine = scan.nextLine();
stock.setStockCode(nextLine.toString());
nextLine = scan.nextLine();
stock.setStockName(nextLine.toString());


violation = validator.validate(stock);
if(violations.size()> 0){
StringBuilder excepcion = new StringBuilder();
for(ConstraintViolation< Stock>违规:违规){
excepcion.append(violation.getMessageTemplate());
excepcion.append(\\\
);
}
System.out.println(excepcion.toString());
}
session.save(stock);
session.getTransaction()。commit();
}
}

FieldMatch.java / p>

  package com.mc.constraints; 

import com.mc.constraints.impl.FieldMatchValidator;

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.TYPE;
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Target;

@Target({TYPE,ANNOTATION_TYPE})
@Retention(RUNTIME)
@Constraint(validatedBy = FieldMatchValidator.class)
@Documented
public @interface FieldMatch {

String message()default{constraints.fieldmatch};

Class<?> [] groups()default {};

Class<?扩展有效载荷> [] payload()default {};

String first();

String second();

@Target({TYPE,ANNOTATION_TYPE})
@Retention(RUNTIME)
@Documented
@interface列表{

FieldMatch [ ] value();
}
}

FieldMatchValidator.java / p>

  package com.mc.constraints.impl; 

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import com.mc.constraints.FieldMatch;
import org.apache.commons.beanutils.BeanUtils;

public class FieldMatchValidator实现ConstraintValidator< FieldMatch,Object> {

private String firstFieldName;
private String secondFieldName;

@Override
public void initialize(final FieldMatch constraintAnnotation){
firstFieldName = constraintAnnotation.first();
secondFieldName = constraintAnnotation.second();
}

@Override
public boolean isValid(final Object value,final ConstraintValidatorContext context){
try {
final Object firstObj = BeanUtils.getProperty value,firstFieldName);
final Object secondObj = BeanUtils.getProperty(value,secondFieldName);

return firstObj == null&&& secondObj == null || firstObj!= null&& firstObj.equals(secondObj);
} catch(final Exception ignore){
// ignore
}
return true;
}
}

Stock.java / p>

  package com.mc.stock; 

import com.mc.constraints.FieldMatch;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
import org.hibernate.validator.constraints.Length;

@Entity
@Table(name =STOCK)
@XmlRootElement
@NamedQueries({
@NamedQuery(name =Stock.findAll ,query =SELECT s FROM Stock s),
@NamedQuery(name =Stock.findByStockId,query =SELECT s FROM Stock s WHERE s.stockId =:stockId),
@NamedQuery(name =Stock.findByStockCode,q​​uery =SELECT s FROM Stock s WHERE s.stockCode =:stockCode),
@NamedQuery(name =Stock.findByStockName,query =SELECT s FROM股票的WHERE s.stockName =:stockName)})
@ FieldMatch.List({
@FieldMatch(first =stockCode,second =stockName,message =代码和库存必须相同的值)
})
public class库实现Serializable {

private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE,generator =seq_stock_id)
@SequenceGenerator(name =seq_stock_id,sequenceName =seq_stock_id,initialValue = 1,allocateSize = 1)
@Basic(optional = false)
@Column(name =STOCK_ID,unique = true,nullable = false)
private Integer stockId;
@Column(name =STOCK_CODE)
private String stockCode;
@Length(min = 1,max = 20,message ={wrong stock name length})
@Column(name =STOCK_NAME)
private String stockName;

public Stock(){
}

public Stock(Integer stockId){
this.stockId = stockId;
}

public Integer getStockId(){
return stockId;
}

public void setStockId(Integer stockId){
this.stockId = stockId;
}

public String getStockCode(){
return stockCode;
}

public void setStockCode(String stockCode){
this.stockCode = stockCode;
}

public String getStockName(){
return stockName;
}

public void setStockName(String stockName){
this.stockName = stockName;
}

@Override
public int hashCode(){
int hash = 0;
hash + =(stockId!= null?stockId.hashCode():0);
返回哈希;
}

@Override
public boolean equals(Object object){
// TODO:Warning - 此方法在id字段为没有设置
if(!(object instanceof Stock)){
return false;
}
库存其他=(库存)对象;
if((this.stockId = null)||(this.stockId!= null& {
return false;
}
返回true;
}

@Override
public String toString(){
returncom.mc.stock.Stock [stockId =+ stockId +];
}
}

HibernateUtil.java / p>

  package com.mc.util; 

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {

private static final SessionFactory sessionFactory = buildSessionFactory();

private static SessionFactory buildSessionFactory(){
try {
//从hibernate.cfg.xml创建SessionFactory
返回新的Configuration()。configure()。 buildSessionFactory();
} catch(Throwable ex){
//确保记录异常,因为它可能被吞下
System.err.println(初始SessionFactory创建失败+ ex);
抛出新的ExceptionInInitializerError(ex);
}
}

public static SessionFactory getSessionFactory(){
return sessionFactory;
}

public static void shutdown(){
//关闭缓存和连接池
getSessionFactory()。
}
}

Oracle数据库结构 / p>

  CREATE TABLE股票

STOCK_ID NUMBER(5)NOT NULL,
STOCK_CODE VARCHAR2 10)NULL,
STOCK_NAME VARCHAR2(20)NULL
);

ALTER TABLE stock
add CONSTRAINT PK_STOCK_ID PRIMARY KEY(STOCK_ID);

创建序列seq_stock_id
以1
开始增加1
nomaxvalue;


解决方案

我倾向于在你之前做很多的验证获取DB级别。看看Hibernate Validator, http://www.hibernate.org/subprojects/validator.html 这是JSR-303的参考实现。



使用标准注释,您可以在尝试将实体放入数据库之前强制执行约束并获取良好的错误消息。



我相信这将允许您根据请求在实体层级进行验证。


I've got a little 'complex' question.

I'm using Hibernate/JPA to make transactions with a DB.

I'm not the DBA, and a client consumes my application, a RESTful web service. My problem is that the DB is altered (not very often, but it still changes). Also, the client does not always respect input for my application (length, type, etc.). When this happens Hibernate throws an exception. The exception is difficult to translate and read from the log, because it has nested exceptions and consists of a lot of text: like I said, very difficult to understand.

I want to know if it's possible to handle exceptions on entity level, throwing maybe a customized exception.

I thank your patience and help in advance.

EDIT:

Fianlly I managed to do what I wanted, not sure if it's done the right way.

App.java

package com.mc;  

import org.hibernate.Session;  
import com.mc.stock.Stock;  
import com.mc.util.HibernateUtil;  
import javax.persistence.EntityManager;  

public class App {  

    public static void main(String[] args) {  
        Set<ConstraintViolation<Stock>> violations;
        validator = Validation.buildDefaultValidatorFactory().getValidator();
        Scanner scan = new Scanner(System.in);

        EntityManager em = null;

        System.out.println("Hibernate one to many (Annotation)");
        Session session = HibernateUtil.getSessionFactory().openSession();

        session.beginTransaction();


        Stock stock = new Stock();
        String nextLine = scan.nextLine();
        stock.setStockCode(nextLine.toString());
        nextLine = scan.nextLine();
        stock.setStockName(nextLine.toString());


        violations = validator.validate(stock);
        if (violations.size() > 0) {
            StringBuilder excepcion = new StringBuilder();
            for (ConstraintViolation<Stock> violation : violations) {
                excepcion.append(violation.getMessageTemplate());
                excepcion.append("\n");
            }
            System.out.println(excepcion.toString());
        }
        session.save(stock);
        session.getTransaction().commit();
    }  
}  

FieldMatch.java

package com.mc.constraints;  

import com.mc.constraints.impl.FieldMatchValidator;  

import javax.validation.Constraint;  
import javax.validation.Payload;  
import java.lang.annotation.Documented;  
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;  
import static java.lang.annotation.ElementType.TYPE;  
import java.lang.annotation.Retention;  
import static java.lang.annotation.RetentionPolicy.RUNTIME;  
import java.lang.annotation.Target;  

@Target({TYPE, ANNOTATION_TYPE})  
@Retention(RUNTIME)  
@Constraint(validatedBy = FieldMatchValidator.class)  
@Documented  
public @interface FieldMatch {  

    String message() default "{constraints.fieldmatch}";  

    Class<?>[] groups() default {};  

    Class<? extends Payload>[] payload() default {};  

    String first();  

    String second();  

    @Target({TYPE, ANNOTATION_TYPE})  
    @Retention(RUNTIME)  
    @Documented  
    @interface List {  

        FieldMatch[] value();  
    }  
}  

FieldMatchValidator.java

package com.mc.constraints.impl;  

import javax.validation.ConstraintValidator;  
import javax.validation.ConstraintValidatorContext;  
import com.mc.constraints.FieldMatch;  
import org.apache.commons.beanutils.BeanUtils;  

public class FieldMatchValidator implements ConstraintValidator<FieldMatch, Object> {  

    private String firstFieldName;  
    private String secondFieldName;  

    @Override  
    public void initialize(final FieldMatch constraintAnnotation) {  
        firstFieldName = constraintAnnotation.first();  
        secondFieldName = constraintAnnotation.second();  
    }  

    @Override  
    public boolean isValid(final Object value, final ConstraintValidatorContext context) {  
        try {  
            final Object firstObj = BeanUtils.getProperty(value, firstFieldName);  
            final Object secondObj = BeanUtils.getProperty(value, secondFieldName);  

            return firstObj == null && secondObj == null || firstObj != null && firstObj.equals(secondObj);  
        } catch (final Exception ignore) {  
            // ignore  
        }  
        return true;  
    }  
}  

Stock.java

package com.mc.stock;  

import com.mc.constraints.FieldMatch;  
import java.io.Serializable;  
import java.util.HashSet;  
import java.util.Set;  
import javax.persistence.Basic;  
import javax.persistence.Column;  
import javax.persistence.Entity;  
import javax.persistence.GeneratedValue;  
import javax.persistence.GenerationType;  
import javax.persistence.Id;  
import javax.persistence.NamedQueries;  
import javax.persistence.NamedQuery;  
import javax.persistence.OneToMany;  
import javax.persistence.SequenceGenerator;  
import javax.persistence.Table;  
import javax.xml.bind.annotation.XmlRootElement;  
import javax.xml.bind.annotation.XmlTransient;  
import org.hibernate.annotations.Cascade;  
import org.hibernate.annotations.CascadeType;  
import org.hibernate.validator.constraints.Length;  

@Entity  
@Table(name = "STOCK")  
@XmlRootElement  
@NamedQueries({  
    @NamedQuery(name = "Stock.findAll", query = "SELECT s FROM Stock s"),  
    @NamedQuery(name = "Stock.findByStockId", query = "SELECT s FROM Stock s WHERE s.stockId = :stockId"),  
    @NamedQuery(name = "Stock.findByStockCode", query = "SELECT s FROM Stock s WHERE s.stockCode = :stockCode"),  
    @NamedQuery(name = "Stock.findByStockName", query = "SELECT s FROM Stock s WHERE s.stockName = :stockName")})  
@FieldMatch.List({  
    @FieldMatch(first = "stockCode", second = "stockName", message = "Code and Stock must have same value")  
})  
public class Stock implements Serializable {  

    private static final long serialVersionUID = 1L;  
    @Id  
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq_stock_id")  
    @SequenceGenerator(name = "seq_stock_id", sequenceName = "seq_stock_id", initialValue = 1, allocationSize = 1)  
    @Basic(optional = false)  
    @Column(name = "STOCK_ID", unique = true, nullable = false)  
    private Integer stockId;  
    @Column(name = "STOCK_CODE")  
    private String stockCode;  
    @Length(min = 1, max = 20, message = "{wrong stock name length}")  
    @Column(name = "STOCK_NAME")  
    private String stockName;  

    public Stock() {  
    }  

    public Stock(Integer stockId) {  
        this.stockId = stockId;  
    }  

    public Integer getStockId() {  
        return stockId;  
    }  

    public void setStockId(Integer stockId) {  
        this.stockId = stockId;  
    }  

    public String getStockCode() {  
        return stockCode;  
    }  

    public void setStockCode(String stockCode) {  
        this.stockCode = stockCode;  
    }  

    public String getStockName() {  
        return stockName;  
    }  

    public void setStockName(String stockName) {  
        this.stockName = stockName;  
    }  

    @Override  
    public int hashCode() {  
        int hash = 0;  
        hash += (stockId != null ? stockId.hashCode() : 0);  
        return hash;  
    }  

    @Override  
    public boolean equals(Object object) {  
        // TODO: Warning - this method won't work in the case the id fields are not set  
        if (!(object instanceof Stock)) {  
            return false;  
        }  
        Stock other = (Stock) object;  
        if ((this.stockId == null && other.stockId != null) || (this.stockId != null && !this.stockId.equals(other.stockId))) {  
            return false;  
        }  
        return true;  
    }  

    @Override  
    public String toString() {  
        return "com.mc.stock.Stock[ stockId=" + stockId + " ]";  
    }  
}  

HibernateUtil.java

package com.mc.util;  

import org.hibernate.SessionFactory;  
import org.hibernate.cfg.Configuration;  

public class HibernateUtil {  

    private static final SessionFactory sessionFactory = buildSessionFactory();  

    private static SessionFactory buildSessionFactory() {  
        try {  
            // Create the SessionFactory from hibernate.cfg.xml  
            return new Configuration().configure().buildSessionFactory();  
        } catch (Throwable ex) {  
            // Make sure you log the exception, as it might be swallowed  
            System.err.println("Initial SessionFactory creation failed." + ex);  
            throw new ExceptionInInitializerError(ex);  
        }  
    }  

    public static SessionFactory getSessionFactory() {  
        return sessionFactory;  
    }  

    public static void shutdown() {  
        // Close caches and connection pools  
        getSessionFactory().close();  
    }  
}  

Oracle DB Structure

CREATE TABLE stock  
(  
    STOCK_ID  NUMBER(5)  NOT NULL ,  
    STOCK_CODE  VARCHAR2(10)  NULL ,  
    STOCK_NAME  VARCHAR2(20)  NULL   
);  

ALTER TABLE stock  
    add CONSTRAINT PK_STOCK_ID  PRIMARY KEY (STOCK_ID);  

create sequence seq_stock_id   
   start with 1   
   increment by 1   
   nomaxvalue;  

解决方案

I'm inclined to do as much validation before you get the the DB level. Have a look at Hibernate Validator, http://www.hibernate.org/subprojects/validator.html which is the reference implementation of JSR-303.

Using standard annotations you can enforce constraints and get good error messages before you attempt to put the entities into your database.

I believe this will allow you to validate at the entity level as requested.

这篇关于休眠异常处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆