my problem is next. I have two table. Table1 that name "Instructor" and Table2 that name "User".
When i displaying information in my template, i need retrieve information about user from table Instructor.
My entity Instructor join column to users
`#Entity
#Table (name = "Instructor")
public class Instructor {
#Id
#GeneratedValue (strategy = GenerationType.IDENTITY)
#Column (name = "instructor_id", nullable = false)
private Long instructorId;
#Basic
#Column (name = "name", nullable = false, length = 45)
private String firstName;
#Basic
#Column (name = "lastName", nullable = false, length = 45)
private String lastName;
#Basic
#Column (name = "summary", nullable = false, length = 45)
private String instructorSummary;
#OneToMany (mappedBy = "instructor", fetch = FetchType.LAZY)
private Set <Course> courses = new HashSet<>();
#OneToOne (cascade = CascadeType.REMOVE)
#JoinColumn (name = "user_id", referencedColumnName = "user_id", nullable = false)
private User user; `
Dao layer when i have Exception
#Query (nativeQuery=true, value = "select i from Instructor as i where i.user.userEmail =:userEmail") Instructor findInstructByuserEmail (#Param ("userEmail") String userEmail);
User Entity
`#Entity
#Table (name = "users")
public class User {
#Id
#GeneratedValue (strategy = GenerationType.IDENTITY)
#Column (name = "user_id", nullable = false)
private Long userId;
#Basic
#Column (name = "email", nullable = false, length = 96, unique = true)
private String userEmail;
#Basic
#Column (name = "password", nullable = false, length = 96)
private String userPassword;
#ManyToMany (fetch = FetchType.EAGER)
#NotFound(action = NotFoundAction.IGNORE)
#JoinTable (name = "user_role",
joinColumns = {#JoinColumn (name = "user_id")},
inverseJoinColumns = {#JoinColumn (name = "role_id")})
private Set <Role> roles = new HashSet<>();
#OneToOne (mappedBy = "user")
private Student student;
#OneToOne (mappedBy = "user")
private Instructor instructor;`
Couple time i change Query in Dao layer, but it does't help me.
My Stack trace
In there Hibernate create request !
Hibernate: select i from Instructor as i where i.user.userEmail =?
2023-01-23T14:30:30.682+02:00 WARN 32888 --- [nio-8071-exec-4] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 1054, SQLState: 42S22
2023-01-23T14:30:30.682+02:00 ERROR 32888 --- [nio-8071-exec-4] o.h.engine.jdbc.spi.SqlExceptionHelper : Unknown column 'i' in 'field list'
2023-01-23T14:30:30.688+02:00 ERROR 32888 --- [nio-8071-exec-4] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.springframework.dao.InvalidDataAccessResourceUsageException: JDBC exception executing SQL [select i from Instructor as i where i.user.userEmail =?]; SQL [n/a]] with root cause
and than i give Exception !
java.sql.SQLSyntaxErrorException: Unknown column 'i' in 'field list'
Also if you know good material, about Query it will be very useful for me, tnx!
Related
I have two entities - User and Song:
User.class:
#Entity
#Table(name = "users")
public class User {
#Id
#Column(name = "user_id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "first_name")
private String firstName;
#Column(name = "last_name")
private String lastName;
#Column(name = "login",unique = true)
private String login;
#Column(name = "password")
private String password;
#Column(name = "token")
private UUID token;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinTable(
name = "users_songs",
joinColumns = #JoinColumn(
name = "u_id",
referencedColumnName = "user_id"
),
inverseJoinColumns = #JoinColumn(
name = "s_id",
referencedColumnName = "song_id"
)
)
private List<Song> songs = new ArrayList<>();
}
Song.class:
#Entity
#Table(name = "songs")
public class Song {
#Id
#Column(name = "song_id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "song_title")
private String songTitle;
#Column(name = "composer_name")
#ElementCollection(fetch = FetchType.EAGER)
#CollectionTable(name = "composers")
#OnDelete(action = OnDeleteAction.CASCADE)
#JoinColumn(name = "composer_id")
private Set<String> composer;
#Column(name = "author_of_words_name")
#ElementCollection(fetch = FetchType.EAGER)
#CollectionTable(name = "author_of_words")
#OnDelete(action = OnDeleteAction.CASCADE)
#JoinColumn(name = "authorOfWords_id")
private Set<String> authorOfWords;
#Column(name = "song_artist")
private String songArtist;
#Column(name = "song_timing")
private int songTiming;
#ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH})
#JoinColumn(name = "user_id_key")
private User user;
#Column(name = "rate_value")
#ElementCollection(fetch = FetchType.EAGER)
#CollectionTable(name = "rating")
#MapKeyColumn(name = "login")
#OnDelete(action = OnDeleteAction.CASCADE)
#JoinColumn
private final Map<String, Integer> rating = new HashMap<>();
#Column
#ElementCollection(fetch = FetchType.EAGER)
#CollectionTable(name = "comment")
#MapKeyColumn(name = "login")
#OnDelete(action = OnDeleteAction.CASCADE)
#JoinColumn
private final Map<String, String> comments = new HashMap<>();
}
I want to delete a Song, but not delete a User.
I tried deleting it like this:
Query query = session.createQuery("DELETE Song s WHERE s.user = :user AND s.songTitle = :songTitle");
query.setParameter("user", user);
query.setParameter("songTitle", songTitle);
query.executeUpdate()
But the error drops:
Caused by: org.hibernate.exception.ConstraintViolationException: could not execute statement...
Caused by: org.postgresql.util.PSQLException: ERROR: update or delete on table "songs" violates foreign key constraint "fka7me64vk6jtx81wt2ggbvm6ur" on table "users_songs"
Key (song_id)=(28) is still referenced from table "users_songs".
I understand that the problem is due to the fact that in the spanning table users_songs, which occurred due to the connection #OneToMany.
I read a similar question in the STO and it says that you need to break the connection. how to delete the record from the join table in hibernate
I executed the following code:
List<Song> collect = user.getSongs().stream().filter(s -> !s.getSongTitle().equals(songTitle)).collect(Collectors.toList());
user.setSongs(collect);
session.update(user);
Query query = session.createQuery("DELETE Song s WHERE s.songTitle = :songTitle");
query.setParameter("songTitle", songTitle);
query.executeUpdate();
This code works, but I don't think it's quite right. Now the question. How do I delete a Song from a user? With the condition that the song should not cascade to delete the user.
Please help me solve this issue correctly. I'd really appreciate it.
You can specify ON DELETE CASCADE for the foreign key constraint fka7me64vk6jtx81wt2ggbvm6ur on the table users_songs like below:
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinTable(
name = "users_songs",
joinColumns = #JoinColumn(
name = "u_id",
referencedColumnName = "user_id"
),
inverseJoinColumns = #JoinColumn(
name = "s_id",
referencedColumnName = "song_id"
),
inverseForeignKey = #ForeignKey(
name = "users_songs_songs_FK", // fka7me64vk6jtx81wt2ggbvm6ur renamed to users_songs_songs_FK
foreignKeyDefinition = "FOREIGN KEY (s_id) REFERENCES songs(song_id) ON DELETE CASCADE"
)
)
private List<Song> songs = new ArrayList<>();
and after database schema regeneration your initial query should work as expected.
In my project I use Spring data jpa. I have tables for many to many relationship. My entities:
#Entity
#Table(name = "SPEC")
public class SpecJpa {
#Id
private int id;
#Column(name = "NAME")
private String name;
#OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinColumn(name = "Creator_ID", unique = false, nullable = false, updatable = true)
private UsersJpa usersJpa;
#Column(name = "DESCRIPTION")
private String description;
#ManyToMany(fetch = FetchType.EAGER)
#JoinTable(name="SPEC_PARTS",
joinColumns = #JoinColumn(name="ID_PARTS", referencedColumnName="id"),
inverseJoinColumns = #JoinColumn(name="ID_SPEC", referencedColumnName="id")
)
private Set<PartsJpa> partsJpa;
//---------------
And Parts:
#Entity
#Table(name = "PARTS")
public class PartsJpa {
#Id
private int id;
#Column(name = "NAME")
private String name;
#OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinColumn(name = "ID_EXPORT", unique = false, nullable = false, updatable = true)
private ExportJpa exportJpa;
#OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinColumn(name = "ID_TYPE", unique = false, nullable = false, updatable = true)
private TypesJpa typesJpa;
#Column(name = "DESCRIPTION")
private String description;
#ManyToMany(fetch = FetchType.EAGER)
private Set<SpecJpa> specJpa;
Now in Controller I try to delete one row from table parts:
#PostMapping("deletePart")
public String deletePart(#RequestParam String id, Model model) {
partsService.deleteById(Integer.parseInt(id));
return "redirect:/parts";
}
But I have exception:
ferential integrity constraint violation:
"FK9Y4MKICYBLJWPENACP4298I49: PUBLIC.PARTS FOREIGN KEY(ID_EXPORT)
REFERENCES PUBLIC.EXPORT(ID) (1)"; SQL statement: /* delete
com.aleksandr0412.demo.entitiesjpa.ExportJpa / delete from EXPORT
where id=? [23503-200]], SQL: / delete
com.aleksandr0412.demo.entitiesjpa.ExportJpa */ delete from EXPORT
where id=? 2020-05-25 19:16:31.630 WARN 13387 --- [nio-8080-exec-4]
o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 23503, SQLState:
23503
In my db for this entities I have 3 tables: Parts, Spec and Spec_parts. As I understand to solve this problem, I firstly should delete rows in table spec_parts, and after this I can delete row from table parts. How can I do this?
In your partsService implementation, I would recommend you first fetch the resource you are about to delete (i.e the PartsJpa) using the given id from the controller.
Next set its specJpa to null or emptySet, then call the delete method afterwards.
For this to work, ensure that method setSpecJpa(SpecJpa specJpa) and setPartJpa(PartJpa partJpa) are properly implemented.
I hope you find this helpful.
I'm having an issue with JPA and Hibernate. I have 2 classes (actually more but those are the 2 that are giving me a headache).
They have a OneToMany/ManyToOne relationship, and I have specified on the OneToMany that I want it to cascade every possible change (CascadeType.ALL).
However, when I let HBM2DDL run in "update" mode, it is creating foreign key constraints that are not fitting what I want to achieve. It is creating a constraint in RESTRICT mode, which is absolutely not what I have specified. Perhaps the error is in my code ? I've joined it below.
#Entity
public class Department {
#Id
#Column(name = "id", nullable = false)
private int id;
#Column(name = "name", nullable = false)
private String name;
#OneToMany(mappedBy = "departmentByDepartment", cascade = CascadeType.ALL)
private Collection<Article> productsById;
#OneToMany(mappedBy = "departmentByDepartment", cascade = CascadeType.ALL)
private Collection<User> usersById;
And then :
#Entity
#Table(name = "product", schema = "qlog_project", catalog = "")
public class Article {
#Id
#Column(name = "id", nullable = false)
private int id;
#Column(name = "name", nullable = false)
private String name;
#Column(name = "description", nullable = false)
private String description;
#Column(name = "price", nullable = false)
private double price;
#Column(name = "image", nullable = false)
private String image;
#ManyToOne
#JoinColumn(name = "department", referencedColumnName = "id", nullable = false)
private Department departmentByDepartment;
#OneToMany(mappedBy = "productByProductId", cascade = CascadeType.ALL)
private Collection<Stock> stocksById;
Also, I cannot seem to be able to delete an Article instance with EntityManager.remove(). It's not producing any query and not doing anything. Maybe it is linked ?
Thanks in advance,
Regards
#Entity
#Getter
#Setter
#Table(name = "product_wallet")
#NamedQuery(name = "ProductWallet.findAll", query = "SELECT pw FROM ProductWallet pw")
#EntityListeners(CUEntityListener.class)
public class ProductWallet implements Serializable, CUEntity {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "product_wallet_id", unique = true, nullable = false)
private Long productWalletId;
#Column
private Integer total;
#Column
private String status;
#Column(name = "user_id", updatable = false, insertable = false)
private String userId;
#Column(name = "member_id", updatable = false, insertable = false)
private Long memberId;
#Column(name = "provider_id", updatable = false, insertable = false)
private String providerId;
#Column(name = "created_by", length = 100)
private String createdBy;
#Column(name = "created_date")
private Timestamp createdDate;
#Column(name = "modified_by", length = 50)
private String modifiedBy;
#Column(name = "modified_date")
private Timestamp modifiedDate;
//bi-directional many-to-one association to MUser
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "user_id", referencedColumnName = "user_id")
private MUser user;
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "member_id")
private Member member;
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "provider_id")
private Provider provider;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "productWallet")
private List<ProductWalletItem> productWalletItems;
I am trying to use this method using the automatic query creation by JPA, writing the query manually, etc.
ProductWallet findProductWalletByProviderIdAndMemberId(String providerId, Long memberId);
but for some reason, String providerId get converted to Long for all of them and I get this error. It seems like jdbc is desperately trying to convert something to Long:
Bad value for type long : PR_0000000288
2019-10-11 19:12:56 - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: could not execute query; SQL [select productwal0_.product_wallet_id as product_1_41_, productwal0_.created_by as created_2_41_, productwal0_.created_date as created_3_41_, productwal0_.member_id as member_i4_41_, productwal0_.modified_by as modified5_41_, productwal0_.modified_date as modified6_41_, productwal0_.provider_id as provider7_41_, productwal0_.status as status8_41_, productwal0_.total as total9_41_, productwal0_.user_id as user_id10_41_ from product_wallet productwal0_ where productwal0_.provider_id=? and productwal0_.member_id=?]; nested exception is org.hibernate.exception.DataException: could not execute query] with root cause
org.postgresql.util.PSQLException: Bad value for type long : PR_0000000288
at org.postgresql.jdbc.PgResultSet.toLong(PgResultSet.java:2860)
at org.postgresql.jdbc.PgResultSet.getLong(PgResultSet.java:2114)
at org.postgresql.jdbc.PgResultSet.getLong(PgResultSet.java:2506)
at com.zaxxer.hikari.proxy.HikariResultSetProxy.getLong(HikariResultSetProxy.java)
at org.hibernate.type.descriptor.sql.BigIntTypeDescriptor$2.doExtract(BigIntTypeDescriptor.java:63)
at org.hibernate.type.descriptor.sql.BasicExtractor.extract(BasicExtractor.java:47)
I think it's because you have two provider_id column in your table. One for the filed providerId and the other for the join column for Provider object. I assume the id for the object Provider is Long type. Can you rename one of these and try?
I am getting an exception with hibernate that I can't figure out.
org.hibernate.AnnotationException: Unable to create unique key constraint (role, username) on table user_roles: database column 'role' not found. Make sure that you use the correct column name which depends on the naming strategy in use (it may not be the same as the property name in the entity, especially for relational types)
I have defined the name of the column "role" with the annotation, am I missing something here?
Any help appreciated.
...
#Entity
#Table(name = "user_roles", uniqueConstraints = #UniqueConstraint(columnNames =
{ "role", "username" }) )
public class UserRole
{
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "user_role_id", unique = true, nullable = false)
private Integer userRoleId;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "username", nullable = false)
private User user;
#Column(name = "role", nullable = false, length = 45)
private String role;
...
}