首先:生成的Id不映射到实体对象。从h2日志看,似乎返回了generatedKeys结果集,并且jpa通过resultSet.getInt(1)获取密钥。但是对象id字段未设置为返回值。
第二:是否有必要使用交易?现在我正在测试简单的CRUD命令并且不需要事务,我希望提交在DAO中调用的每个方法。所以我设置autocommit = true,但是hibernate一直将它设置为false。如何解决?我希望在DAO中调用的方法连接我自己的连接和测试数据后。现在我刚创建@AfterTransactional并检查数据,但这是非常糟糕的解决方案。
模型 @实体 @Table(name =" personal_phone_tbl") 公共类PersonalPhone {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Column(name = "phone")
private String number;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
}
DAO
@Repository
@Transactional
public class PersonalPhoneDao {
@Autowired
private EntityManager entityManager;
public void create(PersonalPhone phone) {
entityManager.merge(phone);
}
context.xml中
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/phonebook" expected-type="javax.sql.DataSource"/>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation" value="classpath:persistence.xml"/>
<property name="persistenceUnitName" value="phonebook-persistence"/>
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan" value="phonebook.*"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true"/>
<property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect"/>
</bean>
</property>
</bean>
<bean id="entityManager" class="org.springframework.orm.jpa.support.SharedEntityManagerBean">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
h2 Log
INFO: Began transaction (1) for test context [DefaultTestContext@2267889d testClass = PersonalPhoneDaoTest, testInstance = com.getjavajob.web06.zhukm.PersonalPhoneDaoTest@3b3a0d10, testMethod = testInsert@AbstractDaoTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@4b06e721 testClass = PersonalPhoneDaoTest, locations = '{classpath:dao-context.xml, classpath:dao-context-overrides.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]]; transaction manager [org.springframework.orm.jpa.JpaTransactionManager@602fb3d0]; rollback [false]
2016-01-29 02:48:50 jdbc[6]:
/**/conn3.close();
2016-01-29 02:48:50 database: disconnecting session #6
2016-01-29 02:48:50 database: disconnected session #6
Hibernate: insert into personal_phone_tbl (phone) values (?)
2016-01-29 02:48:50 jdbc[4]:
/**/conn1.prepareStatement("insert into personal_phone_tbl (phone) values (?)", 1);
2016-01-29 02:48:50 jdbc[4]:
/**/PreparedStatement prep1 = conn1.prepareStatement("insert into personal_phone_tbl (phone) values (?)");
2016-01-29 02:48:50 jdbc[4]:
/**/prep1.setString(1, "+7(909)6696578");
2016-01-29 02:48:50 jdbc[4]:
/**/prep1.executeUpdate();
2016-01-29 02:48:50 lock: 1 exclusive write lock requesting for SYS
2016-01-29 02:48:50 lock: 1 exclusive write lock added for SYS
2016-01-29 02:48:50 lock: 1 exclusive write lock unlock SYS
2016-01-29 02:48:50 lock: 1 shared read lock unlock SYS
2016-01-29 02:48:50 lock: 4 shared read lock requesting for PERSONAL_PHONE_TBL
2016-01-29 02:48:50 lock: 4 shared read lock ok PERSONAL_PHONE_TBL
2016-01-29 02:48:50 jdbc[4]:
/*SQL l:49 #:1 t:2*/insert into personal_phone_tbl (phone) values (?) {1: '+7(909)6696578'};
2016-01-29 02:48:50 jdbc[4]:
/**/ResultSet rs21 = prep1.getGeneratedKeys();
2016-01-29 02:48:50 jdbc[4]:
/*SQL #:1*/SELECT SCOPE_IDENTITY() WHERE SCOPE_IDENTITY() IS NOT NULL;
2016-01-29 02:48:50 jdbc[4]:
/**/rs21.next();
2016-01-29 02:48:50 jdbc[4]:
/**/ResultSetMetaData rsMeta0 = rs21.getMetaData();
2016-01-29 02:48:50 jdbc[4]:
/**/conn1.getCatalog();
2016-01-29 02:48:50 jdbc[4]:
/**/rsMeta0.getColumnCount();
2016-01-29 02:48:50 jdbc[4]:
/**/rs21.getInt(1);
2016-01-29 02:48:50 jdbc[4]:
/**/rs21.close();
2016-01-29 02:48:50 jdbc[4]:
/**/prep1.getWarnings();
2016-01-29 02:48:50 jdbc[4]:
/**/prep1.clearWarnings();
2016-01-29 02:48:50 jdbc[4]:
/**/prep1.getMaxRows();
2016-01-29 02:48:50 jdbc[4]:
/**/prep1.getQueryTimeout();
2016-01-29 02:48:50 jdbc[4]:
/*SQL l:58 #:1 t:1*/SELECT VALUE FROM INFORMATION_SCHEMA.SETTINGS WHERE NAME=? {1: 'QUERY_TIMEOUT'};
2016-01-29 02:48:50 jdbc[4]:
/**/prep1.close();
-----------------------------> personalPhone.getId()0
2016-01-29 02:48:50 jdbc[4]:
/**/conn1.commit();
2016-01-29 02:48:50 lock: 4 shared read lock unlock PERSONAL_PHONE_TBL
2016-01-29 02:48:50 jdbc[4]:
/*SQL */COMMIT;
2016-01-29 02:48:50 jdbc[4]:
/**/conn1.setAutoCommit(true);
2016-01-29 02:48:50 jdbc[4]:
/**/conn1.commit();
2016-01-29 02:48:50 jdbc[4]:
/*SQL */COMMIT;
2016-01-29 02:48:50 jdbc[4]:
/**/conn1.isClosed();
2016-01-29 02:48:50 jdbc[4]:
/**/conn1.getWarnings();
2016-01-29 02:48:50 jdbc[4]:
/**/conn1.clearWarnings();
2016-01-29 02:48:50 jdbc[4]:
/**/conn1.isClosed();
2016-01-29 02:48:50 jdbc[4]:
/**/conn1.clearWarnings();
Jan 29, 2016 2:48:50 AM org.springframework.test.context.transaction.TransactionContext endTransaction
INFO: Committed transaction for test context [DefaultTestContext@2267889d testClass = PersonalPhoneDaoTest, testInstance = com.getjavajob.web06.zhukm.PersonalPhoneDaoTest@3b3a0d10, testMethod = testInsert@AbstractDaoTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@4b06e721 testClass = PersonalPhoneDaoTest, locations = '{classpath:dao-context.xml, classpath:dao-context-overrides.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]].
-----------------------------> @AfterTransaction
-----------------------------> personalPhone.getId()0
2016-01-29 02:48:50 database: connecting session #7 to mem:test
2016-01-29 02:48:50 jdbc[7]:
/*SQL */SET MODE MYSQL;
2016-01-29 02:48:50 jdbc[7]:
/*SQL */SET DB_CLOSE_DELAY -1;
2016-01-29 02:48:50 jdbc[7]:
/**/Connection conn4 = DriverManager.getConnection("jdbc:h2:mem:test;MODE=MYSQL;DB_CLOSE_DELAY=-1", "SA", "");
2016-01-29 02:48:50 jdbc[7]:
/**/conn4.setAutoCommit(false);
2016-01-29 02:48:50 jdbc[7]:
/**/Statement stat2 = conn4.createStatement();
2016-01-29 02:48:50 jdbc[7]:
/**/ResultSet rs22 = stat2.executeQuery("SELECT * FROM personal_phone_tbl");
2016-01-29 02:48:50 jdbc[7]:
/*SQL #:1*/SELECT * FROM personal_phone_tbl;
2016-01-29 02:48:50 jdbc[7]:
/**/rs22.next();
----------------------------->ResultSet
2016-01-29 02:48:50 jdbc[7]:
/**/rs22.getObject(1);
1
2016-01-29 02:48:50 jdbc[7]:
/**/rs22.getObject(2);
+7(909)6696578
----------------------------->ResultSet
2016-01-29 02:48:50 jdbc[7]:
/**/stat2.close();
2016-01-29 02:48:50 jdbc[7]:
/**/conn4.close();
2016-01-29 02:48:50 database: disconnecting session #7
2016-01-29 02:48:50 database: disconnected session #7
2016-01-29 02:48:50 database: closing mem:test from shutdown hook
2016-01-29 02:48:50 database: disconnecting session #4
2016-01-29 02:48:50 database: closing mem:test
2016-01-29 02:48:50 lock: 1 exclusive write lock requesting for SYS
2016-01-29 02:48:50 lock: 1 exclusive write lock added for SYS
2016-01-29 02:48:50 lock: 1 exclusive write lock unlock SYS
2016-01-29 02:48:50 lock: 1 shared read lock unlock SYS
2016-01-29 02:48:50 database: closed
测试
@Before
public void createDb() {
super.dropTables();
super.createDb();
personalPhone = new PersonalPhone();
personalPhone.setNumber("123456");
}
@Override
public void testInsert() {
personalPhoneDao.create(personalPhone);
System.out.println("-----------------------------> personalPhone.getId()"+personalPhone.getId());
connect();
try (Statement statement = connection.createStatement()) {
ResultSet resultSet = statement.executeQuery(SELECT);
if(resultSet.next()){
System.out.println("----------------------------->ResultSet");
System.out.println(resultSet.getObject(1));
System.out.println(resultSet.getInt("id"));
System.out.println(resultSet.getObject(2));
System.out.println("----------------------------->ResultSet");
} else {
Assert.fail();
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
super.close();
}
}
表
CREATE TABLE personal_phone_tbl(
id INT NOT NULL AUTO_INCREMENT,
phone VARCHAR(25) NOT NULL,
employee_id INT,
PRIMARY KEY(id),
FOREIGN KEY (employee_id) REFERENCES employee_tbl(id)
);
答案 0 :(得分:0)
如果您使用
@GeneratedValue(strategy = GenerationType.IDENTITY)
生成的Id将从下一个Id开始,所以如果你有一行将101作为id,那么下一个将是102
@GeneratedValue(strategy = GenerationType.AUTO)
将从第一个未使用的值开始。如果表中没有任何内容,他们也应该这样做。通常你应该使用符合预期的GenerationType.AUTO。
答案 1 :(得分:0)
我的坏。我虽然merge(实体)修改了传递给它的对象。解决方案是更改create方法:
public PersonalPhone create(PersonalPhone phone) {
return entityManager.merge(phone);
}