欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

JPA单向多对一实体映射

程序员文章站 2022-04-24 11:33:54
...

1、建表, 在多的一方创建外键关联

# 产品 - 多的一方
drop table if exists product;
create table product(
    id varchar(64) primary key
    ,name varchar(20)
    ,product_type_id varchar(64)
    # 添加外键映射
    ,constraint fk_product_id foreign key (product_type_id) references product_type(id)
) engine InnoDB charset 'utf8';


# 产品类型名称 - one的一方
create table product_type(
    id varchar(64) primary key
    ,name varchar(20)
) engine InnoDB charset 'utf8';


2、做实体映射

many一方的实体映射代码如下:

package com.jiang.jpa.otm.entity;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

package com.jiang.jpa.otm.entity;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

/**
 *
 * many的一方
 *
 * @author Luosj
 *
 * @date 2020/2/16 5:09 PM
 */
@Entity
@Table(name = "product")
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class Product{

    @Id
    private String id;

    private String name;

    @ManyToOne
    // @Column(name="product_type_id") // 多的一方不能使用@Column来配置外键列名
    @JoinColumn(name = "product_type_id")
    private ProductType productType;

    @Override
    public String toString() {

        return "{id:"+this.getId()+",name:"+this.getName()+"}";
    }
}

/**
 * @author Luosj
 * @desc: from spring-data-jpa-demo
 */


One一方的实体如下:

package com.jiang.jpa.otm.entity;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

/**
 *
 * one的一方
 *
 * @author Luosj
 *
 * @date 2020/2/16 5:12 PM
 */
@Entity
@Table(name = "product_type")
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class ProductType{

    @Id
    private String id;

    private String name;

}

实体映射 - DAO接口


package com.jiang.jpa.otm.dao;

import com.jiang.jpa.otm.entity.Product;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

/**
 * @author Luosj
 * @date 2020/2/16 5:28 PM
 */
@Repository
public interface ProductDao extends JpaRepository<Product, String> {

}


package com.jiang.jpa.otm.dao;

import com.jiang.jpa.otm.entity.ProductType;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

/**
 * @author Luosj
 * @date 2020/2/16 5:29 PM
 */
@Repository
public interface ProductTypeDao extends JpaRepository<ProductType, String> {

}


3、数据初始化操作

数据初始化过程需要保证One的一方存在数据, 才能实现多的一方数据存储
这里展示的是正确的代码

  @Autowired
    private ProductDao productDao;
    @Autowired
    private ProductTypeDao productTypeDao;

    /**
     *
     *  数据初始化测试 - 先保证一的一方存在数据, 才能存储多的一方
     *
     */
    @Test
    public void init(){
        // one
        ProductType type = new ProductType();
        type.setId(String.valueOf(System.currentTimeMillis()));
        type.setName("水果3");
         // many
        Product p1 = new Product(UUID.randomUUID().toString(), "苹果", type);
        Product p2 = new Product(UUID.randomUUID().toString(), "梨子", type);
        Product p3 = new Product(UUID.randomUUID().toString(), "香蕉", type);
        // persistence
        productTypeDao.save(type);
        productDao.save(p1);
        productDao.save(p2);
        productDao.save(p3);
    }

错误的代码

    @Test
    public void errorInit(){
        // one
        ProductType type = new ProductType();
        type.setId(String.valueOf(System.currentTimeMillis()));
        type.setName("水果3");
        // many
        Product p1 = new Product(UUID.randomUUID().toString(), "苹果", type);
        Product p2 = new Product(UUID.randomUUID().toString(), "梨子", type);
        Product p3 = new Product(UUID.randomUUID().toString(), "香蕉", type);
        // persistence
        productDao.save(p1);
        productDao.save(p2);
        productDao.save(p3);
        productTypeDao.save(type);
    }

执行这段代码会抛出的异常:

Caused by: javax.persistence.EntityNotFoundException: Unable to find com.jiang.jpa.otm.entity.ProductType with id 1581848679583
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$JpaEntityNotFoundDelegate.handleEntityNotFound(EntityManagerFactoryBuilderImpl.java:163)
	at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:216)
	at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:332)
	at org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(DefaultLoadEventListener.java:108)
	at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:74)
	at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:118)
	at org.hibernate.internal.SessionImpl.fireLoadNoChecks(SessionImpl.java:1168)
	at org.hibernate.internal.SessionImpl.internalLoad(SessionImpl.java:1033)
	at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:687)
	at org.hibernate.type.EntityType.resolve(EntityType.java:464)
	at org.hibernate.type.ManyToOneType.resolve(ManyToOneType.java:240)
	at org.hibernate.type.EntityType.resolve(EntityType.java:457)
	at org.hibernate.type.EntityType.replace(EntityType.java:358)
	at org.hibernate.type.AbstractType.replace(AbstractType.java:164)
	at org.hibernate.type.TypeHelper.replace(TypeHelper.java:204)
	at org.hibernate.event.internal.DefaultMergeEventListener.copyValues(DefaultMergeEventListener.java:488)
	at org.hibernate.event.internal.DefaultMergeEventListener.entityIsTransient(DefaultMergeEventListener.java:241)
	at org.hibernate.event.internal.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:318)
	at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:172)
	at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:70)
	at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:108)
	at org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:775)
	at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:762)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:314)
	at com.sun.proxy.$Proxy70.merge(Unknown Source)
	at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:557)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:371)
	at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:204)
	at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:657)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:621)
	at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:605)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:80)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:366)
	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:99)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139)
	... 71 more