工作中遇到一個數據庫的問題,有關同義詞和屬主的,由於自己對這塊知識不瞭解,所以整理了一下,理了理思路~
先說明一下,同義詞這個東西,在Oracle中,SqlServer2005以上中有,mysql數據庫中沒有。屬主在這三個數據庫中是都有的。不過工作中遇到的問題是Oracle10的,所以下面的以Oracle爲基礎。
爲了搞明白這問題,我們先來了解幾個概念:
1、屬主(owner)用簡單的話來說就是數據庫的用戶。
2、Schema是數據庫對象的集合,一個用戶一般對應一個schema,該用戶的schema名等於用戶名,並作爲該用戶的缺省schema,這也是爲什麼程序中的schema名都爲數據庫用戶名的原因。注意:Oracle數據庫中不能新創建一個schema,要想創建一個schema,只能通過創建一個用戶的方法解決。
3、同義詞(synonyms)從字面上理解就是別名的意思,和試圖的功能類似,就是一種映射關係。設置同義詞後,用有權限的用戶訪問時,可以隱蔽掉user名。
搞明白了這些概念,我們來看一下它們的一些簡單應用場景:
1、schema的使用
user是控制權限的,而schema則是一個容器,非所有者如果需要訪問這個容器下的對象,就需要在對象前面寫上schema(owner)的名字。
(1)例如:在同一個庫的實例裏,A、B都有查詢權限,從A用戶下查詢B用的表,就是:select * from B.表名。
(2)例如:hibernate在實現實體映射時,DB無需強行指定。部署時會較對DB戶名和密碼,根據用戶名以訪問的表完成實體映射。如果一個帳號可以訪問一個數據庫的下多個表,以oracle爲例用戶user1下面有表table1 ,user2下面也有table1,且user1有user2的所有權限,那麼部署時可能就會搞錯table,出於安全hiberante在配置時設置默認的schema較爲安全。
1、同義詞的使用
(1)創建同義詞
create public synonym table_name for user.table_name;
public:公共的,不加public修飾詞是私有的,公共的名字可以與表名相同,私有的同義詞不可以。
public同義詞只是爲數據庫對象定義了一個公共的別名,其他用戶能否通過這個別名訪問數據庫對象,還要看是否已經爲這個用戶授權。
你可能需要在user用戶中給當前用戶(user2)授權: grant select/delete/update on 表 to user2。
(2)刪除同義詞
drop public synonym table_name;
(3)查看所有同義詞
select * from dba_synonyms;
上面瞭解後,分析下工作中遇到的問題:
有一個項目X從1.0升級到2.0,需要部署,目前環境是在一個數據庫實例下有A、B、C三個用戶,它們的權限一致,A用戶下面的表是項目X的1.0版本的表,B用戶下面是下面X的2.0的表,A用戶的所有表都設置了公共的同義詞,爲了安全考慮,C用戶是實際對項目X開放的用戶。
由之前的知識鋪墊可知,在同義詞與表名一致的前提下,如果使用C用戶之間查詢表名,會首先通過公共的同義詞訪問到A用戶下得表,如果再創建一個用戶D,把A的同義詞改爲私有的同義詞,並且只對D授權,D是訪問項目X的1.0的開放用戶,C作爲項目X的2.0的開放用戶,這個方法是可以的,但是有個問題是私有的同義詞名稱不能與表名相同,客戶是想同義詞名與表名保持一致的,便於管理和訪問,所以這個方法不能使用。因此,現在的思路是打算在屬主方面下手來解決問題,對錶制定屬主,這樣一來就不會訪問到公共的同義詞了。
對於程序的改動:
在程序的hibernate的properties配置文件中,加入如下配置,指定默認屬主
hibernate.default_schema=harold
注意:程序中,與數據庫相關的sql需要用hql,如果sql語句用createSQLQuery等方法的地方,需要注意會報錯,找不到表,因爲這裏不會走hibernate配置的默認schema。所以這種地方,可以修改爲hql的語句,或者通過程序加載schema。
例如:
/**
加載schema的工具類
@author harold
*/
public class InitUtil {
/**
hibernate的properties文件的文件名
*/
private static final String propFileName = "hibernate.properties";
private static Properties props= new Properties();
/**
功能:取得properties配置文件
@author harold
@return
*/
public static Properties getInitProperties(){
InputStream is=InitUtil.class.getClassLoader().getResourceAsStream(propFileName);
try {
props.load(is);
} catch (IOException e) {
e.printStackTrace();
}
return props;
}
/**
功能:獲得hibernate的默認schema
@author harold
@return
*/
public static String getDefaultSchema(){
return InitUtil.getInitProperties().getProperty("hibernate.default_schema");
}
/**
功能:判斷schema是否爲空
@author harold
@return
*/
public static boolean isSchemaNullOrBlank() {
String src = InitUtil.getDefaultSchema();
if (src == null) {
return true;
} else if (src.trim().length() < 1) {
return true;
} else {
return false;
}
}