HIbernate的实体自关联如何写配置文件
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HIbernate的实体自关联如何写配置文件相关的知识,希望对你有一定的参考价值。
例如,我们写一个类来描述生活中的接口,架设写的是RJ45接口,因为RJ45接口只能与RJ45接口连接,所以在RJ45接口类里面有一个linker是RJ45类型的,那么在这种情况下怎么写关联呢?已知写成<one-to-one name="linker" />的话是不行的。求大牛指导、、、
单项的配置many-to-one吧,如果是一对一,还要在里面写unique="true",本来是多对一,但是加上unique="true",就表示唯一,那就是一对一了。如果是双向关联,则要在另外一边配置one-to-one,property_ref="linker",property_ref=""相当于mappedBy,就是指定由哪一方来维护双方的关系。
写配置文件累死了,而且时不时有一些错误,直接用Annotation方便得多,其实hibernate帮助文档上提供了很多例子,要学会穿一手鞋,主动学习放弃被动灌输。
以下是1对1的关系配置
一对一:(少用,可以合成一张表,数据库表一般设计成单向外键关联或主键关联)
外键关联:
单向:@OneToOne @JoinColumn指定外键列名 <many-to-one unique="true"/>
双向:@OneToOne(MappedBy,意思是由哪边维护关联关系,相当与xml中的inverse)
<many-to-one unique="true"/> <one-to-one property_ref=""/>(property_ref相当于MappedBy) 两个都用<many-to-one/>也会生成两个外键
注意:
1、对于双向关联除了双向主键关联,annotation必须加MappedBy(否则会产生冗余外键)
2、设置MappedBy还可以在添加的时候由对方设置关联不再需要两边都设置追问
这些对自关联都是不起作用的,因为自关联它关联的本来就是自身的实体,在写关联关系时,它只能写一个而已。
追答那你把一张表看做两张表,一个对象看做两个对象不就行了么
比如Oracle数据库中的scott用户下有一张emp表,其中有两个列:empno和mgr是一模一样的,empno是员工编号,mgr是上司的员工编号,而上司也属于一个员工,所以mgr这个列中的数据都是引用empno这个列的。
写java实体类的时候,你只要在该类中加入一个自己的引用,用来表示上司,不就行了?如果还要找出你的下属,那就加一个Set集合,集合中的对象就是自己。
@Entity
public class Emp
@Id
private int empno;
private String ename;
//下属和上司存在1对多的关系,也就是1个上司有多个下属,所以是ManyToOne
@ManyToOne
private Emp mgr; //这就是引用自己
//双向关联时,只要加上OneToMany就行了,关系肯定是由多的一方维护,所以加mappedBy
@OneToMany(mappedBy="mgr")
private Set xiashu; //这就是你的下属
这样就是自联1对多,自联1对1还不就是一样的。
如何使用 JPA 和 Hibernate 为关联的只读实体获取单个实例?
【中文标题】如何使用 JPA 和 Hibernate 为关联的只读实体获取单个实例?【英文标题】:How to get a single instance for an associated read-only entity with JPA and Hibernate? 【发布时间】:2019-07-18 08:10:49 【问题描述】:我有这两个实体:
@Entity
@Immutable
@Cacheable
@Cache(region = "dosefrequency", usage = CacheConcurrencyStrategy.READ_ONLY)
public class DoseFrequency
.....
@Entity
public class PrescriptionDrug
.....
@ManyToOne(optional=false)
@JoinColumn(name="doseFrequency")
public DoseFrequency getDoseFrequency()
return doseFrequency;
DoseFrequency 是一个只读实体,PrescriptionDrug 关联了一个 DoseFreqyency。我希望每次加载一个或多个 PrescriptionDrug 时都不会重复 DoseFrequency 的实例。
我知道 DoseFrequency 实例将被缓存在 hibernate 的一级缓存中,但加载是在几个会话中完成的(它是一个 web 应用程序)。我用的是二级缓存,但是那个缓存不存储实例只序列化实体。
我在 DoseFrequency 中使用 Tuplizer 得到了这种行为,但我不知道是否有任何其他方法可以实现这一点。
@Entity
@Immutable
@Cacheable
@Cache(region = "dosefrequency", usage = CacheConcurrencyStrategy.READ_ONLY)
@Tuplizer(impl=DoseFrequencyTuplizer.class)
public class DoseFrequency
....
public class DoseFrequencyTuplizer extends PojoEntityTuplizer
public DoseFrequencyTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappedEntity)
super(entityMetamodel, mappedEntity);
@Override
protected Instantiator buildInstantiator(EntityMetamodel entityMetamodel, PersistentClass persistentClass)
return new DoseFrequencyInstantiator(DoseFrequency.class.getName(),entityMetamodel,persistentClass,null);
public class DoseFrequencyInstantiator implements Instantiator
private final Class targetClass;
protected PojoEntityInstantiator pojoEntityInstantiator;
public DoseFrequencyInstantiator(String targetClassName, EntityMetamodel entityMetamodel,
PersistentClass persistentClass, ReflectionOptimizer.InstantiationOptimizer optimizer)
try
this.targetClass = Class.forName(targetClassName);
catch (ClassNotFoundException e)
throw new HibernateException(e);
pojoEntityInstantiator = new PojoEntityInstantiator(entityMetamodel, persistentClass, optimizer);
@Override
public Object instantiate(Serializable id)
DoseFrequency df = MedereEMRCache.instance.findDoseFrequencyByID(Long.valueOf(id.toString()));
if (df == null)
return pojoEntityInstantiator.instantiate(id);
return df;
@Override
public Object instantiate()
return instantiate(null);
@Override
public boolean isInstance(Object object)
try
return targetClass.isInstance(object);
catch (Throwable t)
throw new HibernateException("could not get handle to entity as interface : " + t);
我知道实例将在应用程序的所有线程之间共享,但它们被视为只读,因此不应修改。
这种方法对吗?
谢谢
【问题讨论】:
【参考方案1】:您也可以使用LoadEventListener
来始终为同一个实例提供服务。尽管如此,由于实体是不可变的,因此不需要此功能,因此,即使您有多个副本,它仍然是不可变的。
此外,即使你实现了单例模式,它也只会在每个 JVM 中强制执行,所以我不明白你为什么要实现这个请求。
实体仅被视为每个EntityManager
的单例。
【讨论】:
感谢弗拉德的回答。在 VisualVM 的采样器中,不可变对象的实例总是在我每次加载它们时上升(当然 GC 会清理它们)。我想避免像单例一样为这些实体实现。我将尝试使用 LoadEventListener,再次感谢您以上是关于HIbernate的实体自关联如何写配置文件的主要内容,如果未能解决你的问题,请参考以下文章