对于如何毫无问题地使用JPA2.0@ManyToMany感兴趣的读者,本文将会是一篇不错的选择,我们将详细介绍jpa怎么使用,并为您提供关于@ManyToMany/@OneToManymappingb
对于如何毫无问题地使用JPA 2.0 @ManyToMany感兴趣的读者,本文将会是一篇不错的选择,我们将详细介绍jpa怎么使用,并为您提供关于@ ManyToMany / @ OneToMany mappingby属性用于双向关联、@ManyToMany JPA 2复杂查询、@ManyToMany 关系的 ebean 缓存问题、@OneToMany、@ManyToOne以及@ManyToMany讲解的有用信息。
本文目录一览:- 如何毫无问题地使用JPA 2.0 @ManyToMany(jpa怎么使用)
- @ ManyToMany / @ OneToMany mappingby属性用于双向关联
- @ManyToMany JPA 2复杂查询
- @ManyToMany 关系的 ebean 缓存问题
- @OneToMany、@ManyToOne以及@ManyToMany讲解
如何毫无问题地使用JPA 2.0 @ManyToMany(jpa怎么使用)
我正在使用JPA 2.0
并且Spring
正在开发中。我的实体类包含两个@ManyToMany
关系。
@Entity("payment") public class PaymentData implements Serializable{ private Long pk; private Collection<PaymentItemData> paymentItem; /** * minorPaymentItem * */ private Collection<MinorPayItemData> minorPaymentItem; @ManyToMany(fetch=FetchType.EAGER) @JoinTable(name = "payitem_m_assig", joinColumns = @JoinColumn(name = "pay_item_id", nullable = false), inverseJoinColumns = @JoinColumn(name = "minor_pay_item_id", nullable = false)) public Collection<MinorPayItemData> getMinorPaymentItem() { return minorPaymentItem; } /** * @param minorPaymentItem the minorPaymentItem to set */ public void setMinorPaymentItem(final Collection<MinorPayItemData> value) { this.minorPaymentItem = value; } @ManyToMany(fetch=FetchType.EAGER) @JoinTable(name = "payitem_assigned", joinColumns = @JoinColumn(name = "pay_item_id", nullable = false), inverseJoinColumns = @JoinColumn(name = "pay_item_id", nullable = false)) public Collection<PaymentItemData> getPaymentItem() { return paymentItem; } /** * Set the property paymentItem * * @param value -paymentItem * */ public void setPaymentItem(final Collection<PaymentItemData> value) { this.paymentItem = value; }}
当我运行查询以从数据库中的付款表中检索记录时,例如
Query q = manager.createQuery("select a from PaymentData a");q.getResultList();
如果我允许fetch=FetchType.EAGER
的@ManyToMany
,我得到以下错误
Caused by: org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags at org.hibernate.loader.BasicLoader.postInstantiate(BasicLoader.java:94) at org.hibernate.loader.entity.EntityLoader.<init>(EntityLoader.java:119) at org.hibernate.loader.entity.EntityLoader.<init>(EntityLoader.java:71) at org.hibernate.loader.entity.EntityLoader.<init>(EntityLoader.java:54) at org.hibernate.loader.entity.BatchingEntityLoader.createBatchingEntityLoader(BatchingEntityLoader.java:133) at org.hibernate.persister.entity.AbstractEntityPersister.createEntityLoader(AbstractEntityPersister.java:1914) at org.hibernate.persister.entity.AbstractEntityPersister.createEntityLoader(AbstractEntityPersister.java:1937) at org.hibernate.persister.entity.AbstractEntityPersister.createLoaders(AbstractEntityPersister.java:3205) at org.hibernate.persister.entity.AbstractEntityPersister.postInstantiate(AbstractEntityPersister.java:3191) at org.hibernate.persister.entity.SingleTableEntityPersister.postInstantiate(SingleTableEntityPersister.java:728) at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:348) at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1845) at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:906) ... 39 more
但是如果我将fetch=FetchType.EAGER
其删除并保留为@ManyToMany
,我将有例外
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.data.PaymentData.paymentItem, no session or session was closed at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:383) at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:375) at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:368) at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:111) at org.hibernate.collection.PersistentBag.toString(PersistentBag.java:506) at java.lang.String.valueOf(String.java:2826) at java.lang.StringBuilder.append(StringBuilder.java:115) at com.niu.util.Util.toString(Util.java:131) at com.niu.util.data.BaseData.toString(BaseData.java:107) at java.lang.String.valueOf(String.java:2826) at java.lang.StringBuilder.append(StringBuilder.java:115) at java.util.AbstractCollection.toString(AbstractCollection.java:422) at java.lang.String.valueOf(String.java:2826) at java.io.PrintStream.println(PrintStream.java:771) at org.apache.tomcat.util.log.SystemLogHandler.println(SystemLogHandler.java:269) at sun.reflect.GeneratedMethodAccessor1861.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at com.opensymphony.xwork2.DefaultActionInvocation.invokeAction(DefaultActionInvocation.java:452) at com.opensymphony.xwork2.DefaultActionInvocation.invokeActionOnly(DefaultActionInvocation.java:291) at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:254) at com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor.doIntercept(DefaultWorkflowInterceptor.java:176) at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98) at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248) at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248) at com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor.intercept(ConversionErrorInterceptor.java:133) at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248) at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:207) at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98) at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248) at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:207) at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98) at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248) at com.opensymphony.xwork2.interceptor.StaticParametersInterceptor.intercept(StaticParametersInterceptor.java:190) at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248) at org.apache.struts2.interceptor.MultiselectInterceptor.intercept(MultiselectInterceptor.java:75) at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248) at org.apache.struts2.interceptor.CheckboxInterceptor.intercept(CheckboxInterceptor.java:94) at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248) at com.niu.web.common.interceptor.ApplicationModelDrivenInterceptor.intercept(ApplicationModelDrivenInterceptor.java:31) at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248) at com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor.intercept(ScopedModelDrivenInterceptor.java:141) at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248) at org.apache.struts2.interceptor.ProfilingActivationInterceptor.intercept(ProfilingActivationInterceptor.java:104) at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248) at org.apache.struts2.interceptor.debugging.DebuggingInterceptor.intercept(DebuggingInterceptor.java:270) at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248) at com.opensymphony.xwork2.interceptor.ChainingInterceptor.intercept(ChainingInterceptor.java:145) at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248) at com.opensymphony.xwork2.interceptor.PrepareInterceptor.doIntercept(PrepareInterceptor.java:171) at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98) at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248) at com.opensymphony.xwork2.interceptor.I18nInterceptor.intercept(I18nInterceptor.java:176) at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248) at org.apache.struts2.interceptor.ServletConfigInterceptor.intercept(ServletConfigInterceptor.java:164) at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248) at com.opensymphony.xwork2.interceptor.AliasInterceptor.intercept(AliasInterceptor.java:190) at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248) at com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.intercept(ExceptionMappingInterceptor.java:187) at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248) at org.apache.struts2.impl.StrutsActionProxy.execute(StrutsActionProxy.java:52) at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:498) at org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:77) at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:91) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:164) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:462) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100) at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:563) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:399) at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:317) at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:204) at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:311) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) at java.lang.Thread.run(Thread.java:662)
我究竟做错了什么
答案1
小编典典为了避免使用MultipleBagFetchException
,而不是使用FetchType.EAGER
,请@LazyCollection(LazyCollectionOption.FALSE)
在本示例中尝试使用:
@ManyToMany@LazyCollection(LazyCollectionOption.FALSE)@JoinTable(name = "payitem_m_assig", joinColumns = @JoinColumn(name = "pay_item_id", nullable = e), inverseJoinColumns = @JoinColumn(name = "minor_pay_item_id", nullable = false))public Collection<MinorPayItemData> getMinorPaymentItem(){ return minorPaymentItem;}
这是对docs的简短描述:
@LazyCollection:定义@ManyToMany和@OneToMany关联上的惰性选项。LazyCollectionOption可以为TRUE(集合是惰性的,并且在访问其状态时将被加载),EXTRA(集合是惰性的,并且所有操作都将尝试避免集合的装载,这对于在装入所有元素时对大型集合特别有用)不必要)和FALSE(关联不懒惰)
@Fetch:定义用于加载关联的获取策略。FetchMode可以是SELECT(需要加载关联时触发选择),SUBSELECT(仅适用于集合,使用子选择策略-请参考Hibernate参考文档以获取更多信息)或JOIN(使用SQL JOIN加载)加载所有者实体时关联)。JOIN会覆盖任何惰性属性(通过JOIN策略加载的关联不能是惰性的)。
希望对您有所帮助
@ ManyToMany / @ OneToMany mappingby属性用于双向关联
我正在为我的实习工作开发JPA兼容套件…该套件的一部分涉及测试极端情况的正确实现。
@ManyToMany
具有mapedBy属性。JPA指出:
字符串mappingBy-拥有关系的字段或属性。除非关系是单向的,否则为必需。
没有给出默认值-默认列为空。
给定双向@ManyToMany
-此示例来自JPA 2.0 JSR-317规范本身!
顾客
@ManyToMany
@JoinTable(name="CUST_PHONES")
public Set<PhoneNumber> getPhones() { return phones; }
电话号码
@ManyToMany(mappedBy="phones")
public Set<Customer> getCustomers() { return customers; }
尚未在@ManyToMany
of的中定义mapledBy属性Customer
!我不知道的双向映射有默认值吗?
我查看了类似的情况,发现: @OneToOne
-mappingBy是可选的,没有默认值
@OneToMany
-完全相同@ManyToMany
(mappedBy对于双向是可选的,没有默认值)
简而言之,我的问题是:
对于@ManyToMany
和@OneToMany
,应在关系的拥有方(Customer
例如)中将其放置在mappedBy属性中?
@ManyToMany JPA 2复杂查询
我有以下ManyToMany映射。
@Entitypublic class Class1 {@Id@GeneratedValue(strategy = GenerationType.AUTO)private Long id;@ManyToMany(fetch = FetchType.LAZY)@JoinTable(name = "class1_class2", joinColumns = @JoinColumn(name = "class1Id"), inverseJoinColumns = @JoinColumn(name = "class2Id"))private List<Class2> class2;}@Entitypublic class Class2 {@Id@GeneratedValue(strategy = GenerationType.AUTO)private Long id;}
我想检索与Classe2实体有关系的所有Class1实体,其中class2Id = 1和class2Id = 2和class2Id = 3。{1,2,3}
或者,要过滤在其class2列表上具有的Classe1实体,请使用具有以下值的Class2实体:class2Id = 1和class2Id =
2和class2Id = 3
例如:
如果在联接表上,我有以下值。
class1Id class2Id 1 1 1 2 1 3 1 4 6 1 6 2 6 3 4 1 5 2
对于该示例,结果将是Class1Id为1和6的Class1。因为Class1Id =
1的Class1实体的classe2Id为1,2,3,4,Class1Id = 2的Class1实体的classe2Id为1。 ,2,3
是否可以通过JPA2(谓词)获得正确的实体?
有没有更好的映射来处理这种情况?
目前,我提出了以下SQL查询:
select v1.class1Id from class1_class2 v1inner join class1_class2 v2 on v1.class1Id=v2.class1Idinner join class1_class2 v3 on v2.class1Id=v3.class1Idwhere v1.classe2Id=1 and v2.classe2Id=2 and v3.classe2Id=3;
答案1
小编典典这是可以提供帮助的查询:
select c1 from Class1 c1 join c1.class2 c2 where c2.id in (1,2,3)group by c1having count(c1)=3 ;
@ManyToMany 关系的 ebean 缓存问题
注解@Cacheable 仅适用于允许拦截器的公共公开方法。但是如果需要,您可以获得“CacheManager”服务并在您的代码中使用它来内部处理私有方法中的缓存。但只是为了解决一些“特殊”问题,通常的方法是对公共方法进行注释。
此外,如果您只使用 starter,那么您只使用了 Spring 的基本和糟糕的实现,一个简单的内存缓存。
考虑您的应用程序将如何工作(单个应用程序、分布式应用程序、缓存的短/长数据量……)以及添加任何支持的缓存管理器(如 ehCache、Hazelcast、Caffeine)的依赖项的内存消耗,...满足您的要求并提高您的缓存性能。
@OneToMany、@ManyToOne以及@ManyToMany讲解
一、一对多(@OneToMany)
1、单向一对多模型
假设通过一个客户实体可以获得多个地址信息。
对于一对多的实体关系而言,表结构有两种设计策略,分别是外键关联和表关联。
(1) 映射策略---外键关联
在数据库中表customer和表结构address定义,如下:
create table customer (
id int(20) not null auto_increment,
name varchar(100),
primary key(id)
)
create table address (
id int(20) not null auto_increment,
province varchar(50),
city varchar(50),
postcode varchar(50),
detail varchar(50),
customer_id int(20),
primary key (id)
)
注意此时外键定义在多的一方,也就是address表中。
此时,表customer映射为实体CustomerEO,代码如下:
@Entity
@Table (name="customer")
public class CustomerEO implements java.io.Serializable {
@OneToMany(cascade={ CascadeType.ALL })
@JoinColumn(name="customer_id")
private Collection<AddressEO> addresses = new ArrayList<AddressEO>();
...
}
注释@OneToMany的定义代码如下:
@Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface OneToMany {
Class targetEntity() default void.class;
CascadeType[] cascade() default {};
FetchType fetch() default LAZY;
String mappedBy() default "";
}
使用时要注意一下几点问题:
a、targetEntity属性表示默认关联的实体类型。如果集合类中指定了具体类型了,不需要使用targetEntity.否则要指定targetEntity=AddressEO.class。
b、mappedBy属性用于标记当实体之间是双向时使用。
(2) 映射策略---表关联
在上面address表中去掉customer_id字段,在增加一个表ref_customer_address,如下:
--客户地址关系表
create table ref_customer_address (
customer_id int(20) not null,
address_id int(20) not null unique
)
此时表customer映射为CustomerEO实体,代码如下:
@Entity
@Table(name = "customer")
public class CustomerEO implements java.io.Serializable {
...
@OneToMany(cascade = { CascadeType.ALL })
@JoinTable(name="ref_customer_address",
joinColumns={ @JoinColumn(name="customer_id",referencedColumnName="id")},
inverseJoinColumns={@JoinColumn(name="address_id",referencedColumnName="id")})
private Collection<AddressEO> addresses = new ArrayList<AddressEO>();
...
}
表关联@JoinTable,定义如下:
@Target({METHOD,FIELD})
public @interface JoinTable {
String name() default "";
String catalog() default "";
String schema() default "";
JoinColumn[] joinColumns() default {};
JoinColumn[] inverseJoinColumns() default {};
UniqueConstraint[] uniqueConstraints default {};
}
其中:
a、该标记和@Table相似,用于标注用于关联的表。
b、name属性为连接两张表的表名。默认的表名为:“表名1”+“-”+“表名2”,上面例子默认的表名为customer_address。
c、joinColumns属性表示,在保存关系中的表中,所保存关联的外键字段。
d、inverseJoinColumns属性与joinColumns属性类似,不过它保存的是保存关系的另一个外键字段。
(3) 默认关联
在数据库底层为两张表添加约束,如下:
create table customer_address (
customer_id int(20) not null,
address_id int(20) not null unique
)
alter table customer_address add constraint fk_ref_customer foreign key (customer_id) references customer (id);
alter table customer_address add constraint fk_ref_address foreign key (address_id) references address (id);
这样,在CustomerEO中只需要在标注@OneToMany即可!
二、多对一@ManyToOne
1、单向多对一模型。
(1) 外键关联
配置AddressEO实体如下:
@Entity
@Table(name="address")
public class AddressEO implements java.io.Serializable {
@ManyToOne(cascade = { CascadeType.ALL })
@JoinColumn(name="customer_id")
private CustomerEO customer;
// ...
}
@ManyToOne定义如下:
@Target({METHOD,FIELD}) @Retention(RUNTIME)
public @interface ManyToOne {
Class targetEntity() default void.class;
CascadeType[] cascade() default {};
FetchType fatch() default EAGER;
boolean optional() default true;
}
(2) 默认关联
数据库脚本定义的相关字段的约束,创建外键后,直接使用@ManyToOne
三、高级一对多和多对一映射
即双向关联模型,确定了双向关联后,多的一方AddressEO不变使用@ManyToOne,而CustomerEO实体修改为:
@Entity
@Table(name="customer")
public class CustomerEO {
@OneToMany(mappedBy="customer")
private Collection<AddressEO> addresses = new ArrayList<AddressEO>();
// ...
}
其中,@OneToMany标记中的mappedBy属性的值为AddressEO实体中所引用的CustomerEO实体的属性名。
四、多对多(@ManyToMany)
和一对多类型,不在赘述。@ManyToMany标记的定义如下:
@Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface ManyToMany {
Class targetEntity() default void.class;
CascadeType[] cascade() default {};
FetchType fecth() default LAZY;
String mappedBy() default "";
}
五、最后,谈谈关于集合类的选择
在映射关系中可以使用的集合类有Collection、Set、List和Map,下面看下如何选择。
1、定义时使用接口,初始化使用具体的类。
如Collection可以初始化为ArrayList或HashSet;
Set可以初始化为HashSet;
List可以初始化为ArrayList;
Map可以初始化为HashMap.
2、集合类的选择
Collection类是Set和List的父类,在未确定使用Set或List时可使用;
Set集合中对象不能重复,并且是无序的;
List集合中的对象可以有重复,并且可以有排序;
Map集合是带有key和value值的集合。
今天的关于如何毫无问题地使用JPA 2.0 @ManyToMany和jpa怎么使用的分享已经结束,谢谢您的关注,如果想了解更多关于@ ManyToMany / @ OneToMany mappingby属性用于双向关联、@ManyToMany JPA 2复杂查询、@ManyToMany 关系的 ebean 缓存问题、@OneToMany、@ManyToOne以及@ManyToMany讲解的相关知识,请在本站进行查询。
本文标签: