{"id":29690795,"url":"https://github.com/daejoon/proxytest","last_synced_at":"2025-07-23T06:38:01.866Z","repository":{"id":210870122,"uuid":"726695647","full_name":"daejoon/ProxyTest","owner":"daejoon","description":"@ManyToOne non-primarykey 확인 테스트 코드 ","archived":false,"fork":false,"pushed_at":"2024-11-29T15:35:27.000Z","size":59,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-11-29T16:34:31.378Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/daejoon.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-12-03T05:15:43.000Z","updated_at":"2024-11-29T15:35:31.000Z","dependencies_parsed_at":"2024-09-08T07:38:13.346Z","dependency_job_id":"7d974c4f-fd2d-4906-bea3-f63d8a89c5c1","html_url":"https://github.com/daejoon/ProxyTest","commit_stats":null,"previous_names":["daejoon/proxytest"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/daejoon/ProxyTest","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/daejoon%2FProxyTest","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/daejoon%2FProxyTest/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/daejoon%2FProxyTest/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/daejoon%2FProxyTest/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/daejoon","download_url":"https://codeload.github.com/daejoon/ProxyTest/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/daejoon%2FProxyTest/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266631715,"owners_count":23959422,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-23T02:00:09.312Z","response_time":66,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-07-23T06:37:58.584Z","updated_at":"2025-07-23T06:38:01.852Z","avatar_url":"https://github.com/daejoon.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ProxyTest\n\nJPA Entity 저장시 Proxy 상태의 연관관계 Entity의 null 반환 오류\n\n## 증상\n\nCity를 저장할때 연관관계에 있는 Code의 엔티티를 참조 시키면 저장시 실제 테이블에 필드값이 자연스럽게 저장된다. 하지만 지금 경우에는 저장시 null 이 저장되면서 예외가 발생\n\n## 원인\n\n* JPA는 엔티티의 Lazy 설정이 되어 있거나 1차 캐쉬(PersistenceContext)에 저장되어 있는 데이터를 다시 조회 하면 HibernateProxy 객체를 리턴하고 실제 DB에서 가져오지 않는다.\n\n* 저장시에 연관관계 Primary 조인 관계라면 실제 참조 엔티트 값을 조회한다.\n\n    ```java\n    /** SimpleForeignKeyDescriptor.java **/\n    ...\n    if ( refersToPrimaryKey ) {\n      final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( targetObject );\n      if ( lazyInitializer != null ) {\n          return lazyInitializer.getIdentifier();\n      }\n    }\n    ...\n    ```\n* 저장시 연관관계 Primary 조인이 아니라면 값을 그대로 조회한다.\n\n    ```java\n    /** ToOneAttributeMapping.java */\n    ...\n    private static Object extractAttributePathValue(Object domainValue, EntityMappingType entityType, String attributePath) {\n        if ( ! attributePath.contains( \".\" ) ) {\n            return entityType.findAttributeMapping( attributePath ).getValue( domainValue );\n        }\n        ...\n    }\n    ...\n    ```\n\n## 조치방법\n\n* 방법1\n    * 연관관계 Primary 조인이 아니라면 Hibernate.unproxy 메소드를 사용해서 실제 참조 값을 리턴하게 변경해야 한다.\n\n* 방법2\n    * 연관관계 선언할때 참조 엔티의의 PrimaryKey와 조인이 되게 설계하고 그렇지 않으면 Join을 하지 말고 실제 키 값만 필드에 직접 가지고 있게 설계한다.\n\n## 결론\n\n* 방법 2 추천\n    * 개발자가 개발하면서 연관 관계를 정확히 알아야 하며 휴먼에러가 발생하기 쉽다. 차라리 그럴바에는 실제 필드 값을 가지고 있게 수정하는게 관리상 용이하며 unrpoxy를 해야 하는 코드도 없어서 흐름도\n      자연스럽다.\n\n## 추가 사항\n\n* Hibernate 6.5.3 에서 해결되어서 비식별 관계일때도 저장된다.\n  * [Hibernate fails to persist an entity when a natural id association is a proxy](https://hibernate.atlassian.net/browse/HHH-18147) ","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdaejoon%2Fproxytest","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdaejoon%2Fproxytest","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdaejoon%2Fproxytest/lists"}