考虑图:
我一直在JPA工作了很短的时间,到目前为止,我从来没有需要坚持扩大班......你可以通过的例子,看SNMPNode
,IPNode
等是从所有的扩展类Node
,它也从延长GeoLocation
.
我知道我可以使用and 来修改主类,@MappedSuperclass
并且将继承它们的属性以便持久化......但是在这种情况下,我将得到几乎相同的表,据我所知,我可以将所有信息分组到节点并使用单个表.IPNode
SNMPNode
这是JPA工作或我的概念上的扩展类的持久性是错误的吗?
与恢复的代码相同:
public class Node extends GeoLocation { private String name; private Group group; private Location location; private Type type; private Company company; } public class IPNode extends Node { private Long id; private String ipAddress; } public class SNMPNode extends Node { private Long id; private SNMPServer server; }
[[在此点之后回复]]
为了贡献,这里有一个我最终做的样本:
索引节点:
public interface INode { public Long getId(); public void setId(Long id); public String getName(); public void setName(String name); public String getIpAddress(); public void setIpAddress(String ipAddress); public String getCommunity(); public void setCommunity(String community); }
节点:
@Entity @DiscriminatorValue("N") @DiscriminatorColumn(name="NODE_TYPE",discriminatorType=DiscriminatorType.STRING, length=20) @Inheritance(strategy=InheritanceType.SINGLE_TABLE) public abstract class Node extends GeoLocation implements INode { @Id @GeneratedValue private Long id; private String name; public Long getId() {return id;} public void setId(Long id) {this.id = id;} public String getName() {return name;} public void setName(String name) {this.name = name;} (... Overrides from INode ...) }
IPNode:
@Entity @DiscriminatorValue("I") public class IPNode extends Node { private String ipAddress; public String getIpAddress() { return this.ipAddress;} public void setIpAddress(String ipAddress) { this.ipAddress = ipAddress; } (... Overrides from INode ...) }
SNMPNode:
@Entity @DiscriminatorValue("S") public class SNMPNode extends Node { private String community; public String getCommunity() { return community;} public void setCommunity(String community) { this.community = community; } (... Overrides from INode ...) }
NodeRepository:
@Repository public interface NodeRepository extends JpaRepository{ }
所以现在我可以做这样的事情:
@ContextConfiguration("classpath:/spring/application-context.xml") @RunWith(SpringJUnit4ClassRunner.class) public class NodeRepositoryTest { @Autowired NodeRepository repo; private INode node; @Before @Transactional @Rollback(false) public void setup() { node = new IPNode(); node.setName("ipNode"); node.setIpAddress("1.1.1.1"); repo.save((IPNode)node); node = new SNMPNode(); node.setName("snmpNode"); node.setIpAddress("2.2.2.2"); node.setCommunity("some text"); repo.save((SNMPNode)node); } @Test @Transactional public void Test() throws Exception { INode testNode = repo.findOne(1L); assertNotNull(testNode); } }
两种节点类型都保存在同一个表中,因此它们的密钥不能重复...我的REST URL可以通过/ nodes/1或/ nodes/2获取它们,这毕竟是我的主要目标......
谢谢 :)
如果基类使用注释进行注释,@MappedSuperclass
那么继承只与OOP上下文相关.该@MappedSuperclass
特性被简单地复制到每个子类相关联的数据库表,并且只能用于子类的实体查询.
单表继承产生最佳性能(不涉及连接或联合),代价是无法声明所有特定子类属性的不可空(因为所有基类和所有子类特定属性都转到单个数据库表) ).
使用连接的继承表,您可以在基础数据库表中具有基类属性,并且每个特定的子类都具有它自己的关联表.子类表通过FK与基础数据库表链接,因此您需要连接这些表以获取子类实体.如上所述@MappedSuperclass
,基类是可查询的,因为OOP上下文和数据库都反映了继承模型.