- 원인: H2에 연결되지 않아서 오류가 났다. 그런데 H2에 연결되지 않은 이유가 Java가 설치되어 있지 않았기 때문이었다. JDK가 설치되어 있어야 H2도 돌아간다.
java
열기
C:\Users\Ran\.jdks\corretto-1.8.0_342\bin\java.exe -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:53579,suspend=y,server=n -javaagent:C:\Users\Ran\AppData\Local\JetBrains\IntelliJIdea2022.2\captureAgent\debugger-agent.jar -Dfile.encoding=UTF-8 -classpath "C:\Users\Ran\.jdks\corretto-1.8.0_342\jre\lib\charsets.jar;C:\Users\Ran\.jdks\corretto-1.8.0_342\jre\lib\ext\access-bridge-64.jar;C:\Users\Ran\.jdks\corretto-1.8.0_342\jre\lib\ext\cldrdata.jar;C:\Users\Ran\.jdks\corretto-1.8.0_342\jre\lib\ext\dnsns.jar;C:\Users\Ran\.jdks\corretto-1.8.0_342\jre\lib\ext\jaccess.jar;C:\Users\Ran\.jdks\corretto-1.8.0_342\jre\lib\ext\jfxrt.jar;C:\Users\Ran\.jdks\corretto-1.8.0_342\jre\lib\ext\localedata.jar;C:\Users\Ran\.jdks\corretto-1.8.0_342\jre\lib\ext\nashorn.jar;C:\Users\Ran\.jdks\corretto-1.8.0_342\jre\lib\ext\sunec.jar;C:\Users\Ran\.jdks\corretto-1.8.0_342\jre\lib\ext\sunjce_provider.jar;C:\Users\Ran\.jdks\corretto-1.8.0_342\jre\lib\ext\sunmscapi.jar;C:\Users\Ran\.jdks\corretto-1.8.0_342\jre\lib\ext\sunpkcs11.jar;C:\Users\Ran\.jdks\corretto-1.8.0_342\jre\lib\ext\zipfs.jar;C:\Users\Ran\.jdks\corretto-1.8.0_342\jre\lib\jce.jar;C:\Users\Ran\.jdks\corretto-1.8.0_342\jre\lib\jfr.jar;C:\Users\Ran\.jdks\corretto-1.8.0_342\jre\lib\jfxswt.jar;C:\Users\Ran\.jdks\corretto-1.8.0_342\jre\lib\jsse.jar;C:\Users\Ran\.jdks\corretto-1.8.0_342\jre\lib\management-agent.jar;C:\Users\Ran\.jdks\corretto-1.8.0_342\jre\lib\resources.jar;C:\Users\Ran\.jdks\corretto-1.8.0_342\jre\lib\rt.jar;C:\Users\Ran\Desktop\R\inflearn\JPA프로그래밍_기본편\새 폴더\jpa-basic\target\classes;C:\Users\Ran\.m2\repository\org\hibernate\hibernate-entitymanager\5.3.10.Final\hibernate-entitymanager-5.3.10.Final.jar;C:\Users\Ran\.m2\repository\org\jboss\logging\jboss-logging\3.3.2.Final\jboss-logging-3.3.2.Final.jar;C:\Users\Ran\.m2\repository\org\hibernate\hibernate-core\5.3.10.Final\hibernate-core-5.3.10.Final.jar;C:\Users\Ran\.m2\repository\org\javassist\javassist\3.23.2-GA\javassist-3.23.2-GA.jar;C:\Users\Ran\.m2\repository\antlr\antlr\2.7.7\antlr-2.7.7.jar;C:\Users\Ran\.m2\repository\org\jboss\jandex\2.0.5.Final\jandex-2.0.5.Final.jar;C:\Users\Ran\.m2\repository\com\fasterxml\classmate\1.3.4\classmate-1.3.4.jar;C:\Users\Ran\.m2\repository\javax\activation\javax.activation-api\1.2.0\javax.activation-api-1.2.0.jar;C:\Users\Ran\.m2\repository\org\dom4j\dom4j\2.1.1\dom4j-2.1.1.jar;C:\Users\Ran\.m2\repository\org\hibernate\common\hibernate-commons-annotations\5.0.4.Final\hibernate-commons-annotations-5.0.4.Final.jar;C:\Users\Ran\.m2\repository\javax\persistence\javax.persistence-api\2.2\javax.persistence-api-2.2.jar;C:\Users\Ran\.m2\repository\net\bytebuddy\byte-buddy\1.9.5\byte-buddy-1.9.5.jar;C:\Users\Ran\.m2\repository\org\jboss\spec\javax\transaction\jboss-transaction-api_1.2_spec\1.1.1.Final\jboss-transaction-api_1.2_spec-1.1.1.Final.jar;C:\Users\Ran\.m2\repository\com\h2database\h2\2.1.214\h2-2.1.214.jar;C:\Program Files\JetBrains\IntelliJ IDEA 2022.2.1\lib\idea_rt.jar" hellojpa.JpaMain
대상 VM에 연결되었습니다, 주소: '127.0.0.1:53579', 전송: '소켓'9월 03, 20221:20:05 오후 org.hibernate.jpa.internal.util.LogHelper logPersistenceUnitInformation
INFO: HHH000204: Processing PersistenceUnitInfo [
name: hello
...]
9월 03, 20221:20:05 오후 org.hibernate.Version logVersion
INFO: HHH000412: Hibernate Core {5.3.10.Final}
9월 03, 20221:20:05 오후 org.hibernate.cfg.Environment <clinit>
INFO: HHH000206: hibernate.properties not found
9월 03, 20221:20:05 오후 org.hibernate.annotations.common.reflection.java.JavaReflectionManager <clinit>
INFO: HCANN000001: Hibernate Commons Annotations {5.0.4.Final}
9월 03, 20221:20:05 오후 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
WARN: HHH10001002: Using Hibernate built-in connection pool(not for production use!)
9월 03, 2022 1:20:05 오후 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001005: using driver [org.h2.Driver] at URL [jdbc:h2:tcp://localhost/~/test]
9월 03, 2022 1:20:05 오후 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001001: Connection properties: {user=sa}
9월 03, 20221:20:05 오후 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001003: Autocommit mode: false9월 03, 20221:20:05 오후 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PooledConnections <init>
INFO: HHH000115: Hibernate connection pool size: 20 (min=1)
9월 03, 20221:20:08 오후 org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator initiateService
WARN: HHH000342: Could not obtain connection to query metadata : null9월 03, 20221:20:08 오후 org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.H2Dialect
9월 03, 20221:20:08 오후 org.hibernate.engine.jdbc.env.internal.LobCreatorBuilderImpl makeLobCreatorBuilder
INFO: HHH000422: Disabling contextual LOB creation as connection was null9월 03, 20221:20:08 오후 org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
WARN: SQL Error: 90067, SQLState: 900679월 03, 20221:20:08 오후 org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
ERROR: Connection is broken: "java.net.SocketTimeoutException: connect timed out: localhost" [90067-214]
Exception in thread "main" org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment]
at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:275)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:214)
at org.hibernate.id.factory.internal.DefaultIdentifierGeneratorFactory.injectServices(DefaultIdentifierGeneratorFactory.java:152)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.injectDependencies(AbstractServiceRegistryImpl.java:286)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:243)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:214)
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.<init>(InFlightMetadataCollectorImpl.java:179)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:119)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:904)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:935)
at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:56)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:79)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:54)
at hellojpa.JpaMain.main(JpaMain.java:13)
Caused by: org.hibernate.exception.JDBCConnectionException: Error calling Driver#connect
at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:48)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:113)
at org.hibernate.engine.jdbc.connections.internal.BasicConnectionCreator.convertSqlException(BasicConnectionCreator.java:118)
at org.hibernate.engine.jdbc.connections.internal.DriverConnectionCreator.makeConnection(DriverConnectionCreator.java:41)
at org.hibernate.engine.jdbc.connections.internal.BasicConnectionCreator.createConnection(BasicConnectionCreator.java:58)
at org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PooledConnections.addConnections(DriverManagerConnectionProviderImpl.java:363)
at org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PooledConnections.<init>(DriverManagerConnectionProviderImpl.java:282)
at org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PooledConnections.<init>(DriverManagerConnectionProviderImpl.java:260)
at org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PooledConnections$Builder.build(DriverManagerConnectionProviderImpl.java:401)
at org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl.buildPool(DriverManagerConnectionProviderImpl.java:112)
at org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl.configure(DriverManagerConnectionProviderImpl.java:75)
at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:100)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:246)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:214)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.buildJdbcConnectionAccess(JdbcEnvironmentInitiator.java:145)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:66)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35)
at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:94)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:263)
... 14 more
Caused by: org.h2.jdbc.JdbcSQLNonTransientConnectionException: Connection is broken: "java.net.SocketTimeoutException: connect timed out: localhost" [90067-214]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:678)
at org.h2.message.DbException.getJdbcSQLException(DbException.java:477)
at org.h2.message.DbException.get(DbException.java:212)
at org.h2.engine.SessionRemote.connectServer(SessionRemote.java:437)
at org.h2.engine.SessionRemote.connectEmbeddedOrServer(SessionRemote.java:325)
at org.h2.jdbc.JdbcConnection.<init>(JdbcConnection.java:122)
at org.h2.Driver.connect(Driver.java:59)
at org.hibernate.engine.jdbc.connections.internal.DriverConnectionCreator.makeConnection(DriverConnectionCreator.java:38)
... 29 more
Caused by: java.net.SocketTimeoutException: connect timed out
at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:607)
at org.h2.util.NetUtils.createSocket(NetUtils.java:135)
at org.h2.util.NetUtils.createSocket(NetUtils.java:99)
at org.h2.engine.SessionRemote.initTransfer(SessionRemote.java:130)
at org.h2.engine.SessionRemote.connectServer(SessionRemote.java:433)
... 33 more
대상 VM에서 연결 해제되었습니다. 주소: '127.0.0.1:53579', 전송: '소켓'
종료 코드 1(으)로 완료된 프로세스
cmd창에서 윈도우는 h2.bat를 실행해야 H2가 연결된다. 맥은 H2.sh 실행
Member 클래스를 만든다.
java
열기
package hellojpa;
import javax.persistence.Entity;
import javax.persistence.Id;
@EntitypublicclassMember{
@Idprivate Long id;
private String name;
public Long getId(){
return id;
}
publicvoidsetId(Long id){
this.id = id;
}
public String getName(){
return name;
}
publicvoidsetName(String name){
this.name = name;
}
}
H2 에 들어가서 위 클래스와 필드를 맞춰서 member 테이블을 새로 만든다.
sql
열기
CREATETABLEmember(
id bigintNOTNULL,
name varchar(255),
primary key(id)
);
Main 클래스
EntityManagerFactory를 애플리케이션 로딩 시점에 딱 하나만 만들어야한다.
em.persist()
java
열기
package hellojpa;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
publicclassJpaMain{
publicstaticvoidmain(String[] args){
EntityManagerFactory emf =
Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
Member member = new Member();
member.setId(1L);
member.setName("HELLOa");
em.persist(member);
em.close();
emf.close(); // 팩토리를 나중에 닫는다.
}
}
Note) 실행 결과 - 대상 VM에서 연결 해제되었습니다.
멤버에 매개변수를 넣어줬는데도 자동으로 연결이 해제된다는 메시지가 나온다.
왜?
JPA는 "트랜잭션"이라는 단위가 중요하다. 데이터를 변경하는 단위는 반드시 트랜잭션 안에서 작업해야한다.
따라서, EntityTransaction을 꼭 써줘야한다.
EntityTransaction 추가한다.
commit() => 바꾼 내용을 반영하고, close() => 자원을 다 쓰고 나면 데이터베이스 커넥션을 반환해야한다.
java
열기
package hellojpa;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
publicclassJpaMain{
publicstaticvoidmain(String[] args){
EntityManagerFactory emf =
Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
Member member = new Member();
member.setId(1L);
member.setName("HELLOa");
em.persist(member);
tx.commit();
em.close();
emf.close(); // 팩토리를 나중에 닫는다.
}
}
Note) Main 클래스 실행 결과
persistence에 옵션을 정한대로 주석이 표시 되고 그 다음에 sql 포맷이 출력되는 걸 볼 수 있다.
쿼리를 직접 만들지 않았지만 JPA가 알아서 쿼리를 만들고 데이터를 넣어준 것이다.
위 매인 클래스를 실행한 다음에 H2를 들어가서 멤버 클래스를 조회하면 아래와 같이 데이터베이스에 데이터가 들어간 걸 볼 수 있다.
jdbc:h2:tcp://localhost/~/test
이 부분도 persistence 파일에서 정한대로 ip 주소를 따라가야한다.
persistence에 로컬 호스트로 지정해두고 다른 아이피로 들어가지 않도록 해야한다.
윈도우는 cmd 창에서 h2.bat을 실행해야한다.
cf) 만약 클래스의 클래스 / 필드 이름과 데이터베이스의 테이블 / 필드명이 다른 경우에
- @Table(name=""), @Column(name="")을 이용해서 쌍따옴표 안에 데이터베이스의 테이블 명 또는 필드 명을 적어줘서 매핑할 수 있다.