17

I am using JPA and I need to make the "tableName" a variable.

In a database, I have many tables, and my code needs to access the table where I specify it to read.

@Entity
@Table(name = "tableName")
public class Database implements Serializable {...............}

Any ideas?

zengr
  • 38,346
  • 37
  • 130
  • 192

6 Answers6

9

You can do something like this, if thats your concern, I guess. Never tried it, its just a wild guess. But thats the usual practice -- I follow for Named Queries; yes, that's a different thing altogether.

@Entity
@Table(name = Database.tableName)
public class Database implements Serializable {
    public static final String tableName = "TABLE_1";
    ...............
}

But I don't see why anyone would do that. Could you tell us what are you up to? Why you have few tables exactly same definition?

[Edited]

I tried your solution. It did not work, it says: The value for annotation attribute Table.name must be a constant expression.

So, isn't that clear enough? I mean you can't do that. And I believe its quite logical. If you want Hibernate to generate your schema then you can define all the entities you want, in the schema, and with the appropriate relationships.

Adeel Ansari
  • 39,541
  • 12
  • 93
  • 133
  • 1
    Ok, this is my scenario. I have one JPA class called "Database" and I can have many number of Tables (depending on the input data from the client side). So, for now, the Database class only creates ONE table when it runs (@Table = name). But I need this class to create Tables at runtime with the TableName variable coming from some where else. I tried your solution. It did not work, it says: The value for annotation attribute Table.name must be a constant expression. – zengr Mar 15 '10 at 04:06
  • To rephrase: I need dynamic schema. Where the Table is created on the fly. – zengr Mar 15 '10 at 04:14
  • @zengr: Check out my addendum to the post. – Adeel Ansari Mar 15 '10 at 04:27
  • Thanks for your help. :) I am using JPA and one more question, will "em.createNativeQuery(create table SQL query)" work? where EntityManager em. – zengr Mar 15 '10 at 04:27
  • and, is this post a workaround? http://java.dzone.com/articles/hibernate-dynamic-table-routin – zengr Mar 15 '10 at 04:29
  • @zengr: Yes the query should work. Regarding the example, I don't see how that fits in. It is discussing the issue of accessing 2 different schemas. – Adeel Ansari Mar 15 '10 at 06:30
  • Know this is an old question but if you're going to use a static variable for the table name you should make it final and protected. Someone could come along and change this value which may be used for building up queries in other classes. – John Apr 24 '15 at 13:43
3

If you want only to reference/read the table name, it is possible as in the code below. If you want to change, it is not possible as Pascal said.

@Entity
@Table(name = Database.tableName)
public class Database implements Serializable {
    public static final String tableName = "TABLE_1";//this variable you can reference in other portions of your code. Of course you cannot change it.
    ...............
}
V G
  • 18,822
  • 6
  • 51
  • 89
3

Specifying the table name at runtime is not possible, this is simply not how JPA works (and I'm still not sure to get your requirement). Either map different entities on your set of tables and run various queries or build them dynamically (maybe using the Criteria API) depending on the input from the client side or use something else than JPA (like iBATIS).

Pascal Thivent
  • 562,542
  • 136
  • 1,062
  • 1,124
  • Is this a possible workaround? http://java.dzone.com/articles/hibernate-dynamic-table-routin – zengr Mar 15 '10 at 04:42
  • 2
    @zengr I can't answer this question, I still don't understand what you're trying to do. Dynamic tables? Different schemas? This is not clear. – Pascal Thivent Mar 15 '10 at 14:10
  • @zengr It does look like this link does what you want (although it can completely obfuscate things for a maintenance engineer). Hibernate Shards is also an interesting option. But when you go in this direction, ask yourself many many times "Do you really need this?". Is your project really really complex to warrant this complex solution? – Kannan Ekanath Mar 15 '10 at 14:41
2

I have a workaround.
It uses javax.persistence.EntityManager and String.format to do that.

package com.example.test.dao;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;
import javax.persistence.EntityManager;

@Component
public class SomeDao {
    @Autowired
    EntityManager em;

    public List<?> listFoodMoneyDateOfPayment(int departmentId, String sumKey, String tableName) {
        String s = "SELECT SUM(%s) AS money, CONCAT(YEAR(apply_time), '-', MONTH(apply_time)) AS yearmonth " +
                "FROM (%s) WHERE department_id = %d GROUP BY yearmonth";
        String sql = String.format(s, sumKey, tableName, departmentId);
        System.out.println(sql);

        List<?> test = em.createNativeQuery(sql).getResultList();

        return test;
    }
}

The invoke code is that:

@RestController
@RequestMapping("/api")
public class TestController {

    @Autowired
    private SomeDao dao;

    @RequestMapping("/test2")
    public HttpEntity test2() {
        var l = dao.listFoodMoneyDateOfPayment(12, "food_payment", "payment_application");
        System.out.println(l.getClass());
        System.out.println(JSON.toJSONString(l));
        return ResultBean.success();
    }
}

And it works well.
But you should check the arguments passed in.

h10g
  • 396
  • 1
  • 4
  • 12
0

If you want to select data from different tables,

then you can use :

@Subselect("")

instead of :

@Table(name = "tableName").

Yaje
  • 2,753
  • 18
  • 32
Alex85
  • 135
  • 1
  • 3
  • 10
0

We can leverage interface constants and initialize at annotation

This is possible because all interface variable are by default constants.

interface DomainPropertiesHelper {
 String TABLE_NAME = "DB_TABLE";
} 


@Entity
@Table(name = DomainPropertiesHelper.TABLE_NAME)
class Database implements Serializable {
 @Id
 private Long id;
}