2010-01-22 30 views
2

我有一個使用JPA和Hibernate 3.3.x的代碼。 此Java代碼可以與存儲在Oracle 10g或MySQL 5.1.x上的模式一起使用。 使用約束來定義表以定義唯一記錄。 發生約束違規時,我想從異常中檢索約束名稱。Hibernate:constraintName在MySQL中爲null

使用Oracle,可正確檢索約束名稱。 使用MySQL,約束名稱是NULL

任何想法如何獲得與MySQL約束名稱?

感謝

回答

0

你在數據庫級別指定在MySQL中的約束的名字呢?在Oracle中,如果沒有指定,約束會得到默認名稱,但是在MySQL中,我不知道,我想我曾經聽說過,如果您沒有爲約束指定名稱,MySQL不會放置默認名稱!

+0

是我設置的名稱,如下圖所示。 ALTER TABLE MY_TABLE ADD CONSTRAINT MY_CONSTRAINT UNIQUE(Col1,Col2,Col3); 我有一個DDL腳本來爲MySQL和Oracle 10g創建數據庫模式。約束在bith DDL腳本中以相同的方式定義。 當我調試我的應用程序時,我看到在Oracle中約束名稱是預期的(MY_Constraint基於我的插圖)。 當我更改持續單元以開啓MySQL時,我收到NULL作爲約束名稱。 – eloudsa 2010-01-22 22:19:40

+0

您是否嘗試使用SQL客戶端查看MySQL數據庫的約束名稱以查看它們是否顯示? – 2010-01-24 11:04:01

5

我已經想出了以下解決方案:

  1. 擴展現有的Hibernate MySQL5Dialect:

    public class MySQL5Dialect extends org.hibernate.dialect.MySQL5Dialect { 
    
        /** 
        * Pattern to extract violated constraint name from {@link SQLException}. 
        */ 
        private static final Pattern PATTERN = Pattern.compile(".*constraint\\W+(\\w+).*", Pattern.CASE_INSENSITIVE); 
    
        private ViolatedConstraintNameExtracter constraintNameExtracter; 
    
        public MySQL5Dialect() { 
         constraintNameExtracter = new ConstraintNameExtractor(); 
        } 
    
        @Override 
        public ViolatedConstraintNameExtracter getViolatedConstraintNameExtracter() { 
         return constraintNameExtracter; 
        } 
    
        private class ConstraintNameExtractor implements ViolatedConstraintNameExtracter { 
    
         @Override 
         public String extractConstraintName(SQLException sqle) { 
          final String msg = sqle.getMessage(); 
          final Matcher matcher = PATTERN.matcher(msg); 
          String constraintName = null; 
          if (matcher.matches()) { 
           constraintName = matcher.group(1); 
          } 
    
          return constraintName; 
         } 
    
        } 
    
    } 
    
  2. 指定的Hibernate配置文件(hibernate.cfg.xml中),新創建的話:

    <property name="dialect">your.package.MySQL5Dialect</property> 
    
  3. 現在getConstraintName()會ret甕實際違反約束名稱:

    try { 
        ... 
    } catch (ConstraintViolationException e) { 
        LOG.error(String.format("Constraint=%s, code=%d", e.getConstraintName(), e.getErrorCode())); 
    } 
    
1

嘗試使用這樣的:

try { 
// ... 
} catch (ConstraintViolationException t) { 
     if (t.getCause().getLocalizedMessage().contains("your_constraint_name")) { 
      // ... 
     } 
} 
相關問題