일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- IntelliJ
- wildfly
- nginx
- react
- Spring
- database
- Kubernetes
- log4j2
- useEffect
- docker
- Windows
- VSCode
- MySQL
- mybatis
- springboot
- gson
- Java
- tibero
- BPMN
- JavaScript
- LOG4J
- Git
- gradle
- intellijIDEA
- dbeaver
- nodejs
- JPA
- NCP
- jetbrains
- kubectl
- Today
- Total
목록JPA (9)
두 손끝의 창조자
EntityManagerFactory는 DataSource와 연관되어 있다. 스프링 환경에서 사용하는 경우 EntityManagerFactory는 빈으로 등록해서 사용하는게 효율적이라 등록 후 사용중이라면 ApplicationContext에서 Factory를 가져올 수 있다. @Transactional 로 트랜잭션 관리를 한다면 @PersistentContext 애노테이션으로 쉽게 현재 스레드의 EntityManager를 가져올 수 있다. @PersistentContext EntityMager em; 그러나 트랜젝션을 직접 관리한다면 아래 방법으로 가져올 수 있다. EntityManager em = EntityManagerFactoryUtils.getTransactionalEntityManager(emf);
Spring data에서 Persistable 인터페이스는 ID를 가져오는 getId, 새로운 오브젝트여서 저장해야 하는지 merge 해야하는지 판단 할 수 있는 isNew 메소드가 있다. 엔티티에서 @Id 애노테이션으로 지정하면 엔티티를 만들 때 이미 ID가 null이 아니기 떄문에 새로운 객체가 아니라고 판단해서 select 한뒤 다시 머지를 하는 비효율적인 행동을 한다. 그래서 ID를 개발자가 직접 넣어줘야하는 엔터티는 Persistable 인터페이스를 구현해서 어떤 상황이 새로운 객체인지 알게 해 주어야한다.
JPA에서 Entity를 가져와서 필드 하나를 업데이트하고 난뒤 커밋할 때 실제로 수행되는 쿼리를 확인해보면 전체 필드에 대해서 다시 업데이트되는 것을 볼 수 있다. 성능상 효율적일 수는 모르겠으나 유지보수할 때는 쿼리가 실행된 타이밍에 어떤 필드가 업데이트 됐는지 알 수가 없어 고통이 따를 수 있다. @Entity 과 함께 @DynamicUpdate 애노테이션은 이 부분을 해결한다. 음~ 깔끔해진 쿼리.
gradle 프로젝트면 resources 디렉토리에 import.sql 파일을 넣으면 초기화 할 때 자동으로 호출된다. 그런데 무슨 데이터소스 기준으로 하는지 프로파일 별로 할 수는 없는지...
구조 Car - Body < Part 구조가 있을 때, 즉 Car 는Body 와 1:1,Body 와 Part 는 1:n 관계가 있다. JPA에서는 모두 양방향 참조로 Car에서 Part 까지 접근 가능하고, 연관관계 주인은 Car -Body 에서는Body 가,Body < Part 에서는Part 가 가지고 있다. 엔티티 저장을 편리하게 하기위해서 모든 OneToXXX 는 cascade 모드를 ALL 로 하였다. 각 엔티티는 Audit 처리를 위해 Audit MappedSuperclass를 상속하고 이 클래스는 int 타입의 version 필드를 가지고 있다. 이 Audit 엔티티에 @EntityListeners 를 등록해서 Create, Update 시 버전을 올릴려고 AuditListener 을 구현하고..
persistence.xml 없이 자바로 속성 설정해서 사용하려면 @Bean public EntityManagerFactory entityManagerFactoryForMysql(DataSource dataSource) { final Properties properties = new Properties(); properties.put( "hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect" ); // MySql5x 쓴다면 properties.put( "hibernate.user_sql_comments", "true" ); properties.put( "hibernate.format_sql", "true" ); properties.put( "hibernat..
persistence.xml 는 필요없다. entityManagerFactoryBean.afterPropertiesSet(); 는 가장 마지막에 호출해줘야 한다. LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean(); entityManagerFactoryBean.setDataSource(dataSource); entityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter()); Map objectObjectHashMap = new HashMap(); objectObjectHashMap.put..
어떤 클래스가 JpaRepository를 참조하기 위해서 @Autowired나 생성자, 속성으로 할 수 있다. Namespace로 빈을 선언할 때 생성자로 참조하기 위해서 JpaRepository를 넣어주면 참조하기 못하는 현상을 발견했다. 이걸 그냥 Autowired로 바꾸면 잘 되는데.... 아무래도 생성자 방식으로 했을 때 JpaRepository가 아직 Bean으로 만들어지지 않은 상황에서 생성자가 실행되어서 그렇지 싶다. 이걸 어떻게 극복을 하는지 모르겠다. 해결 Autowired로 인해서 잘 초기화된 것이 아니었다. 그냥 null로 바인드 되어서 잘 된 것처럼 보일 뿐... 이것만 봐도 그냥 Autowired를 쓰는 것보다는 생성자로 명시적으로 받는 것이 오류를 미리 발견할 수 있다. 참조하지..
hibernate 프로퍼티 설정 hibernate.show_sql = false hibernate.format_sql = true hibernate.user_sql_comments = true log4j2 설정 스프링부트에서는 spring.jpa.properties.hibernate.format_sql=true spring.jpa.properties.hibernate.show_sql=false logging.level.org.hibernate.SQL=debug logging.level.org.hibernate.type=trace