2010-02-15 129 views
1

我有以下两个表(这与春季安全追平 - 但我相信这个问题是使用Hibernate):帮助Hibernate(Spring)中的外键映射?

Table user 
Table authority 

user表被捆绑(通过Hibernate)的域对象在我的应用程序:class User,其具有以下属性(和相应的getter和setter),其对应于在user表中的列(除了后述的集合):

long uId 
String username 
String password 
... 
Collection<GrantedAuthority> authorities 

authority表有两列:UserIduser表中的外键)和Authority(例如, “ROLE_USER”)。此表不被表示为域对象,但仅是User类中的一个集合。

要创建的映射,在我.hbm文件我用如下:

<class name="com.business.project.domain.User" table="user"> 
    <id name="uId" column="UserId"></id> 
    <property name="username" column="Name" type="java.lang.String" /> 
    <property name="password" column="Password" type="java.lang.String" /> 
    ... 
    <set name="authorities" table="authority"> 
     <key column="UserId" /> 
     <element column="Authority" type="java.lang.String" /> 
    </set> 
</class> 

在我休眠DAO实现中,我创建一个查询对象,执行查询,并把结果向User对象:

... 
Query query = session.createQuery("from User where name = :username"); 
... 
User user = (User) query.uniqueResult(); 

在这一点上,我希望这个对象来与它从DB拉(我确信,该​​表与试验数据正确填充和映射的名字是在映射正确的数据填充文件)。

但是,由于某种原因,在user对象上调用各种属性的getter方法都会返回NULL。有人可以看到我的设置立即出错吗?也许我映射集合(到外键关系)是错误的?谢谢!

更新:这里是SQL查询Hibernate生成(从它的调试输出取):

Hibernate: select user0_.UserId as UserId1_, user0_.Name as Name1_, 
    user0_.Password as Password1_ from user user0_ where user0_.Name=? 

出于某种原因,它不会显示相关authority表什么...不这意味着我的映射不正确?

编辑:每bozho的建议下,我看了一眼在启动时对CONSOL消息(Tomcat)的,但没有看到任何不寻常的:

Feb 16, 2010 10:35:12 AM org.hibernate.cfg.HbmBinder bindRootPersistentClassCommonValues 
INFO: Mapping class: com.me.project.domain.User -> user 
Feb 16, 2010 10:35:12 AM org.hibernate.cfg.HbmBinder bindCollection 
INFO: Mapping collection: com.me.project.domain.User.authorities -> authority 
+1

您使用的是什么版本的Spring Hibernate。 。 。好奇 – 2010-02-15 21:58:55

+0

Spring 3.0和hibernate 3.2.7 – oym 2010-02-15 22:02:37

+0

映射对我来说看起来还不错,而且这种关联似乎也没问题,但这就像在黑暗中摸索。你能否提供完整的映射,以及如何将你的映射添加到sessionfactory,比如spring config?你能够保存对象吗?你看到他们在你的SQL浏览器?如果这只是用户实体的一个问题,我建议在单元测试中尝试重现它,并在春天的东西。 – zoidbeck 2010-02-15 22:13:01

回答

0
Query query = session.craeteQuery("FROM User WHERE username = :username"); 
query.setString("username", "SomeUserName"); 

这应该几乎做到这一点。

+0

我有这个,我只是没有显示行。唯一的区别是,我使用了以下内容:query.setString(“username”,username);其中username是该方法的参数。我尝试setParamter()只是为了有趣和同样的问题。 – oym 2010-02-15 22:05:16

+0

System.out.println该参数的值,看看它是什么 – Bozho 2010-02-15 22:18:59

+0

是的,我在该函数中调试调用,打印出适当的值和它的集合(即该值存在于数据库中)。 Thakns建议。 – oym 2010-02-15 22:21:21

0

尝试用"from User where username = :username"

HQL使用类的属性,而不是数据库列名

+0

同样的效果:一切都是NULL。我觉得这很奇怪 - 如果我不正确地使用列名取代类属性,我会不会在之前得到一些其他错误? – oym 2010-02-15 21:45:54

+0

当我将名称更改为既不是类属性也不是db列名的东西时,则出现错误。也许hibernate足够聪明地检查类属性和映射到哪个数据库列?无论哪种方式,我的原始问题仍然存在.. – oym 2010-02-15 21:56:49

+0

可以配置休眠以记录它的SQL查询吗?有没有真正的SQL查询? – 2010-02-15 21:57:21

0

您是否每次运行测试/ java代码都清除数据库?在休眠中有一个设置,当它打开时,它可以在每次运行测试/ java代码时清除数据库。

你可以做一个findAll()并打印大小?我非常怀疑这是错误的数据库,或者数据库中没有数据或数据清除。

注意:检查配置文件中的“hibernate.hbm2ddl.auto”属性。如果它被设置为“create-drop”,hibernate会在启动时自动创建模式,并在VM关闭时删除模式。只是点到“更新”或类似

http://docs.atlassian.com/hibernate2/2.1.8/reference/session-configuration.html

+0

返回一行(完全填充)感谢您的建议,我会研究它并让你知道。但是我很怀疑,因为我总是打开一个数据库管理程序,向我显示数据,而且数据不会被清除。 – oym 2010-02-16 15:32:33

+0

也只是做一个findAll,遍历每个用户并打印所有内容。你会知道你是否错过了一些东西。也许“用户名”有一个空间,你没有给,在最后的空间......东西:) – 2010-02-16 16:16:47

+0

仍然一切都是空的。正如我在之前的评论中提到的那样,我试着直接用Hibernate生成的查询字符串查询数据库(我从它的调试输出中提取),并正确地返回该行... – oym 2010-02-16 16:36:06

0

“密码”,通常是在数据库的关键字。这似乎是你遇到名称冲突问题。尝试以下操作。在列名称周围放置刻度标记以进行转义。

<property name="username" column="`Name`" type="java.lang.String" /> 
<property name="password" column="`Password`" type="java.lang.String" /> 

假设您使用的是org.springframework.security.GrantedAuthority,那么您的权威映射不正确。根据你映射的方式,当你访问集合时,你很有可能会得到一个ClassCastException。你可能想使用类似UerType的东西来避免这个问题。