GVKun编程网logo

如何毫无问题地使用JPA 2.0 @ManyToMany(jpa怎么使用)

4

对于如何毫无问题地使用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怎么使用)

如何毫无问题地使用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属性用于双向关联

@ 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; }

尚未在@ManyToManyof的中定义mapledBy属性Customer!我不知道的双向映射有默认值吗?

我查看了类似的情况,发现: @OneToOne-mappingBy是可选的,没有默认值
@OneToMany-完全相同@ManyToMany(mappedBy对于双向是可选的,没有默认值)

简而言之,我的问题是:
对于@ManyToMany@OneToMany,应在关系的拥有方(Customer例如)中将其放置在mappedBy属性中?

@ManyToMany JPA 2复杂查询

@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 缓存问题

@ManyToMany 关系的 ebean 缓存问题

注解@Cacheable 仅适用于允许拦截器的公共公开方法。但是如果需要,您可以获得“CacheManager”服务并在您的代码中使用它来内部处理私有方法中的缓存。但只是为了解决一些“特殊”问题,通常的方法是对公共方法进行注释。

此外,如果您只使用 starter,那么您只使用了 Spring 的基本和糟糕的实现,一个简单的内存缓存。

考虑您的应用程序将如何工作(单个应用程序、分布式应用程序、缓存的短/长数据量……)以及添加任何支持的缓存管理器(如 ehCache、Hazelcast、Caffeine)的依赖项的内存消耗,...满足您的要求并提高您的缓存性能。

@OneToMany、@ManyToOne以及@ManyToMany讲解

@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 @ManyToManyjpa怎么使用的分享已经结束,谢谢您的关注,如果想了解更多关于@ ManyToMany / @ OneToMany mappingby属性用于双向关联、@ManyToMany JPA 2复杂查询、@ManyToMany 关系的 ebean 缓存问题、@OneToMany、@ManyToOne以及@ManyToMany讲解的相关知识,请在本站进行查询。

本文标签: