نحوه استفاده از schema و catalog به صورت عمومی در کوئری های SQL و HQL

زمانی که ساختار پایگاه داده شما به صورتی است که از چندین شما استفاده می کنید، می توانید با استفاده از hibernate.default_schema در فایل مربوط به تنظیمات Hibernate از یک شمای کلی به عنوان شمای عمومی استفاده کنید:

<property name="hibernate.default_schema" value="forum"/>

هایبرنت با استفاده از کد فوق، در جاهایی که قصد اجرای کوئری HQL را دارید، شما مورد نظر را در تبدیل کوئری از HQL به SQL استفاده می کند. به مثال زیر توجه کنید:

@Entity(name = "Event")
@Table(name = "event")
public class Event { 
    @Id
    @GeneratedValue
    private long id;

    private String name;
    
    @Column(name = "created_on")
    private Timestamp createdOn;

    //Getters and setters omitted for brevity
}

اگر قصد اجرای یک کوئری به صورت زیر داشته باشیم:

List<Event> events = entityManager.createQuery(
    "select e " +
    "from Event e " +
    "where e.createdOn > :timestamp", Event.class)
    .setParameter("timestamp", Timestamp.valueOf(LocalDateTime.now().minusMonths(1)))
   .getResultList();

هایبرنت با استفاده از تنظیمات تعریف شده نام شما را در کوئری SQL ای که تولید می کند، قرار می دهد. یعنی کوئری چیزی مشابه زیر می شود:

SELECT e.id AS id1_0_,
       e.created_on AS created_2_0_,
       e.name AS name3_0_
FROM   forum.event e
WHERE  e.created_on > '2016-09-26 17:22:11.191'

اما اگر درجایی قصد اجرای کوئری به زبان SQL داشته باشیم باید چه کنیم؟ اگر کوئری را به شکل زیر تعریف کنیم:

@NamedNativeQuery(
    name = "past_30_days_events",
    query =
        "select * " +
        "from event" +
        "where age(created_on) > '30 days'",
    resultClass = Event.class
)

و برای اجرای آن به صورت زیر عمل کنیم:

List<Event> events = entityManager.createNamedQuery("past_30_days_events").getResultList();

با خطای زیر مواجه خواهیم شد:

javax.persistence.PersistenceException:
Caused by: org.hibernate.exception.SQLGrammarException: could not extract ResultSet
Caused by: org.postgresql.util.PSQLException: ERROR: relation "event" does not exist

برای حل این مشکل یک راه حل وجود دارد، اینکه هرجا که قصد اجرای کوئری های SQL را داریم، مستقیما به شما مورد نظر اشاره کنیم. یک راه حل هم این هست که این کار به هایبرنت بسپاریم. برای این کار کافی است به شکل زیر عمل کنیم:

@NamedNativeQuery(
    name = "past_30_days_events",
    query =
        "select * " +
        "from {h-schema}event " +
        "where age(created_on) > '30 days'",
        resultClass = Event.class
)

با اینکار هایبرنت هنگام تولید کوئری SQL نام شما را به صورت اتوماتیک تولید می کند:

SELECT * FROM
forum.event
WHERE  age(created_on) > '30 days'

بسیار عالی!!!

نتیجه گیری

استفاده از شمای پیش فرض کار بسیار راحت می کند و تنها کافی این شما را در `hibernate.default_schema` مشخص کنیم. با اینکار کوئری های HQL به راحتی با شمای پیش فرض اجرا می شوند و برای کوئری های SQL نیز بایستی از ‍`{h-schema}` استفاده کنیم.