how to change this sql query to hibernate query? - sql

I want to change this sql query to hibernate query.
SQL query:
SELECT *
FROM User
WHERE (DATE_SUB(NOW(), INTERVAL 1 DAY) >= AccountStartDate)
AND PINStatus = 'N'
AND PetName IS NULL
AND SchoolName IS NULL
AND AccountType = 'Supervisor'
This is my User class
#Entity
#Table(name = "User")
public class User{
#Id
#GeneratedValue
#Column(name="UserID")
private long userID;
#Column(name="AccountStartDate")
private Date accountStartDate;
#Column(name="PINStatus")
private String pinStatus;
#Column(name="PetName")
private String petName;;
#Column(name="SchoolName")
private String schoolName;
#Column(name="AccountType")
private String accountType;
}

Here is part of the answer... Try this
User user = _session.CreateCriteria<User>()
.Add(Restrictions.Eq("PINStatus", "[VARIABLE PARAMETER]"))
.AddOrder(new Order("_id", false))
.List<User>()
.FirstOrDefault();
That will result in something like:
select * from User where PINStatus = ??? Order By Id desc

Query query=sessionFactory.getCurrentSession().createQuery("FROM User WHERE " +
"pinStatus=:pinStatus AND petName IS NULL AND schoolName IS NULL AND accountType=:accountType")
.setString("accountType", "User").setString("pinStatus", "N");
List<User> userList=query.list();
Iterator<User> itr = userList.iterator();
while(itr.hasNext()) {
User user = (User) itr.next();
long diff=currentDate.getTime() - user.getAccountStartDate().getTime();
long diffHours = diff / (60 * 60 * 1000);
if(diffHours>=24)
{
System.out.println("User added "+user.getFirstName());
userList1.add(user);
}
}

Related

Nested query in JPQL

I have 2 entities -
#Table(name = "MM_MONITORING_CARD")
#Entity(name = "mm_MonitoringCard")
public class MonitoringCard extends StandardEntity {
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "CLIENT_ID")
private Counterparty client;
#Column(name = "START_DATE")
private LocalDate startDate;
#Column(name = "END_DATE")
private LocalDate endDate;
...otherColumn
}
and
#DiscriminatorColumn(name = "TYPE", discriminatorType = DiscriminatorType.STRING)
#Table(name = "MM_COUNTERPARTY")
#Entity(name = "mm_Counterparty")
#DiscriminatorValue("COUNTERPARTY")
#NamePattern("%s|name")
public class Counterparty extends StandardEntity {
#Column(name = "TYPE", insertable=false, updateable=false)
private String type;
...otherColumn
I need get all examples monitoringCard with condition - 1) between start date and end date 2) with Counterparty type = 'someType'
I do method -
List<MonitoringCard> monitoringCardList = dataManager.load(MonitoringCard.class)
.query("select distinct cm from mm_MonitoringCard m join mm_Counterparty cm where (m.current_date between cm.startDate and cm.endDate) and cm.type = :type")
.parameter("type", "someType")
.list();
but i get error, how can i make a correct request?
thanks
Your query is not correct. It should use a join like this:
select distinct m.Counterparty from mm_MonitoringCard m
where (m.current_date between m.Counterparty.startDate and m.Counterparty.endDate)
and m.Counterparty.type = :type
In JPA you don't need to do an explicit join when navigating on a ToOne relationship.

MediaStore select query returns only one row

I'm trying to develop music player, I've made a loader and adapter for my data retreiving from mediastore, but when I call query from my app it only returns one row, I don't know wat's wrong with my code, would u help me fixing that problem?
That's my loader which should return a list I'll use in another place
public static List<Song> getAllArtistSongs(Context context, long artist_id){
List<Song> ArtistSongList = new ArrayList<>();
Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
String[] projection = new String[]{
"_id",
"title",
"album_id",
"album",
"artist",
"duration",
"track"
};
String sortorder = MediaStore.Audio.Media.DEFAULT_SORT_ORDER;
String selection = "is_music=1 and artist_id="+artist_id;
Cursor cursor = context.getContentResolver().query(uri, projection, selection, null, sortorder);
assert cursor != null;
if (cursor.moveToFirst()) {
do {
int trackNumber = cursor.getInt(6);
while (trackNumber >= 1000) {
trackNumber -= 1000;
}
Long id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media._ID));
String title = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.TITLE));
Long albumid = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ALBUM_ID));
String albumname = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ALBUM));
String artistname = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ARTIST));
int duration = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DURATION));
ArtistSongList.add(new Song(id, title, albumid, albumname, artist_id, artistname, duration, trackNumber));
} while (cursor.moveToNext());
cursor.close();
}
return ArtistSongList;
}
And this is the adapter which I use to bind to a recyclerview
public void onBindViewHolder(#NonNull VH holder, int position) {
Song song = artistSongList.get(position);
if(song!=null){
holder.ttv.setText(song.title);
holder.dtv.setText(song.artistName);
int trackN = song.trackNumber;
if(trackN==0){
holder.ntv.setText("_");
}else holder.ntv.setText(String.valueOf(trackN));
}
}
And this is where I call the query func
private void setupAlbumList() {
System.out.println(artistId);
songList = ArtistSongLoader.getAllArtistSongs(getActivity(), artistId);
adapter = new ArtistSongAdapter(getActivity(), songList);
recy.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL));
recy.setAdapter(new ArtistSongAdapter(getActivity(), songList));
}
Thx in advance for helping
My example to retrieve all tracks:
private final String track_id = MediaStore.Audio.Media._ID;
private final String track_no = MediaStore.Audio.Media.TRACK;
private final String track_name = MediaStore.Audio.Media.TITLE;
private final String artist = MediaStore.Audio.Media.ARTIST;
private final String artist_id = MediaStore.Audio.Media.ARTIST_ID;
private final String duration = MediaStore.Audio.Media.DURATION;
private final String album = MediaStore.Audio.Media.ALBUM;
private final String composer = MediaStore.Audio.Media.COMPOSER;
private final String year = MediaStore.Audio.Media.YEAR;
private final String path = MediaStore.Audio.Media.DATA;
private final String date_added = MediaStore.Audio.Media.DATE_ADDED;
public Cursor getAllTracks(Context context) {
// gets all tracks
if (context != null) {
ContentResolver cr = context.getContentResolver();
final String[] columns = {track_id, track_no, artist, track_name,
album, duration, path, year, composer};
return cr.query(uri, columns, null, null, null);
} else {
return null;
}
}
then you have
String selection = "is_music=1"
first, you do not need is_music=1. For multiple tracks you of course need more than 1 track by the same artist
The adapter is irrelevant, the query does the selection
To return albums for an artist
public Cursor getArtistsAlbumcursor(Context context, String artistId) {
ContentResolver cr = context.getContentResolver();
final String _id = MediaStore.Audio.Media._ID;
final String album_id = MediaStore.Audio.Media.ALBUM_ID;
final String artistid = MediaStore.Audio.Media.ARTIST_ID;
final String[] columns = {_id, album_id, artistid};
if (artistId != null) {
String where = artistid + " =?";
String[] aId = {artistId};
return cr.query(uri, columns, where, aId, null);
} else {
return null;
}
}

EclipseLink- JPQL join tables through query

I have problem with my JPQl. this is a one to many relationship with TrainRoute and TrainRouteStation. I'm trying to create a inner join and fetch the data. native SQL query working when I used mysql workbeanch and I'm trying convert it to JPQL. also, I was trying to fix from 2 days.
Error : Object comparisons can only be used with OneToOneMappings. Other mapping comparisons must be done through query keys or direct attribute level comparisons.
Class: TrainRoute
#Basic(optional = false)
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Id
#Column(name = "train_route_id", unique = true, nullable = false)
public Long getTrainRouteId() {
return this.trainRouteId;
}
public void setTrainRouteId(Long trainRouteId) {
this.trainRouteId = trainRouteId;
}
#OneToMany(cascade = CascadeType.ALL,fetch = FetchType.EAGER, mappedBy = "trainRoute")
public List<TrainRouteStationData> getTrainRouteStations() {
return this.trainRouteStations;
}
public void setTrainRouteStations(List<TrainRouteStationData> trainRouteStations) {
this.trainRouteStations = trainRouteStations;
}
Class: TrainRouteStation
#Basic(optional = false)
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Id
#Column(name = "train_route_station_id", unique = true, nullable = false)
public Long getTrainRouteStationId() {
return this.trainRouteStationId;
}
public void setTrainRouteStationId(Long trainRouteStationId) {
this.trainRouteStationId = trainRouteStationId;
}
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "train_route_id", nullable = false)
public TrainRouteData getTrainRoute() {
return this.trainRoute;
}
JPQL :"SELECT s FROM TrainRouteData t inner join TrainRouteStationData s ON t.trainRouteId=s.trainRoute where s.stationSeqN >=1 AND s.stationSeqN <=3 AND t.trainRouteDescX='Test1-Test2' order by s.stationSeqN asc"
Native SQL : SELECT train_route_station.* FROM train_route inner join train_route_station ON train_route.train_route_id=train_route_station.train_route_id where train_route_station.station_seq_n >= 1 AND train_route_station.station_seq_n <= 3 AND train_route.train_route_desc_x='Test1-Test2' order by train_route_station.station_seq_n asc
And it throw an error:
Exception Description: Object comparisons can only be used with OneToOneMappings. Other mapping comparisons must be done through query keys or direct attribute level comparisons.
Mapping: [org.eclipse.persistence.mappings.DirectToFieldMapping[trainRouteId-->train_route.train_route_id]]
Expression: [
Query Key trainRouteId
How can I change that query?
That's not how joins work in JPQL.
The correct query is
select s from TrainRouteData t inner join t.trainRouteStations s
where s.stationSeqN >= 1
and s.stationSeqN <= 3
and t.trainRouteDescX = 'Test1-Test2'
order by s.stationSeqN asc

How to get #Query( nativeQuery=true) result into List<MyObject>?

Hello I have a query and I want the result into list of objects, not entity. But the result is actualy a object which I should transfer to my object. Is there a way to map it directly to my custom object?
Maybe this will help you :
public interface ObjRepository extends JpaRepository<MyObject, Long> {
#Query(value = "FROM MyObject WHERE objname = ?1")
public List<MyObject> findByName(String name);
}
Approach-1: using List of object array.
When using native query, we get list of Object array i.e each row in list is array. Elements in array represent column values.
In repo interface:
#Query(value = "select col1, col2, col3 from table1 where col1 = :key", nativeQuery = true)
List<Object[]> findByKey(#Param("key") String key);
In caller
List<Object[]> objectList = new ArrayList<Object[]>();
objectList = repo.findByKey(key);
List<CustomObject> customObjectList = new ArrayList<>();
for (Object[] tuple : objectList) {
String col1 = (String) tuple[0];
String col2 = (String) tuple[1];
String col3 = (String) tuple[2];
CustomObject obj = new CustomObject();
obj.setCol1(col1);
obj.setCol2(col2);
obj.setCol3(col3);
customObjectList.add(obj);
}
return customObjectList;
Approach-2: using custom dto that represents columns in each row.
Refer https://stackoverflow.com/a/42905382/1358551
final List<MyCustomDTO> statuses = myRepository
.findStatuses(marketId, campaignId, stationIds).stream()
.map(o -> new MyCustomDTO(((BigInteger) o[0]), (Boolean) o[1], (Timestamp) o[2]))
.collect(toList());
public class StationStatusDTO {
private long id;
private boolean isSomething;
private LocalDateTime date;
public MyCustomDTO(BigInteger id, Boolean isSomething, Timestamp date) {
this(id.longValue(),
isSomething,
(date == null) ? null : LocalDateTime
.ofInstant(Instant.ofEpochMilli(date.getTime()),
TimeZone.getDefault().toZoneId()));
}

java.lang.IllegalArgumentException with toplink and JPA

I've a problem with JPA, whenever execute this query
#NamedQuery(name = "Usuario.getUsuarioIntento", query = "SELECT u.intentos_id FROM Usuario u WHERE u.username = :username and u.borrado = 0")
i get this error:
java.lang.IllegalArgumentException: NamedQuery of name: Usuario.getUsuarioIntento not found.
But if i execute this query
#NamedQuery(name = "Usuario.getUsuarioIntento", query = "SELECT u.id FROM Usuario u WHERE u.username = :username and u.borrado = 0")
Work fine,Why?
My table,Usuario:
MY USER TABLE
i try with other column as 'superusuario','version_jpa' and doesn't work, the only columns that work fine are 'id,'borrado' and 'username'
Class Usuario:
#Temporal(TemporalType.TIMESTAMP)
private Date fechaCreacion;
#Id
#GeneratedValue (strategy=GenerationType.AUTO)
private int id;
#OneToOne(cascade = CascadeType.ALL)
private Password password;
#OneToMany(cascade = {CascadeType.PERSIST, CascadeType.REFRESH}, fetch = FetchType.LAZY)
private List<Password> clavesAntiguas;
#OneToOne
private Persona persona;
private String sessionId;
private String username;
#ManyToOne(cascade = CascadeType.REFRESH)
private Rol rol;
#ManyToOne(cascade = CascadeType.REFRESH)
private Perfil perfil;
#OneToOne (cascade = CascadeType.ALL)
private IntentosBloqueo intentos;
private boolean superUsuario;
private int borrado;
private int esManager;
#OneToMany ( cascade = {CascadeType.ALL} , fetch = FetchType.LAZY)
private Collection<UsuarioSociedad> sociedades;
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.REFRESH)
#JoinTable (name="USR_UND_VIS",
joinColumns={
#JoinColumn (name="ID_USU", table="USUARIO", referencedColumnName="ID"),
},
inverseJoinColumns=
#JoinColumn (name="ID_UNI", table="UND_ORG", referencedColumnName="ID")
)
private List<UnidadOrganizativa> unidadesVisibles;
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.REFRESH)
#JoinTable (name="USR_UND_DIS",
joinColumns={
#JoinColumn (name="ID_USU", table="USUARIO", referencedColumnName="ID"),
},
inverseJoinColumns=
#JoinColumn (name="ID_UNI", table="UND_ORG", referencedColumnName="ID")
)
private List<UnidadOrganizativa> unidadesDisponibles;
Because Named query works on Entity objetc not on datbase column. You try to find another entity object which contains that id. In That case your named query will give you the object of that entity class and from that object u can get the id or whtever fiels of that entity.
JPA named query is not like SQL or oracle query.
Iin in DB your column name is xyz but in entity your column name is ABC then you have to fetch ABC in named query not XYZ.