在Hibernate中的@Formula中使用NATURAL JOIN

时间:2015-02-08 11:31:07

标签: java mysql hibernate join formula

我在使用NATURAL JOIN的Hibernate中使用@Formula时遇到问题。

我有三张桌子:

CREATE TABLE IF NOT EXISTS `tz_points_logs` (
  `points_log_id` bigint(20) NOT NULL,
  `points_to_uid` bigint(20) NOT NULL,
  `points_get_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `points_rule_id` int(4) NOT NULL,
  `points_meta` text NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `tz_points_rules` (
  `points_rule_id` int(4) NOT NULL,
  `points_rule_credits` int(4) NOT NULL,
  `points_rule_title` varchar(32) NOT NULL,
  `points_rule_description` text NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `tz_users` (
  `uid` bigint(20) NOT NULL,
  `username` varchar(16) NOT NULL,
  `password` varchar(32) NOT NULL,
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

在Hibernate中,有三种映射模型:UserPointsLogPointsRule

现在,@Formal模型中有一个User字段:

@Entity
@Table(name = "tz_users")
public class User implements Serializable {
    // Getters and Setters

    @Id
    @GeneratedValue
    @Column(name = "uid")
    private long uid;

    @Column(name = "username")
    private String username;

    @Column(name = "password")
    private String password;

    @OneToMany(targetEntity = PointsLog.class, 
                fetch = FetchType.LAZY, mappedBy = "user")
    private List<PointsLog> pointsLogs = new ArrayList<PointsLog>();

    @Formula(value = "(SELECT COUNT(*) FROM tz_points_logs pl NATURAL JOIN tz_points_rules WHERE pl.points_to_uid=uid)")
    private long credit;
}

获得用户信用时出现错误:

com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use 
near 'user0_.NATURAL JOIN tz_points_rules WHERE pl.points_to_uid=user0_.uid) as formul' at line 1
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:408)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:377)
    at com.mysql.jdbc.Util.getInstance(Util.java:360)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:978)
    ...
    at java.lang.Thread.run(Thread.java:745)

似乎Hibernate无法识别NATURAL JOIN中的@Formula。 有没有其他方法来实现这个功能?

顺便说一下,以下声明可以正常使用。

@Formula(value = "(SELECT COUNT(*) FROM tz_points_logs pl WHERE pl.points_to_uid=uid)")

非常感谢。

1 个答案:

答案 0 :(得分:1)

this answer中讨论了类似的问题。这里的要点是--H​​ibernate将NATURAL关键字视为属性/列名称。解决方法应该是 - 在方言中将 NATURAL 注册为keyword

例如:

// extend the correct dialect ... in this case MySql
// but simply extend the currently used dialect
public class CustomMySQLDialect extends MySQL5InnoDBDialect
{
    public CustomMySQLDialect()
    {
        super();
        registerKeyword("NATURAL");
    }
}

接下来将Hibernate配置为使用此CustomMySQLDialect,并且应该生成FORMULA:

// instead of this
// user0_.NATURAL JOIN

// we should get this
NATURAL JOIN