【发布时间】:2026-01-13 12:20:02
【问题描述】:
我正在开发 使用 Postgres 的 Spring Boot JPA 组合键示例。在这个例子中,当我试图保存记录时,为什么我没有看到任何异常或违反约束异常?
SongId.java
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Embeddable
public class SongId implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private String album;
private String artist;
}
Song.java
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Entity
public class Song {
@EmbeddedId
private SongId id;
private int duration;
private String genre;
private LocalDateTime releaseDate;
private int rating;
private String downloadUrl;
}
SongsRepository.java
public interface SongsRepository extends JpaRepository<Song, Long>{
}
MainApp.java
@SpringBootApplication
public class CompositeApplication implements CommandLineRunner{
public static void main(String[] args) {
SpringApplication.run(CompositeApplication.class, args);
}
@Autowired
private SongsRepository repo;
@Override
public void run(String... args) throws Exception {
SongId songId1 = SongId.builder().name("John").album("AlbumA").artist("ArtistA").build();
Song song = Song.builder().id(songId1).downloadUrl("http://www.gmail.com").duration(23)
.genre("MyGene").rating(1).releaseDate(LocalDateTime.now()).build();
Song song2 = Song.builder().id(songId1).downloadUrl("http://www.gmail.com").duration(23)
.genre("MyGene").rating(1).releaseDate(LocalDateTime.now()).build();
try {
repo.saveAll(Arrays.asList(song, song2));
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
Edit-1: 我将 SongsRepository.java 更改为
public interface SongsRepository extends CrudRepository<Song, SongId>{}
和主要方法代码。
@Override
public void run(String... args) throws Exception {
SongId songId1 = SongId.builder().name("John").album("AlbumA").artist("ArtistA").build();
Song song = Song.builder().songId(songId1).downloadUrl("http://www.gmail.com").duration(23)
.genre("MyGene").rating(4).releaseDate(LocalDateTime.now()).build();
Song song2 = Song.builder().songId(songId1).downloadUrl("http://www.yahoo.com").duration(25)
.genre("Sample Testung").rating(2).releaseDate(LocalDateTime.now()).build();
repo.saveAll(Arrays.asList(song, song2));
}
日志:
2019-07-03 19:56:31.901 INFO 5420 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 46ms. Found 1 repository interfaces.
2019-07-03 19:56:32.265 INFO 5420 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2019-07-03 19:56:32.378 INFO 5420 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2019-07-03 19:56:32.415 INFO 5420 --- [ main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [
name: default
...]
2019-07-03 19:56:32.466 INFO 5420 --- [ main] org.hibernate.Version : HHH000412: Hibernate Core {5.3.10.Final}
2019-07-03 19:56:32.467 INFO 5420 --- [ main] org.hibernate.cfg.Environment : HHH000206: hibernate.properties not found
2019-07-03 19:56:32.600 INFO 5420 --- [ main] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.0.4.Final}
2019-07-03 19:56:32.747 INFO 5420 --- [ main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.PostgreSQLDialect
2019-07-03 19:56:32.895 INFO 5420 --- [ main] o.h.e.j.e.i.LobCreatorBuilderImpl : HHH000421: Disabling contextual LOB creation as hibernate.jdbc.lob.non_contextual_creation is true
2019-07-03 19:56:32.899 INFO 5420 --- [ main] org.hibernate.type.BasicTypeRegistry : HHH000270: Type registration [java.util.UUID] overrides previous : org.hibernate.type.UUIDBinaryType@4ad3d266
Hibernate:
drop table if exists composite.song cascade
Hibernate:
create table composite.song (
album varchar(255) not null,
artist varchar(255) not null,
name varchar(255) not null,
download_url varchar(255),
duration int4 not null,
genre varchar(255),
rating int4 not null,
release_date timestamp,
primary key (album, artist, name)
)
2019-07-03 19:56:33.350 INFO 5420 --- [ main] o.h.t.schema.internal.SchemaCreatorImpl : HHH000476: Executing import script 'org.hibernate.tool.schema.internal.exec.ScriptSourceInputNonExistentImpl@41ad373'
2019-07-03 19:56:33.352 INFO 5420 --- [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2019-07-03 19:56:33.404 DEBUG 5420 --- [ main] .c.JpaMetamodelMappingContextFactoryBean : Initializing JpaMetamodelMappingContext…
2019-07-03 19:56:33.410 DEBUG 5420 --- [ main] .c.JpaMetamodelMappingContextFactoryBean : Finished initializing JpaMetamodelMappingContext!
2019-07-03 19:56:33.557 DEBUG 5420 --- [ main] o.s.d.r.c.s.RepositoryFactorySupport : Initializing repository instance for com.example.repository.SongsRepository…
2019-07-03 19:56:33.603 DEBUG 5420 --- [ main] o.s.d.j.r.query.JpaQueryFactory : Looking up query for method findBySongId_AlbumAndSongId_ArtistAndSongId_Name
2019-07-03 19:56:33.604 DEBUG 5420 --- [ main] o.s.d.jpa.repository.query.NamedQuery : Looking up named query Song.findBySongId_AlbumAndSongId_ArtistAndSongId_Name
2019-07-03 19:56:33.606 DEBUG 5420 --- [ main] o.s.d.jpa.repository.query.NamedQuery : Did not find named query Song.findBySongId_AlbumAndSongId_ArtistAndSongId_Name
2019-07-03 19:56:33.646 DEBUG 5420 --- [ main] o.s.d.r.c.s.RepositoryFactorySupport : Finished creation of repository instance for com.example.repository.SongsRepository.
2019-07-03 19:56:33.713 INFO 5420 --- [ main] com.example.CompositeApplication : Started CompositeApplication in 2.59 seconds (JVM running for 3.333)
2019-07-03 19:56:33.722 DEBUG 5420 --- [ main] stomAnnotationTransactionAttributeSource : Adding transactional method 'saveAll' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
Hibernate:
select
song0_.album as album1_0_0_,
song0_.artist as artist2_0_0_,
song0_.name as name3_0_0_,
song0_.download_url as download4_0_0_,
song0_.duration as duration5_0_0_,
song0_.genre as genre6_0_0_,
song0_.rating as rating7_0_0_,
song0_.release_date as release_8_0_0_
from
composite.song song0_
where
song0_.album=?
and song0_.artist=?
and song0_.name=?
Hibernate:
insert
into
composite.song
(download_url, duration, genre, rating, release_date, album, artist, name)
values
(?, ?, ?, ?, ?, ?, ?, ?)
Hibernate:
update
composite.song
set
download_url=?,
duration=?,
genre=?,
rating=?,
release_date=?
where
album=?
and artist=?
and name=?
2019-07-03 19:56:33.773 INFO 5420 --- [ Thread-4] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2019-07-03 19:56:33.776 INFO 5420 --- [ Thread-4] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated...
2019-07-03 19:56:33.779 INFO 5420 --- [ Thread-4] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed.
【问题讨论】:
-
您根据存储库接口将密钥定义为
Long。相反,它应该是正确的类型。接下来,您将插入完全相同的内容,并且由于生成的等于/哈希码,休眠会将其检测为相同的实体并丢弃一个。更改实体 2 的一些属性(不是那些构成密钥的属性),这应该使它失败。 -
这是因为最终会完成
merge。默认的isNew检查检查 id 是否为null。在您的情况下,它不是,因此它将导致合并,从而更新第二个实体而不是新实体。 -
@M.Deinum - 你是对的。在检查
isNew后进行合并。你能指导我现在如何解决这个问题吗? -
能否分享一下日志的堆栈跟踪
-
@Mayur Jain - 添加日志
标签: java postgresql spring-data-jpa