hibernate和没有PK
是否有可能创build一个表(从JPA注释的Hibernate @ @Entity
)不包含主键/ ID?
我知道这不是一个好主意, 一个表应该有一个主键。
罗杰的自我回答是正确的。 详细说明一下是什么意思(我一开始并不清楚,认为这会有所帮助):
假设你有一张桌子Foo这样的:
TABLE Foo ( bar varchar(20), bat varchar(20) )
通常情况下,你可以写一个w / Annotations类来处理这个表格:
// Technically, for this example, the @Table and @Column annotations // are not needed, but don't hurt. Use them if your column names // are different than the variable names. @Entity @Table(name = "FOO") class Foo { private String bar; private String bat; @Column(name = "bar") public String getBar() { return bar; } public void setBar(String bar) { this.bar = bar; } @Column(name = "bat") public String getBat() { return bat; } public void setBat(String bat) { this.bat = bat; } }
但是,呃。 这个表格没有我们可以用作id的东西,它是我们用于[insert vital business function]的遗留数据库。 我不认为他们会让我开始修改表,以便我使用hibernate。
你可以把对象分割成一个hibernate可行的结构,它允许整行作为关键字。 (当然,这是假定行是唯一的。)
将Foo对象分解为两部分:
@Entity @Table(name = "FOO") class Foo { @Id private FooKey id; public void setId(FooKey id) { this.id = id; } public void getId() { return id; } }
和
@Embeddable class FooKey implements Serializable { private String bar; private String bat; @Column(name = "bar") public String getBar() { return bar; } public void setBar(String bar) { this.bar = bar; } @Column(name = "bat") public String getBat() { return bat; } public void setBat(String bat) { this.bat = bat; }
}
这应该是。 Hibernate将使用Embeddable键作为其所需的身份,并且可以正常进行呼叫:
Query fooQuery = getSession().createQuery("from Foo");
希望这有助于第一次做这个工作。
使用下面的代码; Hibernate没有自己的逻辑来区分重复的logging
让我知道这个方法是否有问题
@Entity @IdClass(Foo.class) class Foo implements Serializable { @Id private String bar; @Id private String bat; public String getBar() { return bar; } public void setBar(String bar) { this.bar = bar; } public String getBat() { return bat; } public void setBat(String bat) { this.bat = bat; } }
我发现它不可能这样做。 对于那些使用遗留系统的人来说,运气不好。
如果您反向工程(从现有JDBC连接创buildJPA注释实体),该表将创build两个Java类,一个实体和一个字段; ID和一个包含你的关系的所有列的embedded式ID。
我发现这个技巧的作品:
<id column="ROWID" type="string" />
您不需要创build一个单独的类作为您的@Id或主键。 只要使用整数(或其他)。 此外,不要发布假钥匙作为使用它的开发人员可能认为这是真实的,否则尝试使用它。 最后,这在VIEW中最好用。 我同意以前的post,在大多数情况下,如果不是所有情况,表格都应该有一个主键。 例如:
@Entity @Table(name = "FOO") class Foo { @SuppressWarnings("unused") @Id private Integer id; @Column(name = "REAL_COLUMN") private String realColumn; public String getRealColumn() { return realColumn; } public void setRealColumn(String realColumn) { this.realColumn= realColumn; } }
从表中创buildPojo – 使用eclipse中存在的反向工程方法。 对于非主键表,eclipse将生成两个Pojo类。
eclipse generated class and hbm.xml - --- Foo.java // public class Foo implements java.io.Serializable { private FooId id; public Foo() { } public Foo(FooId id) { this.id = id; } public FooId getId() { return this.id; } public void setId(FooId id) { this.id = id; } } --- FooId.java // public class FooId implements java.io.Serializable { private String bar; private String bat; public FooId() { } public FooId(String bar, String bat) { this.bar = bar; this.bat = bat; } public String getBar() { return this.bar; } public void setBar(String bar) { this.bar = bar; } public String getBat() { return this.bat; } public void setBat(String bat) { this.bat = bat; } public boolean equals(Object other) { if ((this == other)) return true; if ((other == null)) return false; if (!(other instanceof FooId)) return false; FooId castOther = (FooId) other; return ((this.getBar() == castOther.getBar()) || (this.getBar() != null && castOther.getBar() != null && this.getBar().equals( castOther.getBar()))) && ((this.getBat() == castOther.getBat()) || (this.getBat() != null && castOther.getBat() != null && this.getBat().equals( castOther.getBat()))); } public int hashCode() { int result = 17; result = 37 * result + (getBar() == null ? 0 : this.getBar().hashCode()); result = 37 * result + (getBat() == null ? 0 : this.getBat().hashCode()); return result; } } --- Foo.hbm.xml <hibernate-mapping> <class name="com.Foo" table="foo" schema="public" catalog="hibernate_poc"> <composite-id name="id" class="com.FooId"> <key-property name="bar" type="string"> <column name="bar" length="20" /> </key-property> <key-property name="bat" type="string"> <column name="bat" length="20" /> </key-property> </composite-id> </class> </hibernate-mapping> --- entry in the Hibernate.cfg.xml - <mapping class="com.poc.Foo" resource="Foo.hbm.xml"/> --- Fetch the Data from table - FooDataFetch.java // import java.util.List; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; public class FooDataFetch { private static Session session = null; public static void main(String[] args) { try{ Configuration cfg = new Configuration(); cfg.configure("/hibernate.cfg.xml"); SessionFactory sf = cfg.buildSessionFactory(); session = sf.openSession(); session.beginTransaction(); queryPerson(session); session.close(); }catch (Throwable ex) { System.err.println("Failed to create sessionFactory object." + ex); ex.printStackTrace(); throw new ExceptionInInitializerError(ex); } } private static void queryPerson(Session session) { Query query = session.createQuery("from Foo"); List <Foo>list = query.list(); java.util.Iterator<Foo> iter = list.iterator(); while (iter.hasNext()) { Foo foo = iter.next(); System.out.println("Foo Details: \"" + foo.getId().getBar() +"\", " + foo.getId().getBat()); } } }
添加到Awied的评论。 如果你想要search一个栏,使用下面的HQL。
Query fooQuery = getSession().createQuery("from Foo.id.bar = '<barName>'");
我find了没有主键和空值为表的解决scheme。 它将在oracle数据库上工作。 也许类似的其他数据库存在。
-
您应该在POJO类中创build新的主键:
@Id @Column(name =“id”)private Integer id;
并像这样使用createNativeQuery
getEntityManager().createNativeQuery("select rownum as id, .....
本地查询将生成主键,您将获得唯一的结果。
当涉及到视图而不是在Hibernate中search解决方法时,可能会更容易在数据库视图中添加虚拟标识。 我在另一个问题写了关于它: https : //stackoverflow.com/a/44050230/1673775